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 "base/json/json_file_value_serializer.h" | 5 #include "base/json/json_file_value_serializer.h" |
6 #include "base/macros.h" | 6 #include "base/macros.h" |
7 #include "base/message_loop/message_loop.h" | 7 #include "base/message_loop/message_loop.h" |
8 #include "base/path_service.h" | 8 #include "base/path_service.h" |
9 #include "base/run_loop.h" | 9 #include "base/run_loop.h" |
10 #include "base/values.h" | 10 #include "base/values.h" |
11 #include "build/build_config.h" | 11 #include "build/build_config.h" |
12 #include "chrome/browser/extensions/extension_icon_manager.h" | 12 #include "chrome/browser/extensions/extension_icon_manager.h" |
13 #include "chrome/common/chrome_paths.h" | 13 #include "chrome/common/chrome_paths.h" |
14 #include "chrome/test/base/testing_profile.h" | 14 #include "chrome/test/base/testing_profile.h" |
15 #include "components/crx_file/id_util.h" | 15 #include "components/crx_file/id_util.h" |
16 #include "content/public/test/test_browser_thread.h" | 16 #include "content/public/test/test_browser_thread.h" |
17 #include "extensions/common/extension.h" | 17 #include "extensions/common/extension.h" |
18 #include "testing/gtest/include/gtest/gtest.h" | 18 #include "testing/gtest/include/gtest/gtest.h" |
19 #include "ui/base/layout.h" | |
20 #include "ui/gfx/favicon_size.h" | |
21 #include "ui/gfx/image/image.h" | |
22 #include "ui/gfx/image/image_skia.h" | |
23 #include "ui/gfx/image/image_unittest_util.h" | |
19 #include "ui/gfx/skia_util.h" | 24 #include "ui/gfx/skia_util.h" |
20 | 25 |
26 namespace extensions { | |
27 namespace { | |
28 | |
21 using content::BrowserThread; | 29 using content::BrowserThread; |
22 using extensions::Extension; | |
23 using extensions::Manifest; | |
24 | 30 |
25 // Our test class that takes care of managing the necessary threads for loading | 31 // Our test class that takes care of managing the necessary threads for loading |
26 // extension icons, and waiting for those loads to happen. | 32 // extension icons, and waiting for those loads to happen. |
27 class ExtensionIconManagerTest : public testing::Test { | 33 class ExtensionIconManagerTest : public testing::Test { |
28 public: | 34 public: |
29 ExtensionIconManagerTest() : | 35 ExtensionIconManagerTest() : |
30 unwaited_image_loads_(0), | 36 unwaited_image_loads_(0), |
31 waiting_(false), | 37 waiting_(false), |
32 ui_thread_(BrowserThread::UI, &ui_loop_), | 38 ui_thread_(BrowserThread::UI, &ui_loop_), |
33 file_thread_(BrowserThread::FILE), | 39 file_thread_(BrowserThread::FILE), |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
88 } | 94 } |
89 | 95 |
90 private: | 96 private: |
91 ExtensionIconManagerTest* test_; | 97 ExtensionIconManagerTest* test_; |
92 | 98 |
93 DISALLOW_COPY_AND_ASSIGN(TestIconManager); | 99 DISALLOW_COPY_AND_ASSIGN(TestIconManager); |
94 }; | 100 }; |
95 | 101 |
96 // Returns the default icon that ExtensionIconManager gives when an extension | 102 // Returns the default icon that ExtensionIconManager gives when an extension |
97 // doesn't have an icon. | 103 // doesn't have an icon. |
98 SkBitmap GetDefaultIcon() { | 104 gfx::Image GetDefaultIcon() { |
99 std::string dummy_id = crx_file::id_util::GenerateId("whatever"); | 105 std::string dummy_id = crx_file::id_util::GenerateId("whatever"); |
100 ExtensionIconManager manager; | 106 ExtensionIconManager manager; |
101 return manager.GetIcon(dummy_id); | 107 return manager.GetIcon(dummy_id); |
102 } | 108 } |
103 | 109 |
104 // Tests loading an icon for an extension, removing it, then re-loading it. | 110 // Tests loading an icon for an extension, removing it, then re-loading it. |
105 TEST_F(ExtensionIconManagerTest, LoadRemoveLoad) { | 111 TEST_F(ExtensionIconManagerTest, LoadRemoveLoad) { |
106 std::unique_ptr<Profile> profile(new TestingProfile()); | 112 std::unique_ptr<Profile> profile(new TestingProfile()); |
107 SkBitmap default_icon = GetDefaultIcon(); | 113 gfx::Image default_icon = GetDefaultIcon(); |
108 | 114 |
109 base::FilePath test_dir; | 115 base::FilePath test_dir; |
110 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir)); | 116 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir)); |
111 base::FilePath manifest_path = test_dir.AppendASCII( | 117 base::FilePath manifest_path = test_dir.AppendASCII( |
112 "extensions/image_loading_tracker/app.json"); | 118 "extensions/image_loading_tracker/app.json"); |
113 | 119 |
114 JSONFileValueDeserializer deserializer(manifest_path); | 120 JSONFileValueDeserializer deserializer(manifest_path); |
115 std::unique_ptr<base::DictionaryValue> manifest = | 121 std::unique_ptr<base::DictionaryValue> manifest = |
116 base::DictionaryValue::From(deserializer.Deserialize(NULL, NULL)); | 122 base::DictionaryValue::From(deserializer.Deserialize(NULL, NULL)); |
117 ASSERT_TRUE(manifest.get() != NULL); | 123 ASSERT_TRUE(manifest.get() != NULL); |
118 | 124 |
119 std::string error; | 125 std::string error; |
120 scoped_refptr<Extension> extension( | 126 scoped_refptr<Extension> extension( |
121 Extension::Create(manifest_path.DirName(), Manifest::INVALID_LOCATION, | 127 Extension::Create(manifest_path.DirName(), Manifest::INVALID_LOCATION, |
122 *manifest, Extension::NO_FLAGS, &error)); | 128 *manifest, Extension::NO_FLAGS, &error)); |
123 ASSERT_TRUE(extension.get()); | 129 ASSERT_TRUE(extension.get()); |
124 TestIconManager icon_manager(this); | 130 TestIconManager icon_manager(this); |
125 | 131 |
126 // Load the icon and grab the bitmap. | 132 // Load the icon. |
127 icon_manager.LoadIcon(profile.get(), extension.get()); | 133 icon_manager.LoadIcon(profile.get(), extension.get()); |
128 WaitForImageLoad(); | 134 WaitForImageLoad(); |
129 SkBitmap first_icon = icon_manager.GetIcon(extension->id()); | 135 gfx::Image first_icon = icon_manager.GetIcon(extension->id()); |
130 EXPECT_FALSE(gfx::BitmapsAreEqual(first_icon, default_icon)); | 136 EXPECT_FALSE(gfx::test::AreImagesEqual(first_icon, default_icon)); |
131 | 137 |
132 // Remove the icon from the manager. | 138 // Remove the icon from the manager. |
133 icon_manager.RemoveIcon(extension->id()); | 139 icon_manager.RemoveIcon(extension->id()); |
134 | 140 |
135 // Now re-load the icon - we should get the same result bitmap (and not the | 141 // Now re-load the icon - we should get the same result bitmap (and not the |
136 // default icon). | 142 // default icon). |
137 icon_manager.LoadIcon(profile.get(), extension.get()); | 143 icon_manager.LoadIcon(profile.get(), extension.get()); |
138 WaitForImageLoad(); | 144 WaitForImageLoad(); |
139 SkBitmap second_icon = icon_manager.GetIcon(extension->id()); | 145 gfx::Image second_icon = icon_manager.GetIcon(extension->id()); |
140 EXPECT_FALSE(gfx::BitmapsAreEqual(second_icon, default_icon)); | 146 EXPECT_FALSE(gfx::test::AreImagesEqual(second_icon, default_icon)); |
141 | 147 |
142 EXPECT_TRUE(gfx::BitmapsAreEqual(first_icon, second_icon)); | 148 EXPECT_TRUE(gfx::test::AreImagesEqual(first_icon, second_icon)); |
143 } | 149 } |
144 | 150 |
145 #if defined(OS_CHROMEOS) | 151 #if defined(OS_CHROMEOS) |
146 // Tests loading an icon for a component extension. | 152 // Tests loading an icon for a component extension. |
147 TEST_F(ExtensionIconManagerTest, LoadComponentExtensionResource) { | 153 TEST_F(ExtensionIconManagerTest, LoadComponentExtensionResource) { |
148 std::unique_ptr<Profile> profile(new TestingProfile()); | 154 std::unique_ptr<Profile> profile(new TestingProfile()); |
149 SkBitmap default_icon = GetDefaultIcon(); | 155 gfx::Image default_icon = GetDefaultIcon(); |
150 | 156 |
151 base::FilePath test_dir; | 157 base::FilePath test_dir; |
152 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir)); | 158 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir)); |
153 base::FilePath manifest_path = test_dir.AppendASCII( | 159 base::FilePath manifest_path = test_dir.AppendASCII( |
154 "extensions/file_manager/app.json"); | 160 "extensions/file_manager/app.json"); |
155 | 161 |
156 JSONFileValueDeserializer deserializer(manifest_path); | 162 JSONFileValueDeserializer deserializer(manifest_path); |
157 std::unique_ptr<base::DictionaryValue> manifest = | 163 std::unique_ptr<base::DictionaryValue> manifest = |
158 base::DictionaryValue::From(deserializer.Deserialize(NULL, NULL)); | 164 base::DictionaryValue::From(deserializer.Deserialize(NULL, NULL)); |
159 ASSERT_TRUE(manifest.get() != NULL); | 165 ASSERT_TRUE(manifest.get() != NULL); |
160 | 166 |
161 std::string error; | 167 std::string error; |
162 scoped_refptr<Extension> extension(Extension::Create( | 168 scoped_refptr<Extension> extension(Extension::Create( |
163 manifest_path.DirName(), Manifest::COMPONENT, *manifest.get(), | 169 manifest_path.DirName(), Manifest::COMPONENT, *manifest.get(), |
164 Extension::NO_FLAGS, &error)); | 170 Extension::NO_FLAGS, &error)); |
165 ASSERT_TRUE(extension.get()); | 171 ASSERT_TRUE(extension.get()); |
166 | 172 |
167 TestIconManager icon_manager(this); | 173 TestIconManager icon_manager(this); |
168 // Load the icon and grab the bitmap. | 174 // Load the icon. |
169 icon_manager.LoadIcon(profile.get(), extension.get()); | 175 icon_manager.LoadIcon(profile.get(), extension.get()); |
170 WaitForImageLoad(); | 176 WaitForImageLoad(); |
171 SkBitmap first_icon = icon_manager.GetIcon(extension->id()); | 177 gfx::Image first_icon = icon_manager.GetIcon(extension->id()); |
172 EXPECT_FALSE(gfx::BitmapsAreEqual(first_icon, default_icon)); | 178 EXPECT_FALSE(gfx::test::AreImagesEqual(first_icon, default_icon)); |
173 | 179 |
174 // Remove the icon from the manager. | 180 // Remove the icon from the manager. |
175 icon_manager.RemoveIcon(extension->id()); | 181 icon_manager.RemoveIcon(extension->id()); |
176 | 182 |
177 // Now re-load the icon - we should get the same result bitmap (and not the | 183 // Now re-load the icon - we should get the same result bitmap (and not the |
178 // default icon). | 184 // default icon). |
179 icon_manager.LoadIcon(profile.get(), extension.get()); | 185 icon_manager.LoadIcon(profile.get(), extension.get()); |
180 WaitForImageLoad(); | 186 WaitForImageLoad(); |
181 SkBitmap second_icon = icon_manager.GetIcon(extension->id()); | 187 gfx::Image second_icon = icon_manager.GetIcon(extension->id()); |
182 EXPECT_FALSE(gfx::BitmapsAreEqual(second_icon, default_icon)); | 188 EXPECT_FALSE(gfx::test::AreImagesEqual(second_icon, default_icon)); |
183 | 189 |
184 EXPECT_TRUE(gfx::BitmapsAreEqual(first_icon, second_icon)); | 190 EXPECT_TRUE(gfx::test::AreImagesEqual(first_icon, second_icon)); |
185 } | 191 } |
186 #endif | 192 #endif |
193 | |
194 // Test what bitmaps are loaded when various combinations of scale factors are | |
195 // supported. | |
196 TEST_F(ExtensionIconManagerTest, ScaleFactors) { | |
197 std::unique_ptr<Profile> profile(new TestingProfile()); | |
Devlin
2016/12/15 17:14:41
nit: I think we prefer MakeUnique now, so
auto pro
Evan Stade
2016/12/15 23:49:02
Done.
| |
198 const gfx::Image default_icon = GetDefaultIcon(); | |
199 | |
200 base::FilePath test_dir; | |
201 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir)); | |
202 base::FilePath manifest_path = | |
203 test_dir.AppendASCII("extensions/context_menus/icons/manifest.json"); | |
204 | |
205 JSONFileValueDeserializer deserializer(manifest_path); | |
206 std::unique_ptr<base::DictionaryValue> manifest = | |
207 base::DictionaryValue::From(deserializer.Deserialize(nullptr, nullptr)); | |
208 ASSERT_TRUE(manifest); | |
209 | |
210 std::string error; | |
211 scoped_refptr<Extension> extension( | |
212 Extension::Create(manifest_path.DirName(), Manifest::INVALID_LOCATION, | |
213 *manifest, Extension::NO_FLAGS, &error)); | |
214 ASSERT_TRUE(extension); | |
215 | |
216 int kMaxIconSizeInManifest = 32; | |
217 std::vector<std::vector<ui::ScaleFactor>> supported_scales = { | |
218 // Base case. | |
219 {ui::SCALE_FACTOR_100P}, | |
220 // Two scale factors. | |
221 {ui::SCALE_FACTOR_100P, ui::SCALE_FACTOR_200P}, | |
222 // A scale factor that is in between two of the provided icon sizes | |
223 // (should use the larger one and scale down). | |
224 {ui::SCALE_FACTOR_125P}, | |
225 // One scale factor for which we have an icon, one scale factor for which | |
226 // we don't. | |
227 {ui::SCALE_FACTOR_100P, ui::SCALE_FACTOR_300P}, | |
228 // Just a scale factor where we don't have any icon. This falls back to | |
229 // the default icon. | |
230 {ui::SCALE_FACTOR_300P}}; | |
231 | |
232 for (size_t i = 0; i < supported_scales.size(); ++i) { | |
233 SCOPED_TRACE(testing::Message() << "Test case: " << i); | |
Devlin
2016/12/15 17:14:41
mind blown. Had no idea this existed. Awesome.
Evan Stade
2016/12/15 23:49:02
Acknowledged.
| |
234 ui::test::ScopedSetSupportedScaleFactors scoped(supported_scales[i]); | |
235 TestIconManager icon_manager(this); | |
236 | |
237 icon_manager.LoadIcon(profile.get(), extension.get()); | |
238 WaitForImageLoad(); | |
239 gfx::Image icon = icon_manager.GetIcon(extension->id()); | |
240 | |
241 // Determine if the default icon fallback will be used. We'll use the | |
242 // default when none of the supported scale factors can find an appropriate | |
243 // icon. | |
244 bool should_fall_back_to_default = true; | |
245 for (auto supported_scale : supported_scales[i]) { | |
246 if (gfx::kFaviconSize * ui::GetScaleForScaleFactor(supported_scale) <= | |
247 kMaxIconSizeInManifest) { | |
248 should_fall_back_to_default = false; | |
249 break; | |
250 } | |
251 } | |
252 if (should_fall_back_to_default) { | |
253 EXPECT_TRUE(gfx::test::AreImagesEqual(icon, default_icon)); | |
254 continue; | |
255 } | |
256 | |
257 gfx::ImageSkia image_skia = icon.AsImageSkia(); | |
258 | |
259 for (int dsf = ui::SCALE_FACTOR_NONE + 1; dsf < ui::NUM_SCALE_FACTORS; | |
Devlin
2016/12/15 17:14:41
what is dsf?
Evan Stade
2016/12/15 23:49:02
stands for device scale factor. Changed to scale_f
| |
260 ++dsf) { | |
261 auto scale_factor = static_cast<ui::ScaleFactor>(dsf); | |
262 float scale = ui::GetScaleForScaleFactor(scale_factor); | |
263 SCOPED_TRACE(testing::Message() << "Scale: " << scale); | |
264 | |
265 const bool has_representation = image_skia.HasRepresentation(scale); | |
266 // We shouldn't have a representation if the extension didn't provide a | |
267 // big enough icon. | |
268 if (gfx::kFaviconSize * scale > kMaxIconSizeInManifest) | |
269 EXPECT_FALSE(has_representation); | |
270 else | |
271 EXPECT_EQ(ui::IsSupportedScale(scale), has_representation); | |
272 } | |
273 } | |
274 } | |
275 | |
276 } // namespace | |
277 } // namespace extensions | |
OLD | NEW |