| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "extensions/browser/extension_icon_image.h" | 5 #include "extensions/browser/extension_icon_image.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/json/json_file_value_serializer.h" | 9 #include "base/json/json_file_value_serializer.h" |
| 10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
| 11 #include "base/path_service.h" | 11 #include "base/path_service.h" |
| 12 #include "content/public/browser/notification_service.h" | 12 #include "content/public/browser/notification_service.h" |
| 13 #include "content/public/test/test_browser_context.h" | 13 #include "content/public/test/test_browser_context.h" |
| 14 #include "content/public/test/test_browser_thread.h" | 14 #include "content/public/test/test_browser_thread.h" |
| 15 #include "extensions/browser/extensions_test.h" | 15 #include "extensions/browser/extensions_test.h" |
| 16 #include "extensions/browser/image_loader.h" | 16 #include "extensions/browser/image_loader.h" |
| 17 #include "extensions/browser/test_image_loader.h" |
| 17 #include "extensions/common/extension.h" | 18 #include "extensions/common/extension.h" |
| 18 #include "extensions/common/extension_paths.h" | 19 #include "extensions/common/extension_paths.h" |
| 19 #include "extensions/common/manifest.h" | 20 #include "extensions/common/manifest.h" |
| 20 #include "extensions/common/manifest_handlers/icons_handler.h" | 21 #include "extensions/common/manifest_handlers/icons_handler.h" |
| 21 #include "skia/ext/image_operations.h" | 22 #include "skia/ext/image_operations.h" |
| 22 #include "testing/gtest/include/gtest/gtest.h" | 23 #include "testing/gtest/include/gtest/gtest.h" |
| 23 #include "ui/base/resource/resource_bundle.h" | 24 #include "ui/base/resource/resource_bundle.h" |
| 24 #include "ui/gfx/image/image_skia_source.h" | 25 #include "ui/gfx/image/image_skia_source.h" |
| 25 #include "ui/gfx/skia_util.h" | 26 #include "ui/gfx/skia_util.h" |
| 26 | 27 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 ~MockImageSkiaSource() override {} | 59 ~MockImageSkiaSource() override {} |
| 59 | 60 |
| 60 gfx::ImageSkiaRep GetImageForScale(float scale) override { | 61 gfx::ImageSkiaRep GetImageForScale(float scale) override { |
| 61 return image_.GetRepresentation(scale); | 62 return image_.GetRepresentation(scale); |
| 62 } | 63 } |
| 63 | 64 |
| 64 private: | 65 private: |
| 65 gfx::ImageSkia image_; | 66 gfx::ImageSkia image_; |
| 66 }; | 67 }; |
| 67 | 68 |
| 68 // Helper class for synchronously loading extension image resource. | |
| 69 class TestImageLoader { | |
| 70 public: | |
| 71 explicit TestImageLoader(const Extension* extension) | |
| 72 : extension_(extension), | |
| 73 waiting_(false), | |
| 74 image_loaded_(false) { | |
| 75 } | |
| 76 virtual ~TestImageLoader() {} | |
| 77 | |
| 78 void OnImageLoaded(const gfx::Image& image) { | |
| 79 image_ = image; | |
| 80 image_loaded_ = true; | |
| 81 if (waiting_) | |
| 82 base::MessageLoop::current()->Quit(); | |
| 83 } | |
| 84 | |
| 85 SkBitmap LoadBitmap(const std::string& path, | |
| 86 int size) { | |
| 87 image_loaded_ = false; | |
| 88 | |
| 89 image_loader_.LoadImageAsync( | |
| 90 extension_, extension_->GetResource(path), gfx::Size(size, size), | |
| 91 base::Bind(&TestImageLoader::OnImageLoaded, | |
| 92 base::Unretained(this))); | |
| 93 | |
| 94 // If |image_| still hasn't been loaded (i.e. it is being loaded | |
| 95 // asynchronously), wait for it. | |
| 96 if (!image_loaded_) { | |
| 97 waiting_ = true; | |
| 98 base::MessageLoop::current()->Run(); | |
| 99 waiting_ = false; | |
| 100 } | |
| 101 | |
| 102 EXPECT_TRUE(image_loaded_); | |
| 103 | |
| 104 return image_.IsEmpty() ? SkBitmap() : *image_.ToSkBitmap(); | |
| 105 } | |
| 106 | |
| 107 private: | |
| 108 const Extension* extension_; | |
| 109 bool waiting_; | |
| 110 bool image_loaded_; | |
| 111 gfx::Image image_; | |
| 112 ImageLoader image_loader_; | |
| 113 | |
| 114 DISALLOW_COPY_AND_ASSIGN(TestImageLoader); | |
| 115 }; | |
| 116 | |
| 117 class ExtensionIconImageTest : public ExtensionsTest, | 69 class ExtensionIconImageTest : public ExtensionsTest, |
| 118 public IconImage::Observer { | 70 public IconImage::Observer { |
| 119 public: | 71 public: |
| 120 ExtensionIconImageTest() | 72 ExtensionIconImageTest() |
| 121 : image_loaded_count_(0), | 73 : image_loaded_count_(0), |
| 122 quit_in_image_loaded_(false), | 74 quit_in_image_loaded_(false), |
| 123 ui_thread_(BrowserThread::UI, &ui_loop_), | 75 ui_thread_(BrowserThread::UI, &ui_loop_), |
| 124 file_thread_(BrowserThread::FILE), | 76 file_thread_(BrowserThread::FILE), |
| 125 io_thread_(BrowserThread::IO), | 77 io_thread_(BrowserThread::IO), |
| 126 notification_service_(content::NotificationService::Create()) {} | 78 notification_service_(content::NotificationService::Create()) {} |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 177 void OnExtensionIconImageChanged(IconImage* image) override { | 129 void OnExtensionIconImageChanged(IconImage* image) override { |
| 178 image_loaded_count_++; | 130 image_loaded_count_++; |
| 179 if (quit_in_image_loaded_) | 131 if (quit_in_image_loaded_) |
| 180 base::MessageLoop::current()->Quit(); | 132 base::MessageLoop::current()->Quit(); |
| 181 } | 133 } |
| 182 | 134 |
| 183 gfx::ImageSkia GetDefaultIcon() { | 135 gfx::ImageSkia GetDefaultIcon() { |
| 184 return gfx::ImageSkia(gfx::ImageSkiaRep(gfx::Size(16, 16), 1.0f)); | 136 return gfx::ImageSkia(gfx::ImageSkiaRep(gfx::Size(16, 16), 1.0f)); |
| 185 } | 137 } |
| 186 | 138 |
| 187 // Loads an image to be used in test from the extension. | |
| 188 // The image will be loaded from the relative path |path|. | |
| 189 SkBitmap GetTestBitmap(const Extension* extension, | |
| 190 const std::string& path, | |
| 191 int size) { | |
| 192 TestImageLoader image_loader(extension); | |
| 193 return image_loader.LoadBitmap(path, size); | |
| 194 } | |
| 195 | |
| 196 private: | 139 private: |
| 197 int image_loaded_count_; | 140 int image_loaded_count_; |
| 198 bool quit_in_image_loaded_; | 141 bool quit_in_image_loaded_; |
| 199 base::MessageLoop ui_loop_; | 142 base::MessageLoop ui_loop_; |
| 200 content::TestBrowserThread ui_thread_; | 143 content::TestBrowserThread ui_thread_; |
| 201 content::TestBrowserThread file_thread_; | 144 content::TestBrowserThread file_thread_; |
| 202 content::TestBrowserThread io_thread_; | 145 content::TestBrowserThread io_thread_; |
| 203 scoped_ptr<content::NotificationService> notification_service_; | 146 scoped_ptr<content::NotificationService> notification_service_; |
| 204 | 147 |
| 205 DISALLOW_COPY_AND_ASSIGN(ExtensionIconImageTest); | 148 DISALLOW_COPY_AND_ASSIGN(ExtensionIconImageTest); |
| 206 }; | 149 }; |
| 207 | 150 |
| 208 } // namespace | 151 } // namespace |
| 209 | 152 |
| 210 TEST_F(ExtensionIconImageTest, Basic) { | 153 TEST_F(ExtensionIconImageTest, Basic) { |
| 211 std::vector<ui::ScaleFactor> supported_factors; | 154 std::vector<ui::ScaleFactor> supported_factors; |
| 212 supported_factors.push_back(ui::SCALE_FACTOR_100P); | 155 supported_factors.push_back(ui::SCALE_FACTOR_100P); |
| 213 supported_factors.push_back(ui::SCALE_FACTOR_200P); | 156 supported_factors.push_back(ui::SCALE_FACTOR_200P); |
| 214 ui::test::ScopedSetSupportedScaleFactors scoped_supported(supported_factors); | 157 ui::test::ScopedSetSupportedScaleFactors scoped_supported(supported_factors); |
| 215 scoped_refptr<Extension> extension(CreateExtension( | 158 scoped_refptr<Extension> extension(CreateExtension( |
| 216 "extension_icon_image", Manifest::INVALID_LOCATION)); | 159 "extension_icon_image", Manifest::INVALID_LOCATION)); |
| 217 ASSERT_TRUE(extension.get() != NULL); | 160 ASSERT_TRUE(extension.get() != NULL); |
| 218 | 161 |
| 219 gfx::ImageSkia default_icon = GetDefaultIcon(); | 162 gfx::ImageSkia default_icon = GetDefaultIcon(); |
| 220 | 163 |
| 221 // Load images we expect to find as representations in icon_image, so we | 164 // Load images we expect to find as representations in icon_image, so we |
| 222 // can later use them to validate icon_image. | 165 // can later use them to validate icon_image. |
| 223 SkBitmap bitmap_16 = GetTestBitmap(extension.get(), "16.png", 16); | 166 SkBitmap bitmap_16 = |
| 167 TestImageLoader::LoadAndGetExtensionBitmap(extension.get(), "16.png", 16); |
| 224 ASSERT_FALSE(bitmap_16.empty()); | 168 ASSERT_FALSE(bitmap_16.empty()); |
| 225 | 169 |
| 226 // There is no image of size 32 defined in the extension manifest, so we | 170 // There is no image of size 32 defined in the extension manifest, so we |
| 227 // should expect manifest image of size 48 resized to size 32. | 171 // should expect manifest image of size 48 resized to size 32. |
| 228 SkBitmap bitmap_48_resized_to_32 = | 172 SkBitmap bitmap_48_resized_to_32 = |
| 229 GetTestBitmap(extension.get(), "48.png", 32); | 173 TestImageLoader::LoadAndGetExtensionBitmap(extension.get(), "48.png", 32); |
| 230 ASSERT_FALSE(bitmap_48_resized_to_32.empty()); | 174 ASSERT_FALSE(bitmap_48_resized_to_32.empty()); |
| 231 | 175 |
| 232 IconImage image(browser_context(), | 176 IconImage image(browser_context(), |
| 233 extension.get(), | 177 extension.get(), |
| 234 IconsInfo::GetIcons(extension.get()), | 178 IconsInfo::GetIcons(extension.get()), |
| 235 16, | 179 16, |
| 236 default_icon, | 180 default_icon, |
| 237 this); | 181 this); |
| 238 | 182 |
| 239 // No representations in |image_| yet. | 183 // No representations in |image_| yet. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 286 supported_factors.push_back(ui::SCALE_FACTOR_200P); | 230 supported_factors.push_back(ui::SCALE_FACTOR_200P); |
| 287 ui::test::ScopedSetSupportedScaleFactors scoped_supported(supported_factors); | 231 ui::test::ScopedSetSupportedScaleFactors scoped_supported(supported_factors); |
| 288 scoped_refptr<Extension> extension(CreateExtension( | 232 scoped_refptr<Extension> extension(CreateExtension( |
| 289 "extension_icon_image", Manifest::INVALID_LOCATION)); | 233 "extension_icon_image", Manifest::INVALID_LOCATION)); |
| 290 ASSERT_TRUE(extension.get() != NULL); | 234 ASSERT_TRUE(extension.get() != NULL); |
| 291 | 235 |
| 292 gfx::ImageSkia default_icon = GetDefaultIcon(); | 236 gfx::ImageSkia default_icon = GetDefaultIcon(); |
| 293 | 237 |
| 294 // Load images we expect to find as representations in icon_image, so we | 238 // Load images we expect to find as representations in icon_image, so we |
| 295 // can later use them to validate icon_image. | 239 // can later use them to validate icon_image. |
| 296 SkBitmap bitmap_48 = GetTestBitmap(extension.get(), "48.png", 48); | 240 SkBitmap bitmap_48 = |
| 241 TestImageLoader::LoadAndGetExtensionBitmap(extension.get(), "48.png", 48); |
| 297 ASSERT_FALSE(bitmap_48.empty()); | 242 ASSERT_FALSE(bitmap_48.empty()); |
| 298 | 243 |
| 299 IconImage image(browser_context(), | 244 IconImage image(browser_context(), |
| 300 extension.get(), | 245 extension.get(), |
| 301 IconsInfo::GetIcons(extension.get()), | 246 IconsInfo::GetIcons(extension.get()), |
| 302 32, | 247 32, |
| 303 default_icon, | 248 default_icon, |
| 304 this); | 249 this); |
| 305 | 250 |
| 306 gfx::ImageSkiaRep representation = image.image_skia().GetRepresentation(2.0f); | 251 gfx::ImageSkiaRep representation = image.image_skia().GetRepresentation(2.0f); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 323 // one. The bigger resource should be loaded. | 268 // one. The bigger resource should be loaded. |
| 324 TEST_F(ExtensionIconImageTest, FallbackToBigger) { | 269 TEST_F(ExtensionIconImageTest, FallbackToBigger) { |
| 325 scoped_refptr<Extension> extension(CreateExtension( | 270 scoped_refptr<Extension> extension(CreateExtension( |
| 326 "extension_icon_image", Manifest::INVALID_LOCATION)); | 271 "extension_icon_image", Manifest::INVALID_LOCATION)); |
| 327 ASSERT_TRUE(extension.get() != NULL); | 272 ASSERT_TRUE(extension.get() != NULL); |
| 328 | 273 |
| 329 gfx::ImageSkia default_icon = GetDefaultIcon(); | 274 gfx::ImageSkia default_icon = GetDefaultIcon(); |
| 330 | 275 |
| 331 // Load images we expect to find as representations in icon_image, so we | 276 // Load images we expect to find as representations in icon_image, so we |
| 332 // can later use them to validate icon_image. | 277 // can later use them to validate icon_image. |
| 333 SkBitmap bitmap_24 = GetTestBitmap(extension.get(), "24.png", 24); | 278 SkBitmap bitmap_24 = |
| 279 TestImageLoader::LoadAndGetExtensionBitmap(extension.get(), "24.png", 24); |
| 334 ASSERT_FALSE(bitmap_24.empty()); | 280 ASSERT_FALSE(bitmap_24.empty()); |
| 335 | 281 |
| 336 IconImage image(browser_context(), | 282 IconImage image(browser_context(), |
| 337 extension.get(), | 283 extension.get(), |
| 338 IconsInfo::GetIcons(extension.get()), | 284 IconsInfo::GetIcons(extension.get()), |
| 339 17, | 285 17, |
| 340 default_icon, | 286 default_icon, |
| 341 this); | 287 this); |
| 342 | 288 |
| 343 gfx::ImageSkiaRep representation = image.image_skia().GetRepresentation(1.0f); | 289 gfx::ImageSkiaRep representation = image.image_skia().GetRepresentation(1.0f); |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 515 // representations should be returned. | 461 // representations should be returned. |
| 516 TEST_F(ExtensionIconImageTest, IconImageDestruction) { | 462 TEST_F(ExtensionIconImageTest, IconImageDestruction) { |
| 517 scoped_refptr<Extension> extension(CreateExtension( | 463 scoped_refptr<Extension> extension(CreateExtension( |
| 518 "extension_icon_image", Manifest::INVALID_LOCATION)); | 464 "extension_icon_image", Manifest::INVALID_LOCATION)); |
| 519 ASSERT_TRUE(extension.get() != NULL); | 465 ASSERT_TRUE(extension.get() != NULL); |
| 520 | 466 |
| 521 gfx::ImageSkia default_icon = GetDefaultIcon(); | 467 gfx::ImageSkia default_icon = GetDefaultIcon(); |
| 522 | 468 |
| 523 // Load images we expect to find as representations in icon_image, so we | 469 // Load images we expect to find as representations in icon_image, so we |
| 524 // can later use them to validate icon_image. | 470 // can later use them to validate icon_image. |
| 525 SkBitmap bitmap_16 = GetTestBitmap(extension.get(), "16.png", 16); | 471 SkBitmap bitmap_16 = |
| 472 TestImageLoader::LoadAndGetExtensionBitmap(extension.get(), "16.png", 16); |
| 526 ASSERT_FALSE(bitmap_16.empty()); | 473 ASSERT_FALSE(bitmap_16.empty()); |
| 527 | 474 |
| 528 scoped_ptr<IconImage> image( | 475 scoped_ptr<IconImage> image( |
| 529 new IconImage(browser_context(), | 476 new IconImage(browser_context(), |
| 530 extension.get(), | 477 extension.get(), |
| 531 IconsInfo::GetIcons(extension.get()), | 478 IconsInfo::GetIcons(extension.get()), |
| 532 16, | 479 16, |
| 533 default_icon, | 480 default_icon, |
| 534 this)); | 481 this)); |
| 535 | 482 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 597 // because image storage is shared, so when we created one from the first | 544 // because image storage is shared, so when we created one from the first |
| 598 // image, all other images should also have that representation... | 545 // image, all other images should also have that representation... |
| 599 gfx::Image image2 = icon_image->image(); | 546 gfx::Image image2 = icon_image->image(); |
| 600 EXPECT_EQ(image_as_png.get(), image2.As1xPNGBytes().get()); | 547 EXPECT_EQ(image_as_png.get(), image2.As1xPNGBytes().get()); |
| 601 | 548 |
| 602 // ...even images that were copied before the representation was constructed. | 549 // ...even images that were copied before the representation was constructed. |
| 603 EXPECT_EQ(image_as_png.get(), prior_image.As1xPNGBytes().get()); | 550 EXPECT_EQ(image_as_png.get(), prior_image.As1xPNGBytes().get()); |
| 604 } | 551 } |
| 605 | 552 |
| 606 } // namespace extensions | 553 } // namespace extensions |
| OLD | NEW |