- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / image_loader_unittest.cc
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/extensions/image_loader.h"
6
7 #include "base/json/json_file_value_serializer.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/path_service.h"
10 #include "chrome/browser/chrome_notification_types.h"
11 #include "chrome/common/chrome_paths.h"
12 #include "chrome/common/extensions/extension.h"
13 #include "chrome/common/extensions/extension_constants.h"
14 #include "chrome/common/extensions/extension_icon_set.h"
15 #include "chrome/common/extensions/manifest_handlers/icons_handler.h"
16 #include "content/public/browser/notification_service.h"
17 #include "content/public/test/test_browser_thread.h"
18 #include "extensions/common/extension_resource.h"
19 #include "extensions/common/manifest.h"
20 #include "grit/component_extension_resources.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22 #include "third_party/skia/include/core/SkBitmap.h"
23 #include "ui/gfx/image/image.h"
24 #include "ui/gfx/image/image_skia.h"
25 #include "ui/gfx/size.h"
26
27 using content::BrowserThread;
28 using extensions::Extension;
29 using extensions::ExtensionResource;
30 using extensions::ImageLoader;
31 using extensions::Manifest;
32 using extensions::UnloadedExtensionInfo;
33
34 class ImageLoaderTest : public testing::Test {
35  public:
36   ImageLoaderTest()
37       : image_loaded_count_(0),
38         quit_in_image_loaded_(false),
39         ui_thread_(BrowserThread::UI, &ui_loop_),
40         file_thread_(BrowserThread::FILE),
41         io_thread_(BrowserThread::IO) {
42   }
43
44   void OnImageLoaded(const gfx::Image& image) {
45     image_loaded_count_++;
46     if (quit_in_image_loaded_)
47       base::MessageLoop::current()->Quit();
48     image_ = image;
49   }
50
51   void WaitForImageLoad() {
52     quit_in_image_loaded_ = true;
53     base::MessageLoop::current()->Run();
54     quit_in_image_loaded_ = false;
55   }
56
57   int image_loaded_count() {
58     int result = image_loaded_count_;
59     image_loaded_count_ = 0;
60     return result;
61   }
62
63   scoped_refptr<Extension> CreateExtension(const char* name,
64                                            Manifest::Location location) {
65     // Create and load an extension.
66     base::FilePath test_file;
67     if (!PathService::Get(chrome::DIR_TEST_DATA, &test_file)) {
68       EXPECT_FALSE(true);
69       return NULL;
70     }
71     test_file = test_file.AppendASCII("extensions")
72                          .AppendASCII(name);
73     int error_code = 0;
74     std::string error;
75     JSONFileValueSerializer serializer(test_file.AppendASCII("app.json"));
76     scoped_ptr<DictionaryValue> valid_value(
77         static_cast<DictionaryValue*>(serializer.Deserialize(&error_code,
78                                                              &error)));
79     EXPECT_EQ(0, error_code) << error;
80     if (error_code != 0)
81       return NULL;
82
83     EXPECT_TRUE(valid_value.get());
84     if (!valid_value)
85       return NULL;
86
87     if (location == Manifest::COMPONENT) {
88       if (!PathService::Get(chrome::DIR_RESOURCES, &test_file)) {
89         EXPECT_FALSE(true);
90         return NULL;
91       }
92       test_file = test_file.AppendASCII(name);
93     }
94     return Extension::Create(test_file, location, *valid_value,
95                              Extension::NO_FLAGS, &error);
96   }
97
98   gfx::Image image_;
99
100  private:
101   virtual void SetUp() OVERRIDE {
102     testing::Test::SetUp();
103     file_thread_.Start();
104     io_thread_.Start();
105   }
106
107   int image_loaded_count_;
108   bool quit_in_image_loaded_;
109   base::MessageLoop ui_loop_;
110   content::TestBrowserThread ui_thread_;
111   content::TestBrowserThread file_thread_;
112   content::TestBrowserThread io_thread_;
113 };
114
115 // Tests loading an image works correctly.
116 TEST_F(ImageLoaderTest, LoadImage) {
117   scoped_refptr<Extension> extension(CreateExtension(
118       "image_loading_tracker", Manifest::INVALID_LOCATION));
119   ASSERT_TRUE(extension.get() != NULL);
120
121   ExtensionResource image_resource = extensions::IconsInfo::GetIconResource(
122       extension.get(),
123       extension_misc::EXTENSION_ICON_SMALLISH,
124       ExtensionIconSet::MATCH_EXACTLY);
125   gfx::Size max_size(extension_misc::EXTENSION_ICON_SMALLISH,
126                      extension_misc::EXTENSION_ICON_SMALLISH);
127   ImageLoader loader;
128   loader.LoadImageAsync(extension.get(),
129                         image_resource,
130                         max_size,
131                         base::Bind(&ImageLoaderTest::OnImageLoaded,
132                                    base::Unretained(this)));
133
134   // The image isn't cached, so we should not have received notification.
135   EXPECT_EQ(0, image_loaded_count());
136
137   WaitForImageLoad();
138
139   // We should have gotten the image.
140   EXPECT_EQ(1, image_loaded_count());
141
142   // Check that the image was loaded.
143   EXPECT_EQ(extension_misc::EXTENSION_ICON_SMALLISH,
144             image_.ToSkBitmap()->width());
145 }
146
147 // Tests deleting an extension while waiting for the image to load doesn't cause
148 // problems.
149 TEST_F(ImageLoaderTest, DeleteExtensionWhileWaitingForCache) {
150   scoped_refptr<Extension> extension(CreateExtension(
151       "image_loading_tracker", Manifest::INVALID_LOCATION));
152   ASSERT_TRUE(extension.get() != NULL);
153
154   ExtensionResource image_resource = extensions::IconsInfo::GetIconResource(
155       extension.get(),
156       extension_misc::EXTENSION_ICON_SMALLISH,
157       ExtensionIconSet::MATCH_EXACTLY);
158   gfx::Size max_size(extension_misc::EXTENSION_ICON_SMALLISH,
159                      extension_misc::EXTENSION_ICON_SMALLISH);
160   ImageLoader loader;
161   std::set<int> sizes;
162   sizes.insert(extension_misc::EXTENSION_ICON_SMALLISH);
163   loader.LoadImageAsync(extension.get(),
164                         image_resource,
165                         max_size,
166                         base::Bind(&ImageLoaderTest::OnImageLoaded,
167                                    base::Unretained(this)));
168
169   // The image isn't cached, so we should not have received notification.
170   EXPECT_EQ(0, image_loaded_count());
171
172   // Send out notification the extension was uninstalled.
173   UnloadedExtensionInfo details(extension.get(),
174                                 UnloadedExtensionInfo::REASON_UNINSTALL);
175   content::NotificationService::current()->Notify(
176       chrome::NOTIFICATION_EXTENSION_UNLOADED,
177       content::NotificationService::AllSources(),
178       content::Details<UnloadedExtensionInfo>(&details));
179
180   // Chuck the extension, that way if anyone tries to access it we should crash
181   // or get valgrind errors.
182   extension = NULL;
183
184   WaitForImageLoad();
185
186   // Even though we deleted the extension, we should still get the image.
187   // We should still have gotten the image.
188   EXPECT_EQ(1, image_loaded_count());
189
190   // Check that the image was loaded.
191   EXPECT_EQ(extension_misc::EXTENSION_ICON_SMALLISH,
192             image_.ToSkBitmap()->width());
193 }
194
195 // Tests loading multiple dimensions of the same image.
196 TEST_F(ImageLoaderTest, MultipleImages) {
197   scoped_refptr<Extension> extension(CreateExtension(
198       "image_loading_tracker", Manifest::INVALID_LOCATION));
199   ASSERT_TRUE(extension.get() != NULL);
200
201   std::vector<ImageLoader::ImageRepresentation> info_list;
202   int sizes[] = {extension_misc::EXTENSION_ICON_SMALLISH,
203                  extension_misc::EXTENSION_ICON_BITTY};
204   for (size_t i = 0; i < arraysize(sizes); ++i) {
205     ExtensionResource resource = extensions::IconsInfo::GetIconResource(
206         extension.get(), sizes[i], ExtensionIconSet::MATCH_EXACTLY);
207     info_list.push_back(ImageLoader::ImageRepresentation(
208         resource,
209         ImageLoader::ImageRepresentation::RESIZE_WHEN_LARGER,
210         gfx::Size(sizes[i], sizes[i]),
211         ui::SCALE_FACTOR_NONE));
212   }
213
214   ImageLoader loader;
215   loader.LoadImagesAsync(extension.get(), info_list,
216                          base::Bind(&ImageLoaderTest::OnImageLoaded,
217                                     base::Unretained(this)));
218
219   // The image isn't cached, so we should not have received notification.
220   EXPECT_EQ(0, image_loaded_count());
221
222   WaitForImageLoad();
223
224   // We should have gotten the image.
225   EXPECT_EQ(1, image_loaded_count());
226
227   // Check that all images were loaded.
228   std::vector<gfx::ImageSkiaRep> image_reps =
229       image_.ToImageSkia()->image_reps();
230   ASSERT_EQ(2u, image_reps.size());
231   const gfx::ImageSkiaRep* img_rep1 = &image_reps[0];
232   const gfx::ImageSkiaRep* img_rep2 = &image_reps[1];
233   if (img_rep1->pixel_width() > img_rep2->pixel_width()) {
234     std::swap(img_rep1, img_rep2);
235   }
236   EXPECT_EQ(extension_misc::EXTENSION_ICON_BITTY,
237             img_rep1->pixel_width());
238   EXPECT_EQ(extension_misc::EXTENSION_ICON_SMALLISH,
239             img_rep2->pixel_width());
240 }
241
242 // Tests IsComponentExtensionResource function.
243 TEST_F(ImageLoaderTest, IsComponentExtensionResource) {
244   scoped_refptr<Extension> extension(CreateExtension(
245       "file_manager", Manifest::COMPONENT));
246   ASSERT_TRUE(extension.get() != NULL);
247
248   ExtensionResource resource = extensions::IconsInfo::GetIconResource(
249       extension.get(),
250       extension_misc::EXTENSION_ICON_BITTY,
251       ExtensionIconSet::MATCH_EXACTLY);
252
253 #if defined(FILE_MANAGER_EXTENSION)
254   int resource_id;
255   ASSERT_EQ(true,
256             ImageLoader::IsComponentExtensionResource(extension->path(),
257                                                       resource.relative_path(),
258                                                       &resource_id));
259   ASSERT_EQ(IDR_FILE_MANAGER_ICON_16, resource_id);
260 #endif
261 }