Commit 74c938f1 authored by tbarzic@chromium.org's avatar tbarzic@chromium.org

taking over xiyuan's patch: http://codereview.chromium.org/10701087/

***************************************************************
chromeos: Fix pixelated icons in app list and launcher (part 2) 

Add an ExtensionIconImage, which loads image that supports DIP 
by having a special ImageSkiaSource that makes 
ImageLoadingTracker to load image for additional DIP scale. 

BUG=131738, 131739
TEST=None. Wait for the last CL to update laucher/app list code to use LoadImageInDIP to verify.

***************************************************************
For gypi files (I reckon this part is trivial enough)
TBR=ben@chromium.org

Review URL: https://chromiumcodereview.appspot.com/10825012

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@152407 0039d316-1c4b-4281-b951-d872f2087c98
parent 9a499a01
...@@ -113,14 +113,18 @@ void AppShortcutManager::SetShortcutCreationDisabledForTesting(bool disabled) { ...@@ -113,14 +113,18 @@ void AppShortcutManager::SetShortcutCreationDisabledForTesting(bool disabled) {
void AppShortcutManager::InstallApplicationShortcuts( void AppShortcutManager::InstallApplicationShortcuts(
const Extension* extension) { const Extension* extension) {
shortcut_info_ = ShortcutInfoForExtensionAndProfile(extension, profile_); shortcut_info_ = ShortcutInfoForExtensionAndProfile(extension, profile_);
std::vector<ImageLoadingTracker::ImageInfo> info_list;
std::vector<ImageLoadingTracker::ImageRepresentation> info_list;
for (size_t i = 0; i < arraysize(kDesiredSizes); ++i) { for (size_t i = 0; i < arraysize(kDesiredSizes); ++i) {
int size = kDesiredSizes[i]; int size = kDesiredSizes[i];
ExtensionResource resource = extension->GetIconResource( ExtensionResource resource = extension->GetIconResource(
size, ExtensionIconSet::MATCH_EXACTLY); size, ExtensionIconSet::MATCH_EXACTLY);
if (!resource.empty()) { if (!resource.empty()) {
info_list.push_back( info_list.push_back(ImageLoadingTracker::ImageRepresentation(
ImageLoadingTracker::ImageInfo(resource, gfx::Size(size, size))); resource,
ImageLoadingTracker::ImageRepresentation::RESIZE_WHEN_LARGER,
gfx::Size(size, size),
ui::SCALE_FACTOR_100P));
} }
} }
...@@ -137,8 +141,11 @@ void AppShortcutManager::InstallApplicationShortcuts( ...@@ -137,8 +141,11 @@ void AppShortcutManager::InstallApplicationShortcuts(
resource = extension->GetIconResource( resource = extension->GetIconResource(
size, ExtensionIconSet::MATCH_SMALLER); size, ExtensionIconSet::MATCH_SMALLER);
} }
info_list.push_back( info_list.push_back(ImageLoadingTracker::ImageRepresentation(
ImageLoadingTracker::ImageInfo(resource, gfx::Size(size, size))); resource,
ImageLoadingTracker::ImageRepresentation::RESIZE_WHEN_LARGER,
gfx::Size(size, size),
ui::SCALE_FACTOR_100P));
} }
// |icon_resources| may still be empty at this point, in which case LoadImage // |icon_resources| may still be empty at this point, in which case LoadImage
......
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/extensions/extension_icon_image.h"
#include <vector>
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/extensions/extension.h"
#include "content/public/browser/notification_service.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia_source.h"
#include "ui/gfx/size.h"
namespace {
const int kMatchBiggerTreshold = 32;
ExtensionResource GetExtensionIconResource(
const extensions::Extension* extension,
const ExtensionIconSet& icons,
int size,
ExtensionIconSet::MatchType match_type) {
std::string path = icons.Get(size, match_type);
if (path.empty())
return ExtensionResource();
return extension->GetResource(path);
}
} // namespace
namespace extensions {
////////////////////////////////////////////////////////////////////////////////
// ExtensionIconImage::Source
class IconImage::Source : public gfx::ImageSkiaSource {
public:
explicit Source(IconImage* host);
virtual ~Source();
void ResetHost();
private:
// gfx::ImageSkiaSource overrides:
virtual gfx::ImageSkiaRep GetImageForScale(
ui::ScaleFactor scale_factor) OVERRIDE;
IconImage* host_;
DISALLOW_COPY_AND_ASSIGN(Source);
};
IconImage::Source::Source(IconImage* host) : host_(host) {
}
IconImage::Source::~Source() {
}
void IconImage::Source::ResetHost() {
host_ = NULL;
}
gfx::ImageSkiaRep IconImage::Source::GetImageForScale(
ui::ScaleFactor scale_factor) {
if (host_)
host_->LoadImageForScaleFactor(scale_factor);
return gfx::ImageSkiaRep();
}
////////////////////////////////////////////////////////////////////////////////
// ExtensionIconImage
IconImage::IconImage(
const Extension* extension,
const ExtensionIconSet& icon_set,
int resource_size_in_dip,
Observer* observer)
: extension_(extension),
icon_set_(icon_set),
resource_size_in_dip_(resource_size_in_dip),
desired_size_in_dip_(resource_size_in_dip, resource_size_in_dip),
observer_(observer),
source_(NULL),
ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)) {
source_ = new Source(this);
image_skia_ = gfx::ImageSkia(source_, desired_size_in_dip_);
registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
content::NotificationService::AllSources());
}
IconImage::~IconImage() {
// |source_| could be NULL if resource does not exist.
if (source_)
source_->ResetHost();
}
void IconImage::LoadImageForScaleFactor(ui::ScaleFactor scale_factor) {
// Do nothing if extension is unloaded.
if (!extension_)
return;
const float scale = ui::GetScaleFactorScale(scale_factor);
const int resource_size_in_pixel =
static_cast<int>(resource_size_in_dip_ * scale);
ExtensionResource resource;
// We try loading bigger image only if resource size is >= 32.
if (resource_size_in_pixel >= kMatchBiggerTreshold) {
resource = GetExtensionIconResource(extension_, icon_set_,
resource_size_in_pixel, ExtensionIconSet::MATCH_BIGGER);
}
// If resource is not found by now, try matching smaller one.
if (resource.empty()) {
resource = GetExtensionIconResource(extension_, icon_set_,
resource_size_in_pixel, ExtensionIconSet::MATCH_SMALLER);
}
// If there is no resource found, bail out and notify observer of failure.
if (resource.empty()) {
if (observer_)
observer_->OnIconImageLoadFailed(this, scale_factor);
return;
}
int id = tracker_.next_id();
load_map_[id] = scale_factor;
std::vector<ImageLoadingTracker::ImageRepresentation> info_list;
info_list.push_back(ImageLoadingTracker::ImageRepresentation(
resource,
ImageLoadingTracker::ImageRepresentation::RESIZE_WHEN_LARGER,
desired_size_in_dip_.Scale(scale),
scale_factor));
tracker_.LoadImages(extension_, info_list, ImageLoadingTracker::DONT_CACHE);
}
void IconImage::OnImageLoaded(const gfx::Image& image,
const std::string& extension_id,
int index) {
LoadMap::iterator load_map_it = load_map_.find(index);
DCHECK(load_map_it != load_map_.end());
ui::ScaleFactor scale_factor = load_map_it->second;
load_map_.erase(load_map_it);
if (image.IsEmpty()) {
// There waas an error loading the image.
if (observer_)
observer_->OnIconImageLoadFailed(this, scale_factor);
return;
}
DCHECK(image.ToImageSkia()->HasRepresentation(scale_factor));
gfx::ImageSkiaRep rep = image.ToImageSkia()->GetRepresentation(scale_factor);
DCHECK(!rep.is_null());
image_skia_.AddRepresentation(rep);
if (observer_)
observer_->OnExtensionIconImageChanged(this);
}
void IconImage::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
DCHECK_EQ(type, chrome::NOTIFICATION_EXTENSION_UNLOADED);
const Extension* extension =
content::Details<extensions::UnloadedExtensionInfo>(details)->extension;
if (extension_ == extension)
extension_ = NULL;
}
} // namespace extensions
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_ICON_IMAGE_H_
#define CHROME_BROWSER_EXTENSIONS_EXTENSION_ICON_IMAGE_H_
#include <map>
#include <string>
#include "base/basictypes.h"
#include "chrome/browser/extensions/image_loading_tracker.h"
#include "chrome/common/extensions/extension_icon_set.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "ui/gfx/image/image_skia.h"
namespace extensions {
class Extension;
}
namespace gfx {
class Size;
}
namespace extensions {
// A class that provides an ImageSkia for UI code to use. It handles extension
// icon resource loading, screen scale factor change etc. UI code that uses
// extension icon should host this class and be its observer. ExtensionIconImage
// should be outlived by the observer. In painting code, UI code paints with the
// ImageSkia provided by this class. If required extension icon resource is not
// present, this class uses ImageLoadingTracker to load it and call on its
// observer interface when the resource is loaded.
class IconImage : public ImageLoadingTracker::Observer,
public content::NotificationObserver {
public:
class Observer {
public:
// Invoked when a new image rep for an additional scale factor
// is loaded and added to |image|.
virtual void OnExtensionIconImageChanged(IconImage* image) = 0;
// Invoked when the icon image couldn't be loaded.
virtual void OnIconImageLoadFailed(IconImage* image,
ui::ScaleFactor scale_factor) = 0;
protected:
virtual ~Observer() {}
};
IconImage(const Extension* extension,
const ExtensionIconSet& icon_set,
int resource_size_in_dip,
Observer* observer);
virtual ~IconImage();
const gfx::ImageSkia& image_skia() const { return image_skia_; }
private:
class Source;
typedef std::map<int, ui::ScaleFactor> LoadMap;
// Loads bitmap for additional scale factor.
void LoadImageForScaleFactor(ui::ScaleFactor scale_factor);
// ImageLoadingTracker::Observer overrides:
virtual void OnImageLoaded(const gfx::Image& image,
const std::string& extension_id,
int index) OVERRIDE;
// content::NotificationObserver overrides:
virtual void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
const Extension* extension_;
const ExtensionIconSet& icon_set_;
const int resource_size_in_dip_;
const gfx::Size desired_size_in_dip_;
Observer* observer_;
Source* source_; // Owned by ImageSkia storage.
gfx::ImageSkia image_skia_;
ImageLoadingTracker tracker_;
content::NotificationRegistrar registrar_;
LoadMap load_map_;
DISALLOW_COPY_AND_ASSIGN(IconImage);
};
} // namespace extensions
#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_ICON_IMAGE_H_
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/extensions/extension_icon_image.h"
#include "base/json/json_file_value_serializer.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/extensions/extension.h"
#include "content/public/test/test_browser_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
using content::BrowserThread;
using extensions::Extension;
using extensions::IconImage;
namespace {
class ExtensionIconImageTest : public testing::Test,
public IconImage::Observer {
public:
ExtensionIconImageTest()
: image_loaded_count_(0),
image_load_failure_count_(0),
quit_in_image_loaded_(false),
ui_thread_(BrowserThread::UI, &ui_loop_),
file_thread_(BrowserThread::FILE),
io_thread_(BrowserThread::IO) {
}
virtual ~ExtensionIconImageTest() {}
void WaitForImageLoad() {
// ExtensionIconImage may return synchronously, in which case there's
// nothing to wait for.
if (image_loaded_count_ > 0 || image_load_failure_count_ > 0)
return;
quit_in_image_loaded_ = true;
MessageLoop::current()->Run();
quit_in_image_loaded_ = false;
}
int ImageLoadedCount() {
int result = image_loaded_count_;
image_loaded_count_ = 0;
return result;
}
int ImageLoadFailureCount() {
int result = image_load_failure_count_;
image_load_failure_count_ = 0;
return result;
}
scoped_refptr<Extension> CreateExtension(const char* name,
Extension::Location location) {
// Create and load an extension.
FilePath test_file;
if (!PathService::Get(chrome::DIR_TEST_DATA, &test_file)) {
EXPECT_FALSE(true);
return NULL;
}
test_file = test_file.AppendASCII("extensions").AppendASCII(name);
int error_code = 0;
std::string error;
JSONFileValueSerializer serializer(test_file.AppendASCII("app.json"));
scoped_ptr<DictionaryValue> valid_value(
static_cast<DictionaryValue*>(serializer.Deserialize(&error_code,
&error)));
EXPECT_EQ(0, error_code) << error;
if (error_code != 0)
return NULL;
EXPECT_TRUE(valid_value.get());
if (!valid_value.get())
return NULL;
return Extension::Create(test_file, location, *valid_value,
Extension::NO_FLAGS, &error);
}
// testing::Test overrides:
virtual void SetUp() OVERRIDE {
file_thread_.Start();
io_thread_.Start();
}
// IconImage::Delegate overrides:
virtual void OnExtensionIconImageChanged(IconImage* image) OVERRIDE {
image_loaded_count_++;
if (quit_in_image_loaded_)
MessageLoop::current()->Quit();
}
virtual void OnIconImageLoadFailed(IconImage* image,
ui::ScaleFactor scale_factor) OVERRIDE {
image_load_failure_count_++;
if (quit_in_image_loaded_)
MessageLoop::current()->Quit();
}
private:
int image_loaded_count_;
int image_load_failure_count_;
bool quit_in_image_loaded_;
MessageLoop ui_loop_;
content::TestBrowserThread ui_thread_;
content::TestBrowserThread file_thread_;
content::TestBrowserThread io_thread_;
DISALLOW_COPY_AND_ASSIGN(ExtensionIconImageTest);
};
} // namespace
TEST_F(ExtensionIconImageTest, Basic) {
scoped_refptr<Extension> extension(CreateExtension(
"extension_icon_image", Extension::INVALID));
ASSERT_TRUE(extension.get() != NULL);
IconImage image(
extension,
extension->icons(),
extension_misc::EXTENSION_ICON_BITTY,
this);
// No representations in |image_| yet.
gfx::ImageSkia::ImageSkiaReps image_reps = image.image_skia().image_reps();
ASSERT_EQ(0u, image_reps.size());
// Gets representation for a scale factor.
image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
WaitForImageLoad();
EXPECT_EQ(1, ImageLoadedCount());
EXPECT_EQ(0, ImageLoadFailureCount());
// Gets representation for an additional scale factor.
image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P);
WaitForImageLoad();
EXPECT_EQ(1, ImageLoadedCount());
EXPECT_EQ(0, ImageLoadFailureCount());
gfx::ImageSkiaRep image_rep =
image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
EXPECT_EQ(extension_misc::EXTENSION_ICON_BITTY,
image_rep.pixel_width());
image_rep = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P);
EXPECT_EQ(extension_misc::EXTENSION_ICON_SMALL,
image_rep.pixel_width());
}
// If we can't load icon with the exact size, but a bigger resource is
// available.
TEST_F(ExtensionIconImageTest, FallbackToBigger) {
scoped_refptr<Extension> extension(CreateExtension(
"extension_icon_image", Extension::INVALID));
ASSERT_TRUE(extension.get() != NULL);
IconImage image(
extension,
extension->icons(),
extension_misc::EXTENSION_ICON_BITTY,
this);
// Get representation for 2x.
image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P);
WaitForImageLoad();
EXPECT_EQ(1, ImageLoadedCount());
EXPECT_EQ(0, ImageLoadFailureCount());
gfx::ImageSkiaRep image_rep =
image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P);
// We should have found a bigger resource and it should have been resized.
EXPECT_EQ(ui::SCALE_FACTOR_200P, image_rep.scale_factor());
EXPECT_EQ(2 * extension_misc::EXTENSION_ICON_BITTY,
image_rep.pixel_width());
}
// There is no resource with either exact or bigger size, but there is a smaller
// resource.
TEST_F(ExtensionIconImageTest, FallbackToSmallerWhenNoBigger) {
scoped_refptr<Extension> extension(CreateExtension(
"extension_icon_image", Extension::INVALID));
ASSERT_TRUE(extension.get() != NULL);
IconImage image(
extension,
extension->icons(),
extension_misc::EXTENSION_ICON_SMALL,
this);
// Attempt to get representation for 2x.
image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P);
WaitForImageLoad();
EXPECT_EQ(1, ImageLoadedCount());
EXPECT_EQ(0, ImageLoadFailureCount());
gfx::ImageSkiaRep image_rep =
image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P);
// We should have loaded the biggest smaller resource. In this case the
// loaded resource should not be resized.
EXPECT_EQ(ui::SCALE_FACTOR_200P, image_rep.scale_factor());
EXPECT_EQ(extension_misc::EXTENSION_ICON_MEDIUM,
image_rep.pixel_width());
}
// There is no resource with exact size, but there is a smaller and a bigger
// one. Requested size is smaller than 32 though, so the smaller resource should
// be loaded.
TEST_F(ExtensionIconImageTest, FallbackToSmaller) {
scoped_refptr<Extension> extension(CreateExtension(
"extension_icon_image", Extension::INVALID));
ASSERT_TRUE(extension.get() != NULL);
IconImage image(
extension,
extension->icons(),
17,
this);
// Attempt to get representation for 1x.
image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
WaitForImageLoad();
EXPECT_EQ(1, ImageLoadedCount());
EXPECT_EQ(0, ImageLoadFailureCount());
gfx::ImageSkiaRep image_rep =
image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
// We should have loaded smaller (not resized) resource.
EXPECT_EQ(ui::SCALE_FACTOR_100P, image_rep.scale_factor());
EXPECT_EQ(extension_misc::EXTENSION_ICON_BITTY,
image_rep.pixel_width());
}
// If resource set is empty, failure should be reported.
TEST_F(ExtensionIconImageTest, NoResources) {
scoped_refptr<Extension> extension(CreateExtension(
"extension_icon_image", Extension::INVALID));
ASSERT_TRUE(extension.get() != NULL);
ExtensionIconSet empty_icon_set;
IconImage image(
extension,
empty_icon_set,
extension_misc::EXTENSION_ICON_SMALLISH,
this);
// Attempt to get representation for 2x.
image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P);
WaitForImageLoad();
EXPECT_EQ(0, ImageLoadedCount());
EXPECT_EQ(1, ImageLoadFailureCount());
}
...@@ -6,13 +6,18 @@ ...@@ -6,13 +6,18 @@
#define CHROME_BROWSER_EXTENSIONS_IMAGE_LOADING_TRACKER_H_ #define CHROME_BROWSER_EXTENSIONS_IMAGE_LOADING_TRACKER_H_
#include <map> #include <map>
#include <string>
#include <vector>
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/gtest_prod_util.h" #include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "chrome/common/extensions/extension_icon_set.h"
#include "chrome/common/extensions/extension_resource.h" #include "chrome/common/extensions/extension_resource.h"
#include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h" #include "content/public/browser/notification_registrar.h"
#include "ui/base/layout.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/size.h" #include "ui/gfx/size.h"
class SkBitmap; class SkBitmap;
...@@ -35,7 +40,7 @@ class Image; ...@@ -35,7 +40,7 @@ class Image;
// Observer::OnImageLoaded and call: // Observer::OnImageLoaded and call:
// tracker_.LoadImage(extension, resource, max_size, false); // tracker_.LoadImage(extension, resource, max_size, false);
// ... and wait for OnImageLoaded to be called back on you with a pointer to the // ... and wait for OnImageLoaded to be called back on you with a pointer to the
// SkBitmap loaded. // ImageSkia loaded.
// NOTE: if the image is available already (or the resource is not valid), the // NOTE: if the image is available already (or the resource is not valid), the
// Observer is notified immediately from the call to LoadImage. In other words, // Observer is notified immediately from the call to LoadImage. In other words,
// by the time LoadImage returns the observer has been notified. // by the time LoadImage returns the observer has been notified.
...@@ -62,14 +67,33 @@ class ImageLoadingTracker : public content::NotificationObserver { ...@@ -62,14 +67,33 @@ class ImageLoadingTracker : public content::NotificationObserver {
virtual ~Observer(); virtual ~Observer();
}; };
// Information about a single image to load from a extension resource. // Information about a singe image representation to load from an extension
struct ImageInfo { // resource.
ImageInfo(const ExtensionResource& resource, gfx::Size max_size); struct ImageRepresentation {
~ImageInfo(); // Enum values to indicate whether to resize loaded bitmap when it is larger
// than |desired_size| or always resize it.
enum ResizeCondition {
RESIZE_WHEN_LARGER,
ALWAYS_RESIZE,
};
ImageRepresentation(const ExtensionResource& resource,
ResizeCondition resize_method,
const gfx::Size& desired_size,
ui::ScaleFactor scale_factor);
~ImageRepresentation();
// Extension resource to load.
ExtensionResource resource; ExtensionResource resource;
// If the loaded image is larger than |max_size| it will be resized to those
// dimensions. ResizeCondition resize_method;
gfx::Size max_size;
// When |resize_method| is ALWAYS_RESIZE or when the loaded image is larger
// than |desired_size| it will be resized to these dimensions.
gfx::Size desired_size;
// |scale_factor| is used to construct the loaded gfx::ImageSkia.
ui::ScaleFactor scale_factor;
}; };
explicit ImageLoadingTracker(Observer* observer); explicit ImageLoadingTracker(Observer* observer);
...@@ -79,6 +103,8 @@ class ImageLoadingTracker : public content::NotificationObserver { ...@@ -79,6 +103,8 @@ class ImageLoadingTracker : public content::NotificationObserver {
// |max_size| it will be resized to those dimensions. IMPORTANT NOTE: this // |max_size| it will be resized to those dimensions. IMPORTANT NOTE: this
// function may call back your observer synchronously (ie before it returns) // function may call back your observer synchronously (ie before it returns)
// if the image was found in the cache. // if the image was found in the cache.
// Note this method loads a raw bitmap from the resource. All sizes given are
// assumed to be in pixels.
void LoadImage(const extensions::Extension* extension, void LoadImage(const extensions::Extension* extension,
const ExtensionResource& resource, const ExtensionResource& resource,
const gfx::Size& max_size, const gfx::Size& max_size,
...@@ -88,7 +114,7 @@ class ImageLoadingTracker : public content::NotificationObserver { ...@@ -88,7 +114,7 @@ class ImageLoadingTracker : public content::NotificationObserver {
// extension. This is used to load multiple resolutions of the same image // extension. This is used to load multiple resolutions of the same image
// type. // type.
void LoadImages(const extensions::Extension* extension, void LoadImages(const extensions::Extension* extension,
const std::vector<ImageInfo>& info_list, const std::vector<ImageRepresentation>& info_list,
CacheParam cache); CacheParam cache);
// Returns the ID used for the next image that is loaded. That is, the return // Returns the ID used for the next image that is loaded. That is, the return
...@@ -97,18 +123,19 @@ class ImageLoadingTracker : public content::NotificationObserver { ...@@ -97,18 +123,19 @@ class ImageLoadingTracker : public content::NotificationObserver {
int next_id() const { return next_id_; } int next_id() const { return next_id_; }
private: private:
// Information for pending image load operation for one or more images. // Information for pending resource load operation for one or more image
// representations.
struct PendingLoadInfo { struct PendingLoadInfo {
PendingLoadInfo(); PendingLoadInfo();
~PendingLoadInfo(); ~PendingLoadInfo();
const extensions::Extension* extension; const extensions::Extension* extension;
// This is cached separate from |extension| in case the extension in // This is cached separate from |extension| in case the extension is
// unloaded. // unloaded.
std::string extension_id; std::string extension_id;
CacheParam cache; CacheParam cache;
size_t pending_count; size_t pending_count;
std::vector<SkBitmap> bitmaps; gfx::ImageSkia image_skia;
}; };
// Maps an integer identifying a load request to a PendingLoadInfo. // Maps an integer identifying a load request to a PendingLoadInfo.
...@@ -116,14 +143,13 @@ class ImageLoadingTracker : public content::NotificationObserver { ...@@ -116,14 +143,13 @@ class ImageLoadingTracker : public content::NotificationObserver {
class ImageLoader; class ImageLoader;
// When an image has finished loaded and been resized on the file thread, it // Called on the calling thread when the bitmap finishes loading.
// is posted back to this method on the original thread. This method then // |bitmap| may be null if the image file failed to decode.
// calls the observer's OnImageLoaded and deletes the ImageLoadingTracker if void OnBitmapLoaded(const SkBitmap* bitmap,
// it was the last image in the list. The |original_size| should be the size const ImageRepresentation& image_info,
// of the image before any resizing was done. const gfx::Size& original_size,
// |image| may be null if the file failed to decode. int id,
void OnImageLoaded(SkBitmap* image, const ExtensionResource& resource, bool should_cache);
const gfx::Size& original_size, int id, bool should_cache);
// Checks whether image is a component extension resource. Returns false // Checks whether image is a component extension resource. Returns false
// if a given |resource| does not have a corresponding image in bundled // if a given |resource| does not have a corresponding image in bundled
......
...@@ -2,10 +2,11 @@ ...@@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/browser/extensions/image_loading_tracker.h"
#include "base/json/json_file_value_serializer.h" #include "base/json/json_file_value_serializer.h"
#include "base/message_loop.h" #include "base/message_loop.h"
#include "base/path_service.h" #include "base/path_service.h"
#include "chrome/browser/extensions/image_loading_tracker.h"
#include "chrome/common/chrome_notification_types.h" #include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_paths.h"
#include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension.h"
...@@ -198,14 +199,17 @@ TEST_F(ImageLoadingTrackerTest, MultipleImages) { ...@@ -198,14 +199,17 @@ TEST_F(ImageLoadingTrackerTest, MultipleImages) {
"image_loading_tracker", Extension::INVALID)); "image_loading_tracker", Extension::INVALID));
ASSERT_TRUE(extension.get() != NULL); ASSERT_TRUE(extension.get() != NULL);
std::vector<ImageLoadingTracker::ImageInfo> info_list; std::vector<ImageLoadingTracker::ImageRepresentation> info_list;
int sizes[] = {extension_misc::EXTENSION_ICON_SMALLISH, int sizes[] = {extension_misc::EXTENSION_ICON_SMALLISH,
extension_misc::EXTENSION_ICON_BITTY}; extension_misc::EXTENSION_ICON_BITTY};
for (size_t i = 0; i < arraysize(sizes); ++i) { for (size_t i = 0; i < arraysize(sizes); ++i) {
ExtensionResource resource = ExtensionResource resource =
extension->GetIconResource(sizes[i], ExtensionIconSet::MATCH_EXACTLY); extension->GetIconResource(sizes[i], ExtensionIconSet::MATCH_EXACTLY);
info_list.push_back(ImageLoadingTracker::ImageInfo( info_list.push_back(ImageLoadingTracker::ImageRepresentation(
resource, gfx::Size(sizes[i], sizes[i]))); resource,
ImageLoadingTracker::ImageRepresentation::RESIZE_WHEN_LARGER,
gfx::Size(sizes[i], sizes[i]),
ui::SCALE_FACTOR_NONE));
} }
ImageLoadingTracker loader(this); ImageLoadingTracker loader(this);
......
...@@ -366,6 +366,8 @@ ...@@ -366,6 +366,8 @@
'browser/extensions/extension_host.h', 'browser/extensions/extension_host.h',
'browser/extensions/extension_host_mac.h', 'browser/extensions/extension_host_mac.h',
'browser/extensions/extension_host_mac.mm', 'browser/extensions/extension_host_mac.mm',
'browser/extensions/extension_icon_image.cc',
'browser/extensions/extension_icon_image.h',
'browser/extensions/extension_icon_manager.cc', 'browser/extensions/extension_icon_manager.cc',
'browser/extensions/extension_icon_manager.h', 'browser/extensions/extension_icon_manager.h',
'browser/extensions/extension_info_map.cc', 'browser/extensions/extension_info_map.cc',
......
...@@ -1257,6 +1257,7 @@ ...@@ -1257,6 +1257,7 @@
'browser/extensions/extension_creator_filter_unittest.cc', 'browser/extensions/extension_creator_filter_unittest.cc',
'browser/extensions/extension_function_test_utils.cc', 'browser/extensions/extension_function_test_utils.cc',
'browser/extensions/extension_function_test_utils.h', 'browser/extensions/extension_function_test_utils.h',
'browser/extensions/extension_icon_image_unittest.cc',
'browser/extensions/extension_icon_manager_unittest.cc', 'browser/extensions/extension_icon_manager_unittest.cc',
'browser/extensions/extension_info_map_unittest.cc', 'browser/extensions/extension_info_map_unittest.cc',
'browser/extensions/extension_pref_value_map_unittest.cc', 'browser/extensions/extension_pref_value_map_unittest.cc',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment