Updating trunk VERSION from 2139.0 to 2140.0
[chromium-blink-merge.git] / extensions / browser / image_loader_unittest.cc
blob74b9cccc52f73f6551984da01e432dbfc69a8ca5
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
3 // found in the LICENSE file.
5 #include "extensions/browser/image_loader.h"
7 #include "base/files/file_path.h"
8 #include "base/json/json_file_value_serializer.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/path_service.h"
11 #include "base/strings/string_util.h"
12 #include "content/public/browser/notification_service.h"
13 #include "content/public/test/test_browser_thread.h"
14 #include "extensions/browser/extensions_browser_client.h"
15 #include "extensions/browser/notification_types.h"
16 #include "extensions/common/constants.h"
17 #include "extensions/common/extension.h"
18 #include "extensions/common/extension_icon_set.h"
19 #include "extensions/common/extension_paths.h"
20 #include "extensions/common/extension_resource.h"
21 #include "extensions/common/manifest.h"
22 #include "extensions/common/manifest_handlers/icons_handler.h"
23 #include "testing/gtest/include/gtest/gtest.h"
24 #include "third_party/skia/include/core/SkBitmap.h"
25 #include "ui/gfx/image/image.h"
26 #include "ui/gfx/image/image_family.h"
27 #include "ui/gfx/image/image_skia.h"
28 #include "ui/gfx/size.h"
30 using content::BrowserThread;
31 using content::NotificationService;
33 namespace extensions {
35 class ImageLoaderTest : public testing::Test {
36 public:
37 ImageLoaderTest()
38 : image_loaded_count_(0),
39 quit_in_image_loaded_(false),
40 ui_thread_(BrowserThread::UI, &ui_loop_),
41 file_thread_(BrowserThread::FILE),
42 io_thread_(BrowserThread::IO),
43 notification_service_(NotificationService::Create()) {}
45 void OnImageLoaded(const gfx::Image& image) {
46 image_loaded_count_++;
47 if (quit_in_image_loaded_)
48 base::MessageLoop::current()->Quit();
49 image_ = image;
52 void OnImageFamilyLoaded(const gfx::ImageFamily& image_family) {
53 image_loaded_count_++;
54 if (quit_in_image_loaded_)
55 base::MessageLoop::current()->Quit();
56 image_family_ = image_family;
59 void WaitForImageLoad() {
60 quit_in_image_loaded_ = true;
61 base::MessageLoop::current()->Run();
62 quit_in_image_loaded_ = false;
65 int image_loaded_count() {
66 int result = image_loaded_count_;
67 image_loaded_count_ = 0;
68 return result;
71 scoped_refptr<Extension> CreateExtension(const char* dir_name,
72 Manifest::Location location) {
73 // Create and load an extension.
74 base::FilePath extension_dir;
75 if (!PathService::Get(DIR_TEST_DATA, &extension_dir)) {
76 EXPECT_FALSE(true);
77 return NULL;
79 extension_dir = extension_dir.AppendASCII(dir_name);
80 int error_code = 0;
81 std::string error;
82 JSONFileValueSerializer serializer(
83 extension_dir.AppendASCII("manifest.json"));
84 scoped_ptr<base::DictionaryValue> valid_value(
85 static_cast<base::DictionaryValue*>(serializer.Deserialize(&error_code,
86 &error)));
87 EXPECT_EQ(0, error_code) << error;
88 if (error_code != 0)
89 return NULL;
91 EXPECT_TRUE(valid_value.get());
92 if (!valid_value)
93 return NULL;
95 return Extension::Create(
96 extension_dir, location, *valid_value, Extension::NO_FLAGS, &error);
99 gfx::Image image_;
100 gfx::ImageFamily image_family_;
102 private:
103 virtual void SetUp() OVERRIDE {
104 testing::Test::SetUp();
105 file_thread_.Start();
106 io_thread_.Start();
109 int image_loaded_count_;
110 bool quit_in_image_loaded_;
111 base::MessageLoop ui_loop_;
112 content::TestBrowserThread ui_thread_;
113 content::TestBrowserThread file_thread_;
114 content::TestBrowserThread io_thread_;
115 scoped_ptr<NotificationService> notification_service_;
118 // Tests loading an image works correctly.
119 TEST_F(ImageLoaderTest, LoadImage) {
120 scoped_refptr<Extension> extension(
121 CreateExtension("image_loader", Manifest::INVALID_LOCATION));
122 ASSERT_TRUE(extension.get() != NULL);
124 ExtensionResource image_resource =
125 IconsInfo::GetIconResource(extension.get(),
126 extension_misc::EXTENSION_ICON_SMALLISH,
127 ExtensionIconSet::MATCH_EXACTLY);
128 gfx::Size max_size(extension_misc::EXTENSION_ICON_SMALLISH,
129 extension_misc::EXTENSION_ICON_SMALLISH);
130 ImageLoader loader;
131 loader.LoadImageAsync(extension.get(),
132 image_resource,
133 max_size,
134 base::Bind(&ImageLoaderTest::OnImageLoaded,
135 base::Unretained(this)));
137 // The image isn't cached, so we should not have received notification.
138 EXPECT_EQ(0, image_loaded_count());
140 WaitForImageLoad();
142 // We should have gotten the image.
143 EXPECT_FALSE(image_.IsEmpty());
144 EXPECT_EQ(1, image_loaded_count());
146 // Check that the image was loaded.
147 EXPECT_EQ(extension_misc::EXTENSION_ICON_SMALLISH,
148 image_.ToSkBitmap()->width());
151 // Tests deleting an extension while waiting for the image to load doesn't cause
152 // problems.
153 TEST_F(ImageLoaderTest, DeleteExtensionWhileWaitingForCache) {
154 scoped_refptr<Extension> extension(
155 CreateExtension("image_loader", Manifest::INVALID_LOCATION));
156 ASSERT_TRUE(extension.get() != NULL);
158 ExtensionResource image_resource =
159 IconsInfo::GetIconResource(extension.get(),
160 extension_misc::EXTENSION_ICON_SMALLISH,
161 ExtensionIconSet::MATCH_EXACTLY);
162 gfx::Size max_size(extension_misc::EXTENSION_ICON_SMALLISH,
163 extension_misc::EXTENSION_ICON_SMALLISH);
164 ImageLoader loader;
165 std::set<int> sizes;
166 sizes.insert(extension_misc::EXTENSION_ICON_SMALLISH);
167 loader.LoadImageAsync(extension.get(),
168 image_resource,
169 max_size,
170 base::Bind(&ImageLoaderTest::OnImageLoaded,
171 base::Unretained(this)));
173 // The image isn't cached, so we should not have received notification.
174 EXPECT_EQ(0, image_loaded_count());
176 // Send out notification the extension was uninstalled.
177 UnloadedExtensionInfo details(extension.get(),
178 UnloadedExtensionInfo::REASON_UNINSTALL);
179 content::NotificationService::current()->Notify(
180 NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
181 content::NotificationService::AllSources(),
182 content::Details<UnloadedExtensionInfo>(&details));
184 // Chuck the extension, that way if anyone tries to access it we should crash
185 // or get valgrind errors.
186 extension = NULL;
188 WaitForImageLoad();
190 // Even though we deleted the extension, we should still get the image.
191 // We should still have gotten the image.
192 EXPECT_EQ(1, image_loaded_count());
194 // Check that the image was loaded.
195 EXPECT_EQ(extension_misc::EXTENSION_ICON_SMALLISH,
196 image_.ToSkBitmap()->width());
199 // Tests loading multiple dimensions of the same image.
200 TEST_F(ImageLoaderTest, MultipleImages) {
201 scoped_refptr<Extension> extension(
202 CreateExtension("image_loader", Manifest::INVALID_LOCATION));
203 ASSERT_TRUE(extension.get() != NULL);
205 std::vector<ImageLoader::ImageRepresentation> info_list;
206 int sizes[] = {extension_misc::EXTENSION_ICON_BITTY,
207 extension_misc::EXTENSION_ICON_SMALLISH, };
208 for (size_t i = 0; i < arraysize(sizes); ++i) {
209 ExtensionResource resource = IconsInfo::GetIconResource(
210 extension.get(), sizes[i], ExtensionIconSet::MATCH_EXACTLY);
211 info_list.push_back(ImageLoader::ImageRepresentation(
212 resource,
213 ImageLoader::ImageRepresentation::RESIZE_WHEN_LARGER,
214 gfx::Size(sizes[i], sizes[i]),
215 ui::SCALE_FACTOR_NONE));
218 ImageLoader loader;
219 loader.LoadImagesAsync(extension.get(), info_list,
220 base::Bind(&ImageLoaderTest::OnImageLoaded,
221 base::Unretained(this)));
223 // The image isn't cached, so we should not have received notification.
224 EXPECT_EQ(0, image_loaded_count());
226 WaitForImageLoad();
228 // We should have gotten the image.
229 EXPECT_EQ(1, image_loaded_count());
231 // Check that all images were loaded.
232 std::vector<gfx::ImageSkiaRep> image_reps =
233 image_.ToImageSkia()->image_reps();
234 ASSERT_EQ(2u, image_reps.size());
236 const gfx::ImageSkiaRep* img_rep1 = &image_reps[0];
237 const gfx::ImageSkiaRep* img_rep2 = &image_reps[1];
238 EXPECT_EQ(extension_misc::EXTENSION_ICON_BITTY,
239 img_rep1->pixel_width());
240 EXPECT_EQ(extension_misc::EXTENSION_ICON_SMALLISH,
241 img_rep2->pixel_width());
244 // Tests loading multiple dimensions of the same image into an image family.
245 TEST_F(ImageLoaderTest, LoadImageFamily) {
246 scoped_refptr<Extension> extension(
247 CreateExtension("image_loader", Manifest::INVALID_LOCATION));
248 ASSERT_TRUE(extension.get() != NULL);
250 std::vector<ImageLoader::ImageRepresentation> info_list;
251 int sizes[] = {extension_misc::EXTENSION_ICON_BITTY,
252 extension_misc::EXTENSION_ICON_SMALLISH, };
253 for (size_t i = 0; i < arraysize(sizes); ++i) {
254 ExtensionResource resource = IconsInfo::GetIconResource(
255 extension.get(), sizes[i], ExtensionIconSet::MATCH_EXACTLY);
256 info_list.push_back(ImageLoader::ImageRepresentation(
257 resource,
258 ImageLoader::ImageRepresentation::NEVER_RESIZE,
259 gfx::Size(sizes[i], sizes[i]),
260 ui::SCALE_FACTOR_100P));
263 // Add a second icon of 200P which should get grouped with the smaller icon's
264 // ImageSkia.
265 ExtensionResource resource =
266 IconsInfo::GetIconResource(extension.get(),
267 extension_misc::EXTENSION_ICON_SMALLISH,
268 ExtensionIconSet::MATCH_EXACTLY);
269 info_list.push_back(ImageLoader::ImageRepresentation(
270 resource,
271 ImageLoader::ImageRepresentation::NEVER_RESIZE,
272 gfx::Size(extension_misc::EXTENSION_ICON_BITTY,
273 extension_misc::EXTENSION_ICON_BITTY),
274 ui::SCALE_FACTOR_200P));
276 ImageLoader loader;
277 loader.LoadImageFamilyAsync(extension.get(),
278 info_list,
279 base::Bind(&ImageLoaderTest::OnImageFamilyLoaded,
280 base::Unretained(this)));
282 // The image isn't cached, so we should not have received notification.
283 EXPECT_EQ(0, image_loaded_count());
285 WaitForImageLoad();
287 // We should have gotten the image.
288 EXPECT_EQ(1, image_loaded_count());
290 // Check that all images were loaded.
291 for (size_t i = 0; i < arraysize(sizes); ++i) {
292 const gfx::Image* image = image_family_.GetBest(sizes[i], sizes[i]);
293 EXPECT_EQ(sizes[i], image->Width());
296 // Check the smaller image has 2 representations of different scale factors.
297 std::vector<gfx::ImageSkiaRep> image_reps =
298 image_family_.GetBest(extension_misc::EXTENSION_ICON_BITTY,
299 extension_misc::EXTENSION_ICON_BITTY)
300 ->ToImageSkia()
301 ->image_reps();
303 ASSERT_EQ(2u, image_reps.size());
305 const gfx::ImageSkiaRep* img_rep1 = &image_reps[0];
306 const gfx::ImageSkiaRep* img_rep2 = &image_reps[1];
307 EXPECT_EQ(extension_misc::EXTENSION_ICON_BITTY, img_rep1->pixel_width());
308 EXPECT_EQ(1.0f, img_rep1->scale());
309 EXPECT_EQ(extension_misc::EXTENSION_ICON_SMALLISH, img_rep2->pixel_width());
310 EXPECT_EQ(2.0f, img_rep2->scale());
313 } // namespace extensions