Chromium Code Reviews| Index: chrome/browser/extensions/extension_icon_image_unittest.cc |
| diff --git a/chrome/browser/extensions/extension_icon_image_unittest.cc b/chrome/browser/extensions/extension_icon_image_unittest.cc |
| index 5693396b02e9423ee648e9eed248cbd492134dac..2239f20d6acb19450ab61b91e5c4e441374468ec 100644 |
| --- a/chrome/browser/extensions/extension_icon_image_unittest.cc |
| +++ b/chrome/browser/extensions/extension_icon_image_unittest.cc |
| @@ -7,9 +7,14 @@ |
| #include "base/json/json_file_value_serializer.h" |
| #include "base/message_loop.h" |
| #include "base/path_service.h" |
| +#include "chrome/browser/extensions/image_loading_tracker.h" |
| #include "chrome/common/chrome_paths.h" |
| #include "chrome/common/extensions/extension.h" |
| +#include "chrome/common/extensions/extension_constants.h" |
| #include "content/public/test/test_browser_thread.h" |
| +#include "grit/theme_resources.h" |
| +#include "ui/base/resource/resource_bundle.h" |
| +#include "ui/gfx/skia_util.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| using content::BrowserThread; |
| @@ -18,12 +23,82 @@ using extensions::IconImage; |
| namespace { |
| +bool ImageRepsAreEqual(const gfx::ImageSkiaRep& image_rep1, |
| + const gfx::ImageSkiaRep& image_rep2) { |
| + return gfx::BitmapsAreEqual(image_rep1.sk_bitmap(), image_rep2.sk_bitmap()); |
| +} |
| + |
| +gfx::ImageSkiaRep CreateBlankRep(int size_dip, ui::ScaleFactor scale_factor) { |
| + SkBitmap bitmap; |
| + const float scale = ui::GetScaleFactorScale(scale_factor); |
| + bitmap.setConfig(SkBitmap::kARGB_8888_Config, |
| + static_cast<int>(size_dip * scale), |
| + static_cast<int>(size_dip * scale)); |
| + bitmap.allocPixels(); |
| + bitmap.eraseColor(SkColorSetARGB(0, 0, 0, 0)); |
| + return gfx::ImageSkiaRep(bitmap, scale_factor); |
| +} |
| + |
| +// Helper class for synchronously loading extension image resource. |
| +class TestImageLoader : public ImageLoadingTracker::Observer { |
| + public: |
| + explicit TestImageLoader(const Extension* extension) |
| + : extension_(extension), |
| + waiting_(false), |
| + image_loaded_(false), |
| + ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)) { |
| + } |
| + virtual ~TestImageLoader() {} |
| + |
| + // ImageLoadingTracker::Observer override. |
| + virtual void OnImageLoaded(const gfx::Image& image, |
| + const std::string& extension_id, |
| + int index) OVERRIDE { |
| + image_ = image; |
| + image_loaded_ = true; |
| + if (waiting_) |
| + MessageLoop::current()->Quit(); |
| + } |
| + |
| + gfx::ImageSkia LoadImage(const std::string& path, int size, bool cache) { |
| + image_loaded_ = false; |
| + |
| + ImageLoadingTracker::CacheParam cache_param = |
| + cache ? ImageLoadingTracker::CACHE : ImageLoadingTracker::DONT_CACHE; |
| + |
| + tracker_.LoadImage(extension_, |
| + extension_->GetResource(path), |
| + gfx::Size(size, size), |
| + cache_param); |
| + |
| + // If |image_| still hasn't been loaded (i.e. it is being loaded |
| + // asynchronously), wait for it. |
| + if (!image_loaded_) { |
| + waiting_ = true; |
| + MessageLoop::current()->Run(); |
| + waiting_ = false; |
| + } |
| + |
| + EXPECT_TRUE(image_loaded_); |
| + |
| + return image_.IsEmpty() ? gfx::ImageSkia() : *image_.ToImageSkia(); |
| + } |
| + |
| + private: |
| + const Extension* extension_; |
| + bool waiting_; |
| + bool image_loaded_; |
| + gfx::Image image_; |
| + ImageLoadingTracker tracker_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(TestImageLoader); |
| +}; |
| + |
| 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), |
| @@ -33,10 +108,6 @@ class ExtensionIconImageTest : public testing::Test, |
| 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; |
| @@ -48,12 +119,6 @@ class ExtensionIconImageTest : public testing::Test, |
| 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. |
| @@ -94,16 +159,13 @@ class ExtensionIconImageTest : public testing::Test, |
| 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(); |
| + gfx::ImageSkia GetDefaultIcon() { |
| + return *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( |
| + IDR_EXTENSIONS_FAVICON); |
| } |
| private: |
| int image_loaded_count_; |
| - int image_load_failure_count_; |
| bool quit_in_image_loaded_; |
| MessageLoop ui_loop_; |
| content::TestBrowserThread ui_thread_; |
| @@ -120,36 +182,76 @@ TEST_F(ExtensionIconImageTest, Basic) { |
| "extension_icon_image", Extension::INVALID)); |
| ASSERT_TRUE(extension.get() != NULL); |
| - IconImage image( |
| - extension, |
| - extension->icons(), |
| - extension_misc::EXTENSION_ICON_BITTY, |
| - this); |
| + gfx::ImageSkia default_icon = GetDefaultIcon(); |
| + |
| + // Load images we expect to find as representations in icon_image, so we |
| + // can later use them to validate icon_image. |
| + TestImageLoader test_image_loader(extension.get()); |
| + gfx::ImageSkia bitty_image = |
| + test_image_loader.LoadImage("16.png", |
| + extension_misc::EXTENSION_ICON_BITTY, |
| + false); |
| + ASSERT_TRUE(bitty_image.HasRepresentation(ui::SCALE_FACTOR_100P)); |
| + |
| + // There is no image of size 32 defined in the extension manifest, so we |
| + // should expect manifest image of size 48 resized to size 32. |
| + gfx::ImageSkia small_image = |
| + test_image_loader.LoadImage("48.png", |
| + 2 * extension_misc::EXTENSION_ICON_BITTY, |
| + false); |
| + ASSERT_TRUE(small_image.HasRepresentation(ui::SCALE_FACTOR_100P)); |
| + |
| + IconImage image(extension, |
| + extension->icons(), |
| + extension_misc::EXTENSION_ICON_BITTY, |
| + default_icon, |
| + 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); |
| + gfx::ImageSkiaRep representation = |
| + image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); |
| + // Before it the image representation is loaded, image should contain default |
|
pkotwicz
2012/08/28 18:56:57
Nit: Before the image representation is loaded, im
tbarzic
2012/08/29 18:41:28
Done.
|
| + // image representation. |
| + EXPECT_TRUE(ImageRepsAreEqual( |
| + representation, |
| + CreateBlankRep(extension_misc::EXTENSION_ICON_BITTY, |
| + ui::SCALE_FACTOR_100P))); |
| + |
| WaitForImageLoad(); |
| EXPECT_EQ(1, ImageLoadedCount()); |
| - EXPECT_EQ(0, ImageLoadFailureCount()); |
| + ASSERT_EQ(1u, image.image_skia().image_reps().size()); |
| + |
| + representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); |
| + // We should get the right representation now. |
| + EXPECT_TRUE(ImageRepsAreEqual( |
| + representation, |
| + bitty_image.GetRepresentation(ui::SCALE_FACTOR_100P))); |
| + EXPECT_EQ(extension_misc::EXTENSION_ICON_BITTY, |
| + representation.pixel_width()); |
| // Gets representation for an additional scale factor. |
| - image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P); |
| + representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P); |
| + |
| + EXPECT_TRUE(ImageRepsAreEqual( |
| + representation, |
| + CreateBlankRep(extension_misc::EXTENSION_ICON_BITTY, |
| + 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()); |
| + ASSERT_EQ(2u, image.image_skia().image_reps().size()); |
| - image_rep = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P); |
| + representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P); |
| + EXPECT_TRUE(ImageRepsAreEqual( |
| + representation, |
| + small_image.GetRepresentation(ui::SCALE_FACTOR_100P))); |
| + // Image should have been resized. |
| EXPECT_EQ(extension_misc::EXTENSION_ICON_SMALL, |
| - image_rep.pixel_width()); |
| + representation.pixel_width()); |
| } |
| // If we can't load icon with the exact size, but a bigger resource is |
| @@ -159,26 +261,40 @@ TEST_F(ExtensionIconImageTest, FallbackToBigger) { |
| "extension_icon_image", Extension::INVALID)); |
| ASSERT_TRUE(extension.get() != NULL); |
| - IconImage image( |
| - extension, |
| - extension->icons(), |
| - extension_misc::EXTENSION_ICON_BITTY, |
| - this); |
| + gfx::ImageSkia default_icon = GetDefaultIcon(); |
| + |
| + // Load images we expect to find as representations in icon_image, so we |
| + // can later use them to validate icon_image. |
| + TestImageLoader test_image_loader(extension.get()); |
| + gfx::ImageSkia small_image = |
| + test_image_loader.LoadImage("48.png", |
| + 2 * extension_misc::EXTENSION_ICON_BITTY, |
| + false); |
| + ASSERT_TRUE(small_image.HasRepresentation(ui::SCALE_FACTOR_100P)); |
| + |
| + IconImage image(extension, |
| + extension->icons(), |
| + extension_misc::EXTENSION_ICON_BITTY, |
| + default_icon, |
| + this); |
| // Get representation for 2x. |
| - image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P); |
| + gfx::ImageSkiaRep representation = |
| + image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P); |
| WaitForImageLoad(); |
| EXPECT_EQ(1, ImageLoadedCount()); |
| - EXPECT_EQ(0, ImageLoadFailureCount()); |
| + ASSERT_EQ(1u, image.image_skia().image_reps().size()); |
| - gfx::ImageSkiaRep image_rep = |
| - image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P); |
| + representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P); |
| + EXPECT_TRUE(ImageRepsAreEqual( |
| + representation, |
| + small_image.GetRepresentation(ui::SCALE_FACTOR_100P))); |
| // 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(ui::SCALE_FACTOR_200P, representation.scale_factor()); |
| EXPECT_EQ(2 * extension_misc::EXTENSION_ICON_BITTY, |
| - image_rep.pixel_width()); |
| + representation.pixel_width()); |
| } |
| // There is no resource with either exact or bigger size, but there is a smaller |
| @@ -188,27 +304,42 @@ TEST_F(ExtensionIconImageTest, FallbackToSmallerWhenNoBigger) { |
| "extension_icon_image", Extension::INVALID)); |
| ASSERT_TRUE(extension.get() != NULL); |
| - IconImage image( |
| - extension, |
| - extension->icons(), |
| - extension_misc::EXTENSION_ICON_SMALL, |
| - this); |
| + gfx::ImageSkia default_icon = GetDefaultIcon(); |
| + |
| + // Load images we expect to find as representations in icon_image, so we |
| + // can later use them to validate icon_image. |
| + // The image should not be resized. |
| + TestImageLoader test_image_loader(extension.get()); |
| + gfx::ImageSkia expected_image = |
| + test_image_loader.LoadImage("48.png", |
| + extension_misc::EXTENSION_ICON_MEDIUM, |
| + false); |
| + ASSERT_TRUE(expected_image.HasRepresentation(ui::SCALE_FACTOR_100P)); |
| + |
| + IconImage image(extension, |
| + extension->icons(), |
| + extension_misc::EXTENSION_ICON_SMALL, |
| + default_icon, |
| + this); |
| // Attempt to get representation for 2x. |
| - image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P); |
| + gfx::ImageSkiaRep representation = |
| + image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P); |
| WaitForImageLoad(); |
| EXPECT_EQ(1, ImageLoadedCount()); |
| - EXPECT_EQ(0, ImageLoadFailureCount()); |
| + ASSERT_EQ(1u, image.image_skia().image_reps().size()); |
| - gfx::ImageSkiaRep image_rep = |
| - image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P); |
| + representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P); |
| + EXPECT_TRUE(ImageRepsAreEqual( |
| + representation, |
| + expected_image.GetRepresentation(ui::SCALE_FACTOR_100P))); |
| // 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(ui::SCALE_FACTOR_200P, representation.scale_factor()); |
| EXPECT_EQ(extension_misc::EXTENSION_ICON_MEDIUM, |
| - image_rep.pixel_width()); |
| + representation.pixel_width()); |
| } |
| // There is no resource with exact size, but there is a smaller and a bigger |
| @@ -219,26 +350,36 @@ TEST_F(ExtensionIconImageTest, FallbackToSmaller) { |
| "extension_icon_image", Extension::INVALID)); |
| ASSERT_TRUE(extension.get() != NULL); |
| - IconImage image( |
| - extension, |
| - extension->icons(), |
| - 17, |
| - this); |
| + gfx::ImageSkia default_icon = GetDefaultIcon(); |
| + |
| + // Load images we expect to find as representations in icon_image, so we |
| + // can later use them to validate icon_image. |
| + TestImageLoader test_image_loader(extension.get()); |
| + gfx::ImageSkia expected_image = |
| + test_image_loader.LoadImage("16.png", |
| + extension_misc::EXTENSION_ICON_BITTY, |
| + false); |
| + ASSERT_TRUE(expected_image.HasRepresentation(ui::SCALE_FACTOR_100P)); |
| + |
| + IconImage image(extension, extension->icons(), 17, default_icon, this); |
| // Attempt to get representation for 1x. |
| - image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); |
| + gfx::ImageSkiaRep representation = |
| + image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); |
| WaitForImageLoad(); |
| EXPECT_EQ(1, ImageLoadedCount()); |
| - EXPECT_EQ(0, ImageLoadFailureCount()); |
| + ASSERT_EQ(1u, image.image_skia().image_reps().size()); |
| - gfx::ImageSkiaRep image_rep = |
| - image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); |
| + representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); |
| + EXPECT_TRUE(ImageRepsAreEqual( |
| + representation, |
| + expected_image.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(ui::SCALE_FACTOR_100P, representation.scale_factor()); |
| EXPECT_EQ(extension_misc::EXTENSION_ICON_BITTY, |
| - image_rep.pixel_width()); |
| + representation.pixel_width()); |
| } |
| // If resource set is empty, failure should be reported. |
| @@ -248,17 +389,100 @@ TEST_F(ExtensionIconImageTest, NoResources) { |
| ASSERT_TRUE(extension.get() != NULL); |
| ExtensionIconSet empty_icon_set; |
| + gfx::ImageSkia default_icon = GetDefaultIcon(); |
| + |
| + IconImage image(extension, |
| + empty_icon_set, |
| + extension_misc::EXTENSION_ICON_SMALLISH, |
| + default_icon, |
| + this); |
| + |
| + // Attempt to get representation for 2x. |
| + gfx::ImageSkiaRep representation = |
| + image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); |
| + EXPECT_TRUE(ImageRepsAreEqual( |
| + representation, |
| + default_icon.GetRepresentation(ui::SCALE_FACTOR_100P))); |
| + |
| + EXPECT_EQ(0, ImageLoadedCount()); |
| + // We should still have default icon representation. |
| + ASSERT_EQ(1u, image.image_skia().image_reps().size()); |
| + |
| + representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); |
| + EXPECT_TRUE(ImageRepsAreEqual( |
| + representation, |
| + default_icon.GetRepresentation(ui::SCALE_FACTOR_100P))); |
| +} |
| + |
| +// If resource set is empty, failure should be reported. |
| +TEST_F(ExtensionIconImageTest, InvalidResource) { |
| + scoped_refptr<Extension> extension(CreateExtension( |
| + "extension_icon_image", Extension::INVALID)); |
| + ASSERT_TRUE(extension.get() != NULL); |
| - IconImage image( |
| - extension, |
| - empty_icon_set, |
| - extension_misc::EXTENSION_ICON_SMALLISH, |
| - this); |
| + ExtensionIconSet invalid_icon_set; |
| + invalid_icon_set.Add(extension_misc::EXTENSION_ICON_SMALLISH, "invalid.png"); |
| + gfx::ImageSkia default_icon = GetDefaultIcon(); |
| + |
| + IconImage image(extension, |
| + invalid_icon_set, |
| + extension_misc::EXTENSION_ICON_SMALLISH, |
| + default_icon, |
| + this); |
| // Attempt to get representation for 2x. |
| - image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P); |
| + gfx::ImageSkiaRep representation = |
| + image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); |
| + EXPECT_TRUE(ImageRepsAreEqual( |
| + representation, |
| + CreateBlankRep(extension_misc::EXTENSION_ICON_SMALLISH, |
| + ui::SCALE_FACTOR_100P))); |
| WaitForImageLoad(); |
| + EXPECT_EQ(1, ImageLoadedCount()); |
| + // We should still have default icon representation. |
| + ASSERT_EQ(1u, image.image_skia().image_reps().size()); |
| + |
| + representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); |
| + EXPECT_TRUE(ImageRepsAreEqual( |
| + representation, |
| + default_icon.GetRepresentation(ui::SCALE_FACTOR_100P))); |
| +} |
| + |
| +TEST_F(ExtensionIconImageTest, LoadPrecachedImage) { |
| + scoped_refptr<Extension> extension(CreateExtension( |
| + "extension_icon_image", Extension::INVALID)); |
| + ASSERT_TRUE(extension.get() != NULL); |
| + |
| + gfx::ImageSkia default_icon = GetDefaultIcon(); |
| + |
| + TestImageLoader test_image_loader(extension.get()); |
| + // Load image and cache it. |
| + gfx::ImageSkia bitty_image = |
| + test_image_loader.LoadImage("16.png", |
| + extension_misc::EXTENSION_ICON_BITTY, |
| + true); |
| + ASSERT_TRUE(bitty_image.HasRepresentation(ui::SCALE_FACTOR_100P)); |
| + |
| + IconImage image(extension, |
| + extension->icons(), |
| + extension_misc::EXTENSION_ICON_BITTY, |
| + default_icon, |
| + 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. |
| + // Since the icon representation is precached, it should be returned right |
| + // away. Also, we should not received any notifications. |
| + gfx::ImageSkiaRep representation = |
| + image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); |
| + EXPECT_TRUE(ImageRepsAreEqual( |
| + representation, |
| + bitty_image.GetRepresentation(ui::SCALE_FACTOR_100P))); |
| + |
| EXPECT_EQ(0, ImageLoadedCount()); |
| - EXPECT_EQ(1, ImageLoadFailureCount()); |
| + ASSERT_EQ(1u, image.image_skia().image_reps().size()); |
| } |