| OLD | NEW |
| 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/extension_icon_image.h" | 5 #include "chrome/browser/extensions/extension_icon_image.h" |
| 6 | 6 |
| 7 #include "base/json/json_file_value_serializer.h" | 7 #include "base/json/json_file_value_serializer.h" |
| 8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
| 9 #include "base/path_service.h" | 9 #include "base/path_service.h" |
| 10 #include "chrome/browser/extensions/image_loading_tracker.h" |
| 10 #include "chrome/common/chrome_paths.h" | 11 #include "chrome/common/chrome_paths.h" |
| 11 #include "chrome/common/extensions/extension.h" | 12 #include "chrome/common/extensions/extension.h" |
| 13 #include "chrome/common/extensions/extension_constants.h" |
| 12 #include "content/public/test/test_browser_thread.h" | 14 #include "content/public/test/test_browser_thread.h" |
| 15 #include "grit/theme_resources.h" |
| 13 #include "testing/gtest/include/gtest/gtest.h" | 16 #include "testing/gtest/include/gtest/gtest.h" |
| 17 #include "ui/base/resource/resource_bundle.h" |
| 18 #include "ui/gfx/image/image_skia_source.h" |
| 19 #include "ui/gfx/skia_util.h" |
| 14 | 20 |
| 15 using content::BrowserThread; | 21 using content::BrowserThread; |
| 16 using extensions::Extension; | 22 using extensions::Extension; |
| 17 using extensions::IconImage; | 23 using extensions::IconImage; |
| 18 | 24 |
| 19 namespace { | 25 namespace { |
| 20 | 26 |
| 27 SkBitmap CreateBlankBitmapForScale(int size_dip, ui::ScaleFactor scale_factor) { |
| 28 SkBitmap bitmap; |
| 29 const float scale = ui::GetScaleFactorScale(scale_factor); |
| 30 bitmap.setConfig(SkBitmap::kARGB_8888_Config, |
| 31 static_cast<int>(size_dip * scale), |
| 32 static_cast<int>(size_dip * scale)); |
| 33 bitmap.allocPixels(); |
| 34 bitmap.eraseColor(SkColorSetARGB(0, 0, 0, 0)); |
| 35 return bitmap; |
| 36 } |
| 37 |
| 38 // Used to test behaviour including images defined by an image skia source. |
| 39 // |GetImageForScale| simply returns image representation from the image given |
| 40 // in the ctor. |
| 41 class MockImageSkiaSource : public gfx::ImageSkiaSource { |
| 42 public: |
| 43 explicit MockImageSkiaSource(const gfx::ImageSkia& image) |
| 44 : image_(image) { |
| 45 } |
| 46 virtual ~MockImageSkiaSource() {} |
| 47 |
| 48 virtual gfx::ImageSkiaRep GetImageForScale( |
| 49 ui::ScaleFactor scale_factor) OVERRIDE { |
| 50 return image_.GetRepresentation(scale_factor); |
| 51 } |
| 52 |
| 53 private: |
| 54 gfx::ImageSkia image_; |
| 55 }; |
| 56 |
| 57 // Helper class for synchronously loading extension image resource. |
| 58 class TestImageLoader : public ImageLoadingTracker::Observer { |
| 59 public: |
| 60 explicit TestImageLoader(const Extension* extension) |
| 61 : extension_(extension), |
| 62 waiting_(false), |
| 63 image_loaded_(false), |
| 64 ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)) { |
| 65 } |
| 66 virtual ~TestImageLoader() {} |
| 67 |
| 68 // ImageLoadingTracker::Observer override. |
| 69 virtual void OnImageLoaded(const gfx::Image& image, |
| 70 const std::string& extension_id, |
| 71 int index) OVERRIDE { |
| 72 image_ = image; |
| 73 image_loaded_ = true; |
| 74 if (waiting_) |
| 75 MessageLoop::current()->Quit(); |
| 76 } |
| 77 |
| 78 SkBitmap LoadBitmap(const std::string& path, |
| 79 int size, |
| 80 ImageLoadingTracker::CacheParam cache_param) { |
| 81 image_loaded_ = false; |
| 82 |
| 83 tracker_.LoadImage(extension_, |
| 84 extension_->GetResource(path), |
| 85 gfx::Size(size, size), |
| 86 cache_param); |
| 87 |
| 88 // If |image_| still hasn't been loaded (i.e. it is being loaded |
| 89 // asynchronously), wait for it. |
| 90 if (!image_loaded_) { |
| 91 waiting_ = true; |
| 92 MessageLoop::current()->Run(); |
| 93 waiting_ = false; |
| 94 } |
| 95 |
| 96 EXPECT_TRUE(image_loaded_); |
| 97 |
| 98 return image_.IsEmpty() ? SkBitmap() : *image_.ToSkBitmap(); |
| 99 } |
| 100 |
| 101 private: |
| 102 const Extension* extension_; |
| 103 bool waiting_; |
| 104 bool image_loaded_; |
| 105 gfx::Image image_; |
| 106 ImageLoadingTracker tracker_; |
| 107 |
| 108 DISALLOW_COPY_AND_ASSIGN(TestImageLoader); |
| 109 }; |
| 110 |
| 21 class ExtensionIconImageTest : public testing::Test, | 111 class ExtensionIconImageTest : public testing::Test, |
| 22 public IconImage::Observer { | 112 public IconImage::Observer { |
| 23 public: | 113 public: |
| 24 ExtensionIconImageTest() | 114 ExtensionIconImageTest() |
| 25 : image_loaded_count_(0), | 115 : image_loaded_count_(0), |
| 26 image_load_failure_count_(0), | |
| 27 quit_in_image_loaded_(false), | 116 quit_in_image_loaded_(false), |
| 28 ui_thread_(BrowserThread::UI, &ui_loop_), | 117 ui_thread_(BrowserThread::UI, &ui_loop_), |
| 29 file_thread_(BrowserThread::FILE), | 118 file_thread_(BrowserThread::FILE), |
| 30 io_thread_(BrowserThread::IO) { | 119 io_thread_(BrowserThread::IO) { |
| 31 } | 120 } |
| 32 | 121 |
| 33 virtual ~ExtensionIconImageTest() {} | 122 virtual ~ExtensionIconImageTest() {} |
| 34 | 123 |
| 35 void WaitForImageLoad() { | 124 void WaitForImageLoad() { |
| 36 // ExtensionIconImage may return synchronously, in which case there's | |
| 37 // nothing to wait for. | |
| 38 if (image_loaded_count_ > 0 || image_load_failure_count_ > 0) | |
| 39 return; | |
| 40 quit_in_image_loaded_ = true; | 125 quit_in_image_loaded_ = true; |
| 41 MessageLoop::current()->Run(); | 126 MessageLoop::current()->Run(); |
| 42 quit_in_image_loaded_ = false; | 127 quit_in_image_loaded_ = false; |
| 43 } | 128 } |
| 44 | 129 |
| 45 int ImageLoadedCount() { | 130 int ImageLoadedCount() { |
| 46 int result = image_loaded_count_; | 131 int result = image_loaded_count_; |
| 47 image_loaded_count_ = 0; | 132 image_loaded_count_ = 0; |
| 48 return result; | 133 return result; |
| 49 } | 134 } |
| 50 | 135 |
| 51 int ImageLoadFailureCount() { | |
| 52 int result = image_load_failure_count_; | |
| 53 image_load_failure_count_ = 0; | |
| 54 return result; | |
| 55 } | |
| 56 | |
| 57 scoped_refptr<Extension> CreateExtension(const char* name, | 136 scoped_refptr<Extension> CreateExtension(const char* name, |
| 58 Extension::Location location) { | 137 Extension::Location location) { |
| 59 // Create and load an extension. | 138 // Create and load an extension. |
| 60 FilePath test_file; | 139 FilePath test_file; |
| 61 if (!PathService::Get(chrome::DIR_TEST_DATA, &test_file)) { | 140 if (!PathService::Get(chrome::DIR_TEST_DATA, &test_file)) { |
| 62 EXPECT_FALSE(true); | 141 EXPECT_FALSE(true); |
| 63 return NULL; | 142 return NULL; |
| 64 } | 143 } |
| 65 test_file = test_file.AppendASCII("extensions").AppendASCII(name); | 144 test_file = test_file.AppendASCII("extensions").AppendASCII(name); |
| 66 int error_code = 0; | 145 int error_code = 0; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 87 io_thread_.Start(); | 166 io_thread_.Start(); |
| 88 } | 167 } |
| 89 | 168 |
| 90 // IconImage::Delegate overrides: | 169 // IconImage::Delegate overrides: |
| 91 virtual void OnExtensionIconImageChanged(IconImage* image) OVERRIDE { | 170 virtual void OnExtensionIconImageChanged(IconImage* image) OVERRIDE { |
| 92 image_loaded_count_++; | 171 image_loaded_count_++; |
| 93 if (quit_in_image_loaded_) | 172 if (quit_in_image_loaded_) |
| 94 MessageLoop::current()->Quit(); | 173 MessageLoop::current()->Quit(); |
| 95 } | 174 } |
| 96 | 175 |
| 97 virtual void OnIconImageLoadFailed(IconImage* image, | 176 gfx::ImageSkia GetDefaultIcon() { |
| 98 ui::ScaleFactor scale_factor) OVERRIDE { | 177 return *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( |
| 99 image_load_failure_count_++; | 178 IDR_EXTENSIONS_FAVICON); |
| 100 if (quit_in_image_loaded_) | 179 } |
| 101 MessageLoop::current()->Quit(); | 180 |
| 181 // Loads an image to be used in test from the extension. |
| 182 // The image will be loaded from the relative path |path|. |
| 183 SkBitmap GetTestBitmap(const Extension* extension, |
| 184 const std::string& path, |
| 185 int size, |
| 186 ImageLoadingTracker::CacheParam cache_param) { |
| 187 TestImageLoader image_loader(extension); |
| 188 return image_loader.LoadBitmap(path, size, cache_param); |
| 102 } | 189 } |
| 103 | 190 |
| 104 private: | 191 private: |
| 105 int image_loaded_count_; | 192 int image_loaded_count_; |
| 106 int image_load_failure_count_; | |
| 107 bool quit_in_image_loaded_; | 193 bool quit_in_image_loaded_; |
| 108 MessageLoop ui_loop_; | 194 MessageLoop ui_loop_; |
| 109 content::TestBrowserThread ui_thread_; | 195 content::TestBrowserThread ui_thread_; |
| 110 content::TestBrowserThread file_thread_; | 196 content::TestBrowserThread file_thread_; |
| 111 content::TestBrowserThread io_thread_; | 197 content::TestBrowserThread io_thread_; |
| 112 | 198 |
| 113 DISALLOW_COPY_AND_ASSIGN(ExtensionIconImageTest); | 199 DISALLOW_COPY_AND_ASSIGN(ExtensionIconImageTest); |
| 114 }; | 200 }; |
| 115 | 201 |
| 116 } // namespace | 202 } // namespace |
| 117 | 203 |
| 118 TEST_F(ExtensionIconImageTest, Basic) { | 204 TEST_F(ExtensionIconImageTest, Basic) { |
| 119 scoped_refptr<Extension> extension(CreateExtension( | 205 scoped_refptr<Extension> extension(CreateExtension( |
| 120 "extension_icon_image", Extension::INVALID)); | 206 "extension_icon_image", Extension::INVALID)); |
| 121 ASSERT_TRUE(extension.get() != NULL); | 207 ASSERT_TRUE(extension.get() != NULL); |
| 122 | 208 |
| 123 IconImage image( | 209 gfx::ImageSkia default_icon = GetDefaultIcon(); |
| 124 extension, | 210 |
| 125 extension->icons(), | 211 // Load images we expect to find as representations in icon_image, so we |
| 126 extension_misc::EXTENSION_ICON_BITTY, | 212 // can later use them to validate icon_image. |
| 127 this); | 213 SkBitmap bitmap_16 = |
| 214 GetTestBitmap(extension, "16.png", 16, ImageLoadingTracker::DONT_CACHE); |
| 215 ASSERT_FALSE(bitmap_16.empty()); |
| 216 |
| 217 // There is no image of size 32 defined in the extension manifest, so we |
| 218 // should expect manifest image of size 48 resized to size 32. |
| 219 SkBitmap bitmap_48_resized_to_32 = |
| 220 GetTestBitmap(extension, "48.png", 32, ImageLoadingTracker::DONT_CACHE); |
| 221 ASSERT_FALSE(bitmap_48_resized_to_32.empty()); |
| 222 |
| 223 IconImage image(extension, extension->icons(), 16, default_icon, this); |
| 128 | 224 |
| 129 // No representations in |image_| yet. | 225 // No representations in |image_| yet. |
| 130 gfx::ImageSkia::ImageSkiaReps image_reps = image.image_skia().image_reps(); | 226 gfx::ImageSkia::ImageSkiaReps image_reps = image.image_skia().image_reps(); |
| 131 ASSERT_EQ(0u, image_reps.size()); | 227 ASSERT_EQ(0u, image_reps.size()); |
| 132 | 228 |
| 133 // Gets representation for a scale factor. | 229 // Gets representation for a scale factor. |
| 134 image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); | 230 gfx::ImageSkiaRep representation = |
| 135 WaitForImageLoad(); | 231 image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); |
| 136 EXPECT_EQ(1, ImageLoadedCount()); | |
| 137 EXPECT_EQ(0, ImageLoadFailureCount()); | |
| 138 | 232 |
| 139 // Gets representation for an additional scale factor. | 233 // Before the image representation is loaded, image should contain blank |
| 140 image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P); | 234 // image representation. |
| 141 WaitForImageLoad(); | 235 EXPECT_TRUE(gfx::BitmapsAreEqual( |
| 142 EXPECT_EQ(1, ImageLoadedCount()); | 236 representation.sk_bitmap(), |
| 143 EXPECT_EQ(0, ImageLoadFailureCount()); | 237 CreateBlankBitmapForScale(16, ui::SCALE_FACTOR_100P))); |
| 144 | |
| 145 gfx::ImageSkiaRep image_rep = | |
| 146 image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); | |
| 147 EXPECT_EQ(extension_misc::EXTENSION_ICON_BITTY, | |
| 148 image_rep.pixel_width()); | |
| 149 | |
| 150 image_rep = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P); | |
| 151 EXPECT_EQ(extension_misc::EXTENSION_ICON_SMALL, | |
| 152 image_rep.pixel_width()); | |
| 153 } | |
| 154 | |
| 155 // If we can't load icon with the exact size, but a bigger resource is | |
| 156 // available. | |
| 157 TEST_F(ExtensionIconImageTest, FallbackToBigger) { | |
| 158 scoped_refptr<Extension> extension(CreateExtension( | |
| 159 "extension_icon_image", Extension::INVALID)); | |
| 160 ASSERT_TRUE(extension.get() != NULL); | |
| 161 | |
| 162 IconImage image( | |
| 163 extension, | |
| 164 extension->icons(), | |
| 165 extension_misc::EXTENSION_ICON_BITTY, | |
| 166 this); | |
| 167 | |
| 168 // Get representation for 2x. | |
| 169 image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P); | |
| 170 | 238 |
| 171 WaitForImageLoad(); | 239 WaitForImageLoad(); |
| 172 EXPECT_EQ(1, ImageLoadedCount()); | 240 EXPECT_EQ(1, ImageLoadedCount()); |
| 173 EXPECT_EQ(0, ImageLoadFailureCount()); | 241 ASSERT_EQ(1u, image.image_skia().image_reps().size()); |
| 174 | 242 |
| 175 gfx::ImageSkiaRep image_rep = | 243 representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); |
| 176 image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P); | |
| 177 | 244 |
| 178 // We should have found a bigger resource and it should have been resized. | 245 // We should get the right representation now. |
| 179 EXPECT_EQ(ui::SCALE_FACTOR_200P, image_rep.scale_factor()); | 246 EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(), bitmap_16)); |
| 180 EXPECT_EQ(2 * extension_misc::EXTENSION_ICON_BITTY, | 247 EXPECT_EQ(16, representation.pixel_width()); |
| 181 image_rep.pixel_width()); | 248 |
| 249 // Gets representation for an additional scale factor. |
| 250 representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P); |
| 251 |
| 252 EXPECT_TRUE(gfx::BitmapsAreEqual( |
| 253 representation.sk_bitmap(), |
| 254 CreateBlankBitmapForScale(16, ui::SCALE_FACTOR_200P))); |
| 255 |
| 256 WaitForImageLoad(); |
| 257 EXPECT_EQ(1, ImageLoadedCount()); |
| 258 ASSERT_EQ(2u, image.image_skia().image_reps().size()); |
| 259 |
| 260 representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P); |
| 261 |
| 262 // Image should have been resized. |
| 263 EXPECT_EQ(32, representation.pixel_width()); |
| 264 EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(), |
| 265 bitmap_48_resized_to_32)); |
| 182 } | 266 } |
| 183 | 267 |
| 184 // There is no resource with either exact or bigger size, but there is a smaller | 268 // There is no resource with either exact or bigger size, but there is a smaller |
| 185 // resource. | 269 // resource. |
| 186 TEST_F(ExtensionIconImageTest, FallbackToSmallerWhenNoBigger) { | 270 TEST_F(ExtensionIconImageTest, FallbackToSmallerWhenNoBigger) { |
| 187 scoped_refptr<Extension> extension(CreateExtension( | 271 scoped_refptr<Extension> extension(CreateExtension( |
| 188 "extension_icon_image", Extension::INVALID)); | 272 "extension_icon_image", Extension::INVALID)); |
| 189 ASSERT_TRUE(extension.get() != NULL); | 273 ASSERT_TRUE(extension.get() != NULL); |
| 190 | 274 |
| 191 IconImage image( | 275 gfx::ImageSkia default_icon = GetDefaultIcon(); |
| 192 extension, | |
| 193 extension->icons(), | |
| 194 extension_misc::EXTENSION_ICON_SMALL, | |
| 195 this); | |
| 196 | 276 |
| 197 // Attempt to get representation for 2x. | 277 // Load images we expect to find as representations in icon_image, so we |
| 198 image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P); | 278 // can later use them to validate icon_image. |
| 279 SkBitmap bitmap_48 = |
| 280 GetTestBitmap(extension, "48.png", 48, ImageLoadingTracker::DONT_CACHE); |
| 281 ASSERT_FALSE(bitmap_48.empty()); |
| 282 |
| 283 IconImage image(extension, extension->icons(), 32, default_icon, this); |
| 284 |
| 285 gfx::ImageSkiaRep representation = |
| 286 image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P); |
| 199 | 287 |
| 200 WaitForImageLoad(); | 288 WaitForImageLoad(); |
| 201 EXPECT_EQ(1, ImageLoadedCount()); | 289 EXPECT_EQ(1, ImageLoadedCount()); |
| 202 EXPECT_EQ(0, ImageLoadFailureCount()); | 290 ASSERT_EQ(1u, image.image_skia().image_reps().size()); |
| 203 | 291 |
| 204 gfx::ImageSkiaRep image_rep = | 292 representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P); |
| 205 image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P); | |
| 206 | 293 |
| 207 // We should have loaded the biggest smaller resource. In this case the | 294 // We should have loaded the biggest smaller resource. In this case the |
| 208 // loaded resource should not be resized. | 295 // loaded resource should not be resized. |
| 209 EXPECT_EQ(ui::SCALE_FACTOR_200P, image_rep.scale_factor()); | 296 EXPECT_EQ(ui::SCALE_FACTOR_200P, representation.scale_factor()); |
| 210 EXPECT_EQ(extension_misc::EXTENSION_ICON_MEDIUM, | 297 EXPECT_EQ(48, representation.pixel_width()); |
| 211 image_rep.pixel_width()); | 298 EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(), bitmap_48)); |
| 212 } | 299 } |
| 213 | 300 |
| 214 // There is no resource with exact size, but there is a smaller and a bigger | 301 // There is no resource with exact size, but there is a smaller and a bigger |
| 215 // one. Requested size is smaller than 32 though, so the smaller resource should | 302 // one. Requested size is smaller than 32 though, so the smaller resource should |
| 216 // be loaded. | 303 // be loaded. |
| 217 TEST_F(ExtensionIconImageTest, FallbackToSmaller) { | 304 TEST_F(ExtensionIconImageTest, FallbackToSmaller) { |
| 218 scoped_refptr<Extension> extension(CreateExtension( | 305 scoped_refptr<Extension> extension(CreateExtension( |
| 219 "extension_icon_image", Extension::INVALID)); | 306 "extension_icon_image", Extension::INVALID)); |
| 220 ASSERT_TRUE(extension.get() != NULL); | 307 ASSERT_TRUE(extension.get() != NULL); |
| 221 | 308 |
| 222 IconImage image( | 309 gfx::ImageSkia default_icon = GetDefaultIcon(); |
| 223 extension, | 310 |
| 224 extension->icons(), | 311 // Load images we expect to find as representations in icon_image, so we |
| 225 17, | 312 // can later use them to validate icon_image. |
| 226 this); | 313 SkBitmap bitmap_16 = |
| 227 | 314 GetTestBitmap(extension, "16.png", 16, ImageLoadingTracker::DONT_CACHE); |
| 228 // Attempt to get representation for 1x. | 315 ASSERT_FALSE(bitmap_16.empty()); |
| 229 image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); | 316 |
| 230 | 317 IconImage image(extension, extension->icons(), 17, default_icon, this); |
| 231 WaitForImageLoad(); | 318 |
| 232 EXPECT_EQ(1, ImageLoadedCount()); | 319 gfx::ImageSkiaRep representation = |
| 233 EXPECT_EQ(0, ImageLoadFailureCount()); | 320 image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); |
| 234 | 321 |
| 235 gfx::ImageSkiaRep image_rep = | 322 WaitForImageLoad(); |
| 236 image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); | 323 EXPECT_EQ(1, ImageLoadedCount()); |
| 324 ASSERT_EQ(1u, image.image_skia().image_reps().size()); |
| 325 |
| 326 representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); |
| 237 | 327 |
| 238 // We should have loaded smaller (not resized) resource. | 328 // We should have loaded smaller (not resized) resource. |
| 239 EXPECT_EQ(ui::SCALE_FACTOR_100P, image_rep.scale_factor()); | 329 EXPECT_EQ(ui::SCALE_FACTOR_100P, representation.scale_factor()); |
| 240 EXPECT_EQ(extension_misc::EXTENSION_ICON_BITTY, | 330 EXPECT_EQ(16, representation.pixel_width()); |
| 241 image_rep.pixel_width()); | 331 EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(), bitmap_16)); |
| 242 } | 332 } |
| 243 | 333 |
| 244 // If resource set is empty, failure should be reported. | 334 // If resource set is empty, |GetRepresentation| should synchronously return |
| 335 // default icon, without notifying observer of image change. |
| 245 TEST_F(ExtensionIconImageTest, NoResources) { | 336 TEST_F(ExtensionIconImageTest, NoResources) { |
| 246 scoped_refptr<Extension> extension(CreateExtension( | 337 scoped_refptr<Extension> extension(CreateExtension( |
| 247 "extension_icon_image", Extension::INVALID)); | 338 "extension_icon_image", Extension::INVALID)); |
| 248 ASSERT_TRUE(extension.get() != NULL); | 339 ASSERT_TRUE(extension.get() != NULL); |
| 249 | 340 |
| 250 ExtensionIconSet empty_icon_set; | 341 ExtensionIconSet empty_icon_set; |
| 251 | 342 gfx::ImageSkia default_icon = GetDefaultIcon(); |
| 252 IconImage image( | 343 |
| 253 extension, | 344 IconImage image(extension, empty_icon_set, 24, default_icon, this); |
| 254 empty_icon_set, | 345 |
| 255 extension_misc::EXTENSION_ICON_SMALLISH, | 346 gfx::ImageSkiaRep representation = |
| 256 this); | 347 image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); |
| 257 | 348 EXPECT_TRUE(gfx::BitmapsAreEqual( |
| 258 // Attempt to get representation for 2x. | 349 representation.sk_bitmap(), |
| 259 image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P); | 350 default_icon.GetRepresentation(ui::SCALE_FACTOR_100P).sk_bitmap())); |
| 260 | 351 |
| 261 WaitForImageLoad(); | |
| 262 EXPECT_EQ(0, ImageLoadedCount()); | 352 EXPECT_EQ(0, ImageLoadedCount()); |
| 263 EXPECT_EQ(1, ImageLoadFailureCount()); | 353 // We should have a default icon representation. |
| 264 } | 354 ASSERT_EQ(1u, image.image_skia().image_reps().size()); |
| 355 |
| 356 representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); |
| 357 EXPECT_TRUE(gfx::BitmapsAreEqual( |
| 358 representation.sk_bitmap(), |
| 359 default_icon.GetRepresentation(ui::SCALE_FACTOR_100P).sk_bitmap())); |
| 360 } |
| 361 |
| 362 // If resource set is invalid, image load should be done asynchronously and |
| 363 // the observer should be notified when it's done. |GetRepresentation| should |
| 364 // return the default icon representation once image load is done. |
| 365 TEST_F(ExtensionIconImageTest, InvalidResource) { |
| 366 scoped_refptr<Extension> extension(CreateExtension( |
| 367 "extension_icon_image", Extension::INVALID)); |
| 368 ASSERT_TRUE(extension.get() != NULL); |
| 369 |
| 370 ExtensionIconSet invalid_icon_set; |
| 371 invalid_icon_set.Add(24, "invalid.png"); |
| 372 |
| 373 gfx::ImageSkia default_icon = GetDefaultIcon(); |
| 374 |
| 375 IconImage image(extension, invalid_icon_set, 24, default_icon, this); |
| 376 |
| 377 gfx::ImageSkiaRep representation = |
| 378 image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); |
| 379 EXPECT_TRUE(gfx::BitmapsAreEqual( |
| 380 representation.sk_bitmap(), |
| 381 CreateBlankBitmapForScale(24, ui::SCALE_FACTOR_100P))); |
| 382 |
| 383 WaitForImageLoad(); |
| 384 EXPECT_EQ(1, ImageLoadedCount()); |
| 385 // We should have default icon representation now. |
| 386 ASSERT_EQ(1u, image.image_skia().image_reps().size()); |
| 387 |
| 388 representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); |
| 389 EXPECT_TRUE(gfx::BitmapsAreEqual( |
| 390 representation.sk_bitmap(), |
| 391 default_icon.GetRepresentation(ui::SCALE_FACTOR_100P).sk_bitmap())); |
| 392 } |
| 393 |
| 394 // Test that IconImage works with lazily (but synchronously) created default |
| 395 // icon when IconImage returns synchronously. |
| 396 TEST_F(ExtensionIconImageTest, LazyDefaultIcon) { |
| 397 scoped_refptr<Extension> extension(CreateExtension( |
| 398 "extension_icon_image", Extension::INVALID)); |
| 399 ASSERT_TRUE(extension.get() != NULL); |
| 400 |
| 401 gfx::ImageSkia default_icon = GetDefaultIcon(); |
| 402 gfx::ImageSkia lazy_default_icon(new MockImageSkiaSource(default_icon), |
| 403 default_icon.size()); |
| 404 |
| 405 ExtensionIconSet empty_icon_set; |
| 406 |
| 407 IconImage image(extension, empty_icon_set, 128, lazy_default_icon, this); |
| 408 |
| 409 ASSERT_FALSE(lazy_default_icon.HasRepresentation(ui::SCALE_FACTOR_100P)); |
| 410 |
| 411 gfx::ImageSkiaRep representation = |
| 412 image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); |
| 413 |
| 414 // The resouce set is empty, so we should get the result right away. |
| 415 EXPECT_TRUE(lazy_default_icon.HasRepresentation(ui::SCALE_FACTOR_100P)); |
| 416 EXPECT_TRUE(gfx::BitmapsAreEqual( |
| 417 representation.sk_bitmap(), |
| 418 default_icon.GetRepresentation(ui::SCALE_FACTOR_100P).sk_bitmap())); |
| 419 |
| 420 // We should have a default icon representation. |
| 421 ASSERT_EQ(1u, image.image_skia().image_reps().size()); |
| 422 } |
| 423 |
| 424 // Test that IconImage works with lazily (but synchronously) created default |
| 425 // icon when IconImage returns asynchronously. |
| 426 TEST_F(ExtensionIconImageTest, LazyDefaultIcon_AsyncIconImage) { |
| 427 scoped_refptr<Extension> extension(CreateExtension( |
| 428 "extension_icon_image", Extension::INVALID)); |
| 429 ASSERT_TRUE(extension.get() != NULL); |
| 430 |
| 431 gfx::ImageSkia default_icon = GetDefaultIcon(); |
| 432 gfx::ImageSkia lazy_default_icon(new MockImageSkiaSource(default_icon), |
| 433 default_icon.size()); |
| 434 |
| 435 ExtensionIconSet invalid_icon_set; |
| 436 invalid_icon_set.Add(24, "invalid.png"); |
| 437 |
| 438 IconImage image(extension, invalid_icon_set, 24, lazy_default_icon, this); |
| 439 |
| 440 ASSERT_FALSE(lazy_default_icon.HasRepresentation(ui::SCALE_FACTOR_100P)); |
| 441 |
| 442 gfx::ImageSkiaRep representation = |
| 443 image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); |
| 444 |
| 445 WaitForImageLoad(); |
| 446 EXPECT_EQ(1, ImageLoadedCount()); |
| 447 // We should have default icon representation now. |
| 448 ASSERT_EQ(1u, image.image_skia().image_reps().size()); |
| 449 |
| 450 EXPECT_TRUE(lazy_default_icon.HasRepresentation(ui::SCALE_FACTOR_100P)); |
| 451 |
| 452 representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); |
| 453 EXPECT_TRUE(gfx::BitmapsAreEqual( |
| 454 representation.sk_bitmap(), |
| 455 default_icon.GetRepresentation(ui::SCALE_FACTOR_100P).sk_bitmap())); |
| 456 } |
| 457 |
| 458 TEST_F(ExtensionIconImageTest, LoadPrecachedImage) { |
| 459 scoped_refptr<Extension> extension(CreateExtension( |
| 460 "extension_icon_image", Extension::INVALID)); |
| 461 ASSERT_TRUE(extension.get() != NULL); |
| 462 |
| 463 gfx::ImageSkia default_icon = GetDefaultIcon(); |
| 464 |
| 465 // Note the cache parameter. |
| 466 SkBitmap bitmap_16 = |
| 467 GetTestBitmap(extension, "16.png", 16, ImageLoadingTracker::CACHE); |
| 468 ASSERT_FALSE(bitmap_16.empty()); |
| 469 |
| 470 IconImage image(extension, extension->icons(), 16, default_icon, this); |
| 471 |
| 472 // No representations in |image_| yet. |
| 473 gfx::ImageSkia::ImageSkiaReps image_reps = image.image_skia().image_reps(); |
| 474 ASSERT_EQ(0u, image_reps.size()); |
| 475 |
| 476 // Gets representation for a scale factor. |
| 477 // Since the icon representation is precached, it should be returned right |
| 478 // away. Also, we should not receive any notifications. |
| 479 gfx::ImageSkiaRep representation = |
| 480 image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); |
| 481 EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(), bitmap_16)); |
| 482 |
| 483 EXPECT_EQ(0, ImageLoadedCount()); |
| 484 ASSERT_EQ(1u, image.image_skia().image_reps().size()); |
| 485 } |
| 486 |
| 487 // Tests behaviour of image created by IconImage after IconImage host goes |
| 488 // away. The image should still return loaded representations. If requested |
| 489 // representation was not loaded while IconImage host was around, transparent |
| 490 // representations should be returned. |
| 491 TEST_F(ExtensionIconImageTest, IconImageDestruction) { |
| 492 scoped_refptr<Extension> extension(CreateExtension( |
| 493 "extension_icon_image", Extension::INVALID)); |
| 494 ASSERT_TRUE(extension.get() != NULL); |
| 495 |
| 496 gfx::ImageSkia default_icon = GetDefaultIcon(); |
| 497 |
| 498 // Load images we expect to find as representations in icon_image, so we |
| 499 // can later use them to validate icon_image. |
| 500 SkBitmap bitmap_16 = |
| 501 GetTestBitmap(extension, "16.png", 16, ImageLoadingTracker::DONT_CACHE); |
| 502 ASSERT_FALSE(bitmap_16.empty()); |
| 503 |
| 504 scoped_ptr<IconImage> image( |
| 505 new IconImage(extension, extension->icons(), 16, default_icon, this)); |
| 506 |
| 507 // Load an image representation. |
| 508 gfx::ImageSkiaRep representation = |
| 509 image->image_skia().GetRepresentation(ui::SCALE_FACTOR_100P); |
| 510 |
| 511 WaitForImageLoad(); |
| 512 EXPECT_EQ(1, ImageLoadedCount()); |
| 513 ASSERT_EQ(1u, image->image_skia().image_reps().size()); |
| 514 |
| 515 // Stash loaded image skia, and destroy |image|. |
| 516 gfx::ImageSkia image_skia = image->image_skia(); |
| 517 image.reset(); |
| 518 extension = NULL; |
| 519 |
| 520 // Image skia should still be able to get previously loaded representation. |
| 521 representation = image_skia.GetRepresentation(ui::SCALE_FACTOR_100P); |
| 522 |
| 523 EXPECT_EQ(ui::SCALE_FACTOR_100P, representation.scale_factor()); |
| 524 EXPECT_EQ(16, representation.pixel_width()); |
| 525 EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(), bitmap_16)); |
| 526 |
| 527 // When requesting another representation, we should get blank image. |
| 528 representation = image_skia.GetRepresentation(ui::SCALE_FACTOR_200P); |
| 529 |
| 530 EXPECT_TRUE(gfx::BitmapsAreEqual( |
| 531 representation.sk_bitmap(), |
| 532 CreateBlankBitmapForScale(16, ui::SCALE_FACTOR_200P))); |
| 533 } |
| OLD | NEW |