| 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/image_loading_tracker.h" | 5 #include "chrome/browser/extensions/image_loader.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/common/chrome_notification_types.h" | 10 #include "chrome/common/chrome_notification_types.h" |
| 11 #include "chrome/common/chrome_paths.h" | 11 #include "chrome/common/chrome_paths.h" |
| 12 #include "chrome/common/extensions/extension.h" | 12 #include "chrome/common/extensions/extension.h" |
| 13 #include "chrome/common/extensions/extension_constants.h" | 13 #include "chrome/common/extensions/extension_constants.h" |
| 14 #include "chrome/common/extensions/extension_icon_set.h" | 14 #include "chrome/common/extensions/extension_icon_set.h" |
| 15 #include "chrome/common/extensions/extension_resource.h" | 15 #include "chrome/common/extensions/extension_resource.h" |
| 16 #include "content/public/browser/notification_service.h" | 16 #include "content/public/browser/notification_service.h" |
| 17 #include "content/public/test/test_browser_thread.h" | 17 #include "content/public/test/test_browser_thread.h" |
| 18 #include "grit/component_extension_resources.h" | 18 #include "grit/component_extension_resources.h" |
| 19 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
| 20 #include "third_party/skia/include/core/SkBitmap.h" | 20 #include "third_party/skia/include/core/SkBitmap.h" |
| 21 #include "ui/gfx/image/image.h" | 21 #include "ui/gfx/image/image.h" |
| 22 #include "ui/gfx/image/image_skia.h" | 22 #include "ui/gfx/image/image_skia.h" |
| 23 #include "ui/gfx/size.h" | 23 #include "ui/gfx/size.h" |
| 24 | 24 |
| 25 using content::BrowserThread; | 25 using content::BrowserThread; |
| 26 using extensions::Extension; | 26 using extensions::Extension; |
| 27 using extensions::ImageLoader; |
| 27 | 28 |
| 28 class ImageLoadingTrackerTest : public testing::Test, | 29 class ImageLoaderTest : public testing::Test { |
| 29 public ImageLoadingTracker::Observer { | |
| 30 public: | 30 public: |
| 31 ImageLoadingTrackerTest() | 31 ImageLoaderTest() |
| 32 : image_loaded_count_(0), | 32 : image_loaded_count_(0), |
| 33 quit_in_image_loaded_(false), | 33 quit_in_image_loaded_(false), |
| 34 ui_thread_(BrowserThread::UI, &ui_loop_), | 34 ui_thread_(BrowserThread::UI, &ui_loop_), |
| 35 file_thread_(BrowserThread::FILE), | 35 file_thread_(BrowserThread::FILE), |
| 36 io_thread_(BrowserThread::IO) { | 36 io_thread_(BrowserThread::IO) { |
| 37 } | 37 } |
| 38 | 38 |
| 39 virtual void OnImageLoaded(const gfx::Image& image, | 39 void OnImageLoaded(const gfx::Image& image) { |
| 40 const std::string& extension_id, | |
| 41 int index) OVERRIDE { | |
| 42 image_loaded_count_++; | 40 image_loaded_count_++; |
| 43 if (quit_in_image_loaded_) | 41 if (quit_in_image_loaded_) |
| 44 MessageLoop::current()->Quit(); | 42 MessageLoop::current()->Quit(); |
| 45 image_ = image; | 43 image_ = image; |
| 46 } | 44 } |
| 47 | 45 |
| 48 void WaitForImageLoad() { | 46 void WaitForImageLoad() { |
| 49 quit_in_image_loaded_ = true; | 47 quit_in_image_loaded_ = true; |
| 50 MessageLoop::current()->Run(); | 48 MessageLoop::current()->Run(); |
| 51 quit_in_image_loaded_ = false; | 49 quit_in_image_loaded_ = false; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 | 100 |
| 103 int image_loaded_count_; | 101 int image_loaded_count_; |
| 104 bool quit_in_image_loaded_; | 102 bool quit_in_image_loaded_; |
| 105 MessageLoop ui_loop_; | 103 MessageLoop ui_loop_; |
| 106 content::TestBrowserThread ui_thread_; | 104 content::TestBrowserThread ui_thread_; |
| 107 content::TestBrowserThread file_thread_; | 105 content::TestBrowserThread file_thread_; |
| 108 content::TestBrowserThread io_thread_; | 106 content::TestBrowserThread io_thread_; |
| 109 }; | 107 }; |
| 110 | 108 |
| 111 // Tests asking ImageLoadingTracker to cache pushes the result to the Extension. | 109 // Tests asking ImageLoadingTracker to cache pushes the result to the Extension. |
| 112 TEST_F(ImageLoadingTrackerTest, Cache) { | 110 TEST_F(ImageLoaderTest, Cache) { |
| 113 scoped_refptr<Extension> extension(CreateExtension( | 111 scoped_refptr<Extension> extension(CreateExtension( |
| 114 "image_loading_tracker", Extension::INVALID)); | 112 "image_loading_tracker", Extension::INVALID)); |
| 115 ASSERT_TRUE(extension.get() != NULL); | 113 ASSERT_TRUE(extension.get() != NULL); |
| 116 | 114 |
| 117 ExtensionResource image_resource = | 115 ExtensionResource image_resource = |
| 118 extension->GetIconResource(extension_misc::EXTENSION_ICON_SMALLISH, | 116 extension->GetIconResource(extension_misc::EXTENSION_ICON_SMALLISH, |
| 119 ExtensionIconSet::MATCH_EXACTLY); | 117 ExtensionIconSet::MATCH_EXACTLY); |
| 120 gfx::Size max_size(extension_misc::EXTENSION_ICON_SMALLISH, | 118 gfx::Size max_size(extension_misc::EXTENSION_ICON_SMALLISH, |
| 121 extension_misc::EXTENSION_ICON_SMALLISH); | 119 extension_misc::EXTENSION_ICON_SMALLISH); |
| 122 ImageLoadingTracker loader(this); | 120 ImageLoader loader; |
| 123 loader.LoadImage(extension.get(), | 121 std::set<int> sizes; |
| 124 image_resource, | 122 sizes.insert(extension_misc::EXTENSION_ICON_SMALLISH); |
| 125 max_size, | 123 loader.SetImageSizesToCache(sizes); |
| 126 ImageLoadingTracker::CACHE); | 124 loader.LoadImageAsync(extension.get(), |
| 125 image_resource, |
| 126 max_size, |
| 127 base::Bind(&ImageLoaderTest::OnImageLoaded, |
| 128 base::Unretained(this))); |
| 127 | 129 |
| 128 // The image isn't cached, so we should not have received notification. | 130 // The image isn't cached, so we should not have received notification. |
| 129 EXPECT_EQ(0, image_loaded_count()); | 131 EXPECT_EQ(0, image_loaded_count()); |
| 130 | 132 |
| 131 WaitForImageLoad(); | 133 WaitForImageLoad(); |
| 132 | 134 |
| 133 // We should have gotten the image. | 135 // We should have gotten the image. |
| 134 EXPECT_EQ(1, image_loaded_count()); | 136 EXPECT_EQ(1, image_loaded_count()); |
| 135 | 137 |
| 136 // Check that the image was loaded. | 138 // Check that the image was loaded. |
| 137 EXPECT_EQ(extension_misc::EXTENSION_ICON_SMALLISH, | 139 EXPECT_EQ(extension_misc::EXTENSION_ICON_SMALLISH, |
| 138 image_.ToSkBitmap()->width()); | 140 image_.ToSkBitmap()->width()); |
| 139 | 141 |
| 140 // The image should be cached in the Extension. | 142 // Make sure the image is cached. |
| 141 EXPECT_TRUE(extension->HasCachedImage(image_resource, max_size)); | 143 const SkBitmap* bitmap = loader.GetCachedImage(image_resource, max_size); |
| 142 | 144 ASSERT_TRUE(bitmap); |
| 143 // Make sure the image is in the extension. | |
| 144 EXPECT_EQ(extension_misc::EXTENSION_ICON_SMALLISH, | 145 EXPECT_EQ(extension_misc::EXTENSION_ICON_SMALLISH, |
| 145 extension->GetCachedImage(image_resource, max_size).width()); | 146 bitmap->width()); |
| 146 | 147 |
| 147 // Ask the tracker for the image again, this should call us back immediately. | 148 // Ask the tracker for the image again, this should call us back immediately. |
| 148 loader.LoadImage(extension.get(), | 149 loader.LoadImageAsync(extension.get(), |
| 149 image_resource, | 150 image_resource, |
| 150 max_size, | 151 max_size, |
| 151 ImageLoadingTracker::CACHE); | 152 base::Bind(&ImageLoaderTest::OnImageLoaded, |
| 153 base::Unretained(this))); |
| 152 // We should have gotten the image. | 154 // We should have gotten the image. |
| 153 EXPECT_EQ(1, image_loaded_count()); | 155 EXPECT_EQ(1, image_loaded_count()); |
| 154 | 156 |
| 155 // Check that the image was loaded. | 157 // Check that the image was loaded. |
| 156 EXPECT_EQ(extension_misc::EXTENSION_ICON_SMALLISH, | 158 EXPECT_EQ(extension_misc::EXTENSION_ICON_SMALLISH, |
| 157 image_.ToSkBitmap()->width()); | 159 image_.ToSkBitmap()->width()); |
| 158 } | 160 } |
| 159 | 161 |
| 160 // Tests deleting an extension while waiting for the image to load doesn't cause | 162 // Tests deleting an extension while waiting for the image to load doesn't cause |
| 161 // problems. | 163 // problems. |
| 162 TEST_F(ImageLoadingTrackerTest, DeleteExtensionWhileWaitingForCache) { | 164 TEST_F(ImageLoaderTest, DeleteExtensionWhileWaitingForCache) { |
| 163 scoped_refptr<Extension> extension(CreateExtension( | 165 scoped_refptr<Extension> extension(CreateExtension( |
| 164 "image_loading_tracker", Extension::INVALID)); | 166 "image_loading_tracker", Extension::INVALID)); |
| 165 ASSERT_TRUE(extension.get() != NULL); | 167 ASSERT_TRUE(extension.get() != NULL); |
| 166 | 168 |
| 167 ExtensionResource image_resource = | 169 ExtensionResource image_resource = |
| 168 extension->GetIconResource(extension_misc::EXTENSION_ICON_SMALLISH, | 170 extension->GetIconResource(extension_misc::EXTENSION_ICON_SMALLISH, |
| 169 ExtensionIconSet::MATCH_EXACTLY); | 171 ExtensionIconSet::MATCH_EXACTLY); |
| 170 ImageLoadingTracker loader(this); | 172 gfx::Size max_size(extension_misc::EXTENSION_ICON_SMALLISH, |
| 171 loader.LoadImage(extension.get(), | 173 extension_misc::EXTENSION_ICON_SMALLISH); |
| 172 image_resource, | 174 ImageLoader loader; |
| 173 gfx::Size(extension_misc::EXTENSION_ICON_SMALLISH, | 175 std::set<int> sizes; |
| 174 extension_misc::EXTENSION_ICON_SMALLISH), | 176 sizes.insert(extension_misc::EXTENSION_ICON_SMALLISH); |
| 175 ImageLoadingTracker::CACHE); | 177 loader.SetImageSizesToCache(sizes); |
| 178 loader.LoadImageAsync(extension.get(), |
| 179 image_resource, |
| 180 max_size, |
| 181 base::Bind(&ImageLoaderTest::OnImageLoaded, |
| 182 base::Unretained(this))); |
| 176 | 183 |
| 177 // The image isn't cached, so we should not have received notification. | 184 // The image isn't cached, so we should not have received notification. |
| 178 EXPECT_EQ(0, image_loaded_count()); | 185 EXPECT_EQ(0, image_loaded_count()); |
| 179 | 186 |
| 180 // Send out notification the extension was uninstalled. | 187 // Send out notification the extension was uninstalled. |
| 181 extensions::UnloadedExtensionInfo details(extension.get(), | 188 extensions::UnloadedExtensionInfo details(extension.get(), |
| 182 extension_misc::UNLOAD_REASON_UNINSTALL); | 189 extension_misc::UNLOAD_REASON_UNINSTALL); |
| 183 content::NotificationService::current()->Notify( | 190 content::NotificationService::current()->Notify( |
| 184 chrome::NOTIFICATION_EXTENSION_UNLOADED, | 191 chrome::NOTIFICATION_EXTENSION_UNLOADED, |
| 185 content::NotificationService::AllSources(), | 192 content::NotificationService::AllSources(), |
| 186 content::Details<extensions::UnloadedExtensionInfo>(&details)); | 193 content::Details<extensions::UnloadedExtensionInfo>(&details)); |
| 187 | 194 |
| 188 // Chuck the extension, that way if anyone tries to access it we should crash | 195 // Chuck the extension, that way if anyone tries to access it we should crash |
| 189 // or get valgrind errors. | 196 // or get valgrind errors. |
| 190 extension = NULL; | 197 extension = NULL; |
| 191 | 198 |
| 192 WaitForImageLoad(); | 199 WaitForImageLoad(); |
| 193 | 200 |
| 194 // Even though we deleted the extension, we should still get the image. | 201 // Even though we deleted the extension, we should still get the image. |
| 195 // We should still have gotten the image. | 202 // We should still have gotten the image. |
| 196 EXPECT_EQ(1, image_loaded_count()); | 203 EXPECT_EQ(1, image_loaded_count()); |
| 197 | 204 |
| 198 // Check that the image was loaded. | 205 // Check that the image was loaded. |
| 199 EXPECT_EQ(extension_misc::EXTENSION_ICON_SMALLISH, | 206 EXPECT_EQ(extension_misc::EXTENSION_ICON_SMALLISH, |
| 200 image_.ToSkBitmap()->width()); | 207 image_.ToSkBitmap()->width()); |
| 208 |
| 209 // Make sure the image was not cached. |
| 210 EXPECT_EQ(NULL, loader.GetCachedImage(image_resource, max_size)); |
| 201 } | 211 } |
| 202 | 212 |
| 203 // Tests loading multiple dimensions of the same image. | 213 // Tests loading multiple dimensions of the same image. |
| 204 TEST_F(ImageLoadingTrackerTest, MultipleImages) { | 214 TEST_F(ImageLoaderTest, MultipleImages) { |
| 205 scoped_refptr<Extension> extension(CreateExtension( | 215 scoped_refptr<Extension> extension(CreateExtension( |
| 206 "image_loading_tracker", Extension::INVALID)); | 216 "image_loading_tracker", Extension::INVALID)); |
| 207 ASSERT_TRUE(extension.get() != NULL); | 217 ASSERT_TRUE(extension.get() != NULL); |
| 208 | 218 |
| 209 std::vector<ImageLoadingTracker::ImageRepresentation> info_list; | 219 std::vector<ImageLoader::ImageRepresentation> info_list; |
| 210 int sizes[] = {extension_misc::EXTENSION_ICON_SMALLISH, | 220 int sizes[] = {extension_misc::EXTENSION_ICON_SMALLISH, |
| 211 extension_misc::EXTENSION_ICON_BITTY}; | 221 extension_misc::EXTENSION_ICON_BITTY}; |
| 212 for (size_t i = 0; i < arraysize(sizes); ++i) { | 222 for (size_t i = 0; i < arraysize(sizes); ++i) { |
| 213 ExtensionResource resource = | 223 ExtensionResource resource = |
| 214 extension->GetIconResource(sizes[i], ExtensionIconSet::MATCH_EXACTLY); | 224 extension->GetIconResource(sizes[i], ExtensionIconSet::MATCH_EXACTLY); |
| 215 info_list.push_back(ImageLoadingTracker::ImageRepresentation( | 225 info_list.push_back(ImageLoader::ImageRepresentation( |
| 216 resource, | 226 resource, |
| 217 ImageLoadingTracker::ImageRepresentation::RESIZE_WHEN_LARGER, | 227 ImageLoader::ImageRepresentation::RESIZE_WHEN_LARGER, |
| 218 gfx::Size(sizes[i], sizes[i]), | 228 gfx::Size(sizes[i], sizes[i]), |
| 219 ui::SCALE_FACTOR_NONE)); | 229 ui::SCALE_FACTOR_NONE)); |
| 220 } | 230 } |
| 221 | 231 |
| 222 ImageLoadingTracker loader(this); | 232 ImageLoader loader; |
| 223 loader.LoadImages(extension.get(), info_list, ImageLoadingTracker::CACHE); | 233 loader.LoadImagesAsync(extension.get(), info_list, |
| 234 base::Bind(&ImageLoaderTest::OnImageLoaded, |
| 235 base::Unretained(this))); |
| 224 | 236 |
| 225 // The image isn't cached, so we should not have received notification. | 237 // The image isn't cached, so we should not have received notification. |
| 226 EXPECT_EQ(0, image_loaded_count()); | 238 EXPECT_EQ(0, image_loaded_count()); |
| 227 | 239 |
| 228 WaitForImageLoad(); | 240 WaitForImageLoad(); |
| 229 | 241 |
| 230 // We should have gotten the image. | 242 // We should have gotten the image. |
| 231 EXPECT_EQ(1, image_loaded_count()); | 243 EXPECT_EQ(1, image_loaded_count()); |
| 232 | 244 |
| 233 // Check that all images were loaded. | 245 // Check that all images were loaded. |
| 234 std::vector<gfx::ImageSkiaRep> image_reps = | 246 std::vector<gfx::ImageSkiaRep> image_reps = |
| 235 image_.ToImageSkia()->image_reps(); | 247 image_.ToImageSkia()->image_reps(); |
| 236 ASSERT_EQ(2u, image_reps.size()); | 248 ASSERT_EQ(2u, image_reps.size()); |
| 237 const gfx::ImageSkiaRep* img_rep1 = &image_reps[0]; | 249 const gfx::ImageSkiaRep* img_rep1 = &image_reps[0]; |
| 238 const gfx::ImageSkiaRep* img_rep2 = &image_reps[1]; | 250 const gfx::ImageSkiaRep* img_rep2 = &image_reps[1]; |
| 239 if (img_rep1->pixel_width() > img_rep2->pixel_width()) { | 251 if (img_rep1->pixel_width() > img_rep2->pixel_width()) { |
| 240 std::swap(img_rep1, img_rep2); | 252 std::swap(img_rep1, img_rep2); |
| 241 } | 253 } |
| 242 EXPECT_EQ(extension_misc::EXTENSION_ICON_BITTY, | 254 EXPECT_EQ(extension_misc::EXTENSION_ICON_BITTY, |
| 243 img_rep1->pixel_width()); | 255 img_rep1->pixel_width()); |
| 244 EXPECT_EQ(extension_misc::EXTENSION_ICON_SMALLISH, | 256 EXPECT_EQ(extension_misc::EXTENSION_ICON_SMALLISH, |
| 245 img_rep2->pixel_width()); | 257 img_rep2->pixel_width()); |
| 246 } | 258 } |
| 247 | 259 |
| 248 // Tests IsComponentExtensionResource function. | 260 // Tests IsComponentExtensionResource function. |
| 249 TEST_F(ImageLoadingTrackerTest, IsComponentExtensionResource) { | 261 TEST_F(ImageLoaderTest, IsComponentExtensionResource) { |
| 250 scoped_refptr<Extension> extension(CreateExtension( | 262 scoped_refptr<Extension> extension(CreateExtension( |
| 251 "file_manager", Extension::COMPONENT)); | 263 "file_manager", Extension::COMPONENT)); |
| 252 ASSERT_TRUE(extension.get() != NULL); | 264 ASSERT_TRUE(extension.get() != NULL); |
| 253 | 265 |
| 254 ExtensionResource resource = | 266 ExtensionResource resource = |
| 255 extension->GetIconResource(extension_misc::EXTENSION_ICON_BITTY, | 267 extension->GetIconResource(extension_misc::EXTENSION_ICON_BITTY, |
| 256 ExtensionIconSet::MATCH_EXACTLY); | 268 ExtensionIconSet::MATCH_EXACTLY); |
| 257 | 269 |
| 258 #if defined(FILE_MANAGER_EXTENSION) | 270 #if defined(FILE_MANAGER_EXTENSION) |
| 259 ImageLoadingTracker loader(this); | |
| 260 int resource_id; | 271 int resource_id; |
| 261 ASSERT_EQ(true, | 272 ASSERT_EQ(true, |
| 262 loader.IsComponentExtensionResource(extension.get(), | 273 ImageLoader::IsComponentExtensionResource(extension.get(), |
| 263 resource.relative_path(), | 274 resource.relative_path(), |
| 264 &resource_id)); | 275 &resource_id)); |
| 265 ASSERT_EQ(IDR_FILE_MANAGER_ICON_16, resource_id); | 276 ASSERT_EQ(IDR_FILE_MANAGER_ICON_16, resource_id); |
| 266 #endif | 277 #endif |
| 267 } | 278 } |
| OLD | NEW |