Chromium Code Reviews

Side by Side Diff: chrome/browser/extensions/api/extension_action/browser_action_apitest.cc

Issue 1580983002: Fix the dynamic browser action setIcon path to work with any size icon. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: mac compatible image equality check Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
OLDNEW
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 <stdint.h> 5 #include <stdint.h>
6 6
7 #include "base/macros.h" 7 #include "base/macros.h"
8 #include "build/build_config.h" 8 #include "build/build_config.h"
9 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h" 9 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
10 #include "chrome/browser/extensions/browser_action_test_util.h" 10 #include "chrome/browser/extensions/browser_action_test_util.h"
(...skipping 23 matching lines...)
34 #include "extensions/test/result_catcher.h" 34 #include "extensions/test/result_catcher.h"
35 #include "grit/theme_resources.h" 35 #include "grit/theme_resources.h"
36 #include "net/dns/mock_host_resolver.h" 36 #include "net/dns/mock_host_resolver.h"
37 #include "net/test/embedded_test_server/embedded_test_server.h" 37 #include "net/test/embedded_test_server/embedded_test_server.h"
38 #include "ui/base/resource/resource_bundle.h" 38 #include "ui/base/resource/resource_bundle.h"
39 #include "ui/gfx/geometry/rect.h" 39 #include "ui/gfx/geometry/rect.h"
40 #include "ui/gfx/geometry/size.h" 40 #include "ui/gfx/geometry/size.h"
41 #include "ui/gfx/image/canvas_image_source.h" 41 #include "ui/gfx/image/canvas_image_source.h"
42 #include "ui/gfx/image/image_skia.h" 42 #include "ui/gfx/image/image_skia.h"
43 #include "ui/gfx/image/image_skia_operations.h" 43 #include "ui/gfx/image/image_skia_operations.h"
44 #include "ui/gfx/image/image_unittest_util.h"
44 #include "ui/gfx/skia_util.h" 45 #include "ui/gfx/skia_util.h"
45 46
46 using content::WebContents; 47 using content::WebContents;
47 48
48 namespace extensions { 49 namespace extensions {
49 namespace { 50 namespace {
50 51
51 // An ImageSkia source that will do nothing (i.e., have a blank skia). We need 52 // An ImageSkia source that will do nothing (i.e., have a blank skia). We need
52 // this because we need a blank canvas at a certain size, and that can't be done 53 // this because we need a blank canvas at a certain size, and that can't be done
53 // by just using a null ImageSkia. 54 // by just using a null ImageSkia.
54 class BlankImageSource : public gfx::CanvasImageSource { 55 class BlankImageSource : public gfx::CanvasImageSource {
55 public: 56 public:
56 explicit BlankImageSource(const gfx::Size& size) 57 explicit BlankImageSource(const gfx::Size& size)
57 : gfx::CanvasImageSource(size, false) {} 58 : gfx::CanvasImageSource(size, false) {}
58 ~BlankImageSource() override {} 59 ~BlankImageSource() override {}
59 60
60 void Draw(gfx::Canvas* canvas) override {} 61 void Draw(gfx::Canvas* canvas) override {}
61 62
62 private: 63 private:
63 DISALLOW_COPY_AND_ASSIGN(BlankImageSource); 64 DISALLOW_COPY_AND_ASSIGN(BlankImageSource);
64 }; 65 };
65 66
66 const char kEmptyImageDataError[] = 67 const char kEmptyImageDataError[] =
67 "The imageData property must contain an ImageData object or dictionary " 68 "The imageData property must contain an ImageData object or dictionary "
68 "of ImageData objects."; 69 "of ImageData objects.";
69 const char kEmptyPathError[] = "The path property must not be empty."; 70 const char kEmptyPathError[] = "The path property must not be empty.";
70 71
71 // Views platforms have the icon superimposed over a button's background.
72 // Macs don't, but still need a 29x29-sized image (and the easiest way to do
73 // that is to superimpose the icon over a blank background).
74 gfx::ImageSkia AddBackground(const gfx::ImageSkia& icon) {
75 #if !defined(OS_MACOSX)
76 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
77 gfx::ImageSkia bg = *rb.GetImageSkiaNamed(IDR_BROWSER_ACTION);
78 #else
79 const gfx::Size size(29, 29); // Size of browser actions buttons.
80 gfx::ImageSkia bg(new BlankImageSource(size), size);
81 #endif
82 return gfx::ImageSkiaOperations::CreateSuperimposedImage(bg, icon);
83 }
84
85 bool ImagesAreEqualAtScale(const gfx::ImageSkia& i1,
86 const gfx::ImageSkia& i2,
87 float scale) {
88 SkBitmap bitmap1 = i1.GetRepresentation(scale).sk_bitmap();
89 SkBitmap bitmap2 = i2.GetRepresentation(scale).sk_bitmap();
90 return gfx::BitmapsAreEqual(bitmap1, bitmap2);
91 }
92
93 class BrowserActionApiTest : public ExtensionApiTest { 72 class BrowserActionApiTest : public ExtensionApiTest {
94 public: 73 public:
95 BrowserActionApiTest() {} 74 BrowserActionApiTest() {}
96 ~BrowserActionApiTest() override {} 75 ~BrowserActionApiTest() override {}
97 76
98 protected: 77 protected:
99 BrowserActionTestUtil* GetBrowserActionsBar() { 78 BrowserActionTestUtil* GetBrowserActionsBar() {
100 if (!browser_action_test_util_) 79 if (!browser_action_test_util_)
101 browser_action_test_util_.reset(new BrowserActionTestUtil(browser())); 80 browser_action_test_util_.reset(new BrowserActionTestUtil(browser()));
102 return browser_action_test_util_.get(); 81 return browser_action_test_util_.get();
(...skipping 78 matching lines...)
181 ASSERT_EQ(1, GetBrowserActionsBar()->NumberOfBrowserActions()); 160 ASSERT_EQ(1, GetBrowserActionsBar()->NumberOfBrowserActions());
182 EXPECT_TRUE(GetBrowserActionsBar()->HasIcon(0)); 161 EXPECT_TRUE(GetBrowserActionsBar()->HasIcon(0));
183 162
184 gfx::Image action_icon = icon_factory.GetIcon(0); 163 gfx::Image action_icon = icon_factory.GetIcon(0);
185 uint32_t action_icon_last_id = action_icon.ToSkBitmap()->getGenerationID(); 164 uint32_t action_icon_last_id = action_icon.ToSkBitmap()->getGenerationID();
186 165
187 // Let's check that |GetIcon| doesn't always return bitmap with new id. 166 // Let's check that |GetIcon| doesn't always return bitmap with new id.
188 ASSERT_EQ(action_icon_last_id, 167 ASSERT_EQ(action_icon_last_id,
189 icon_factory.GetIcon(0).ToSkBitmap()->getGenerationID()); 168 icon_factory.GetIcon(0).ToSkBitmap()->getGenerationID());
190 169
191 uint32_t action_icon_current_id = 0; 170 gfx::Image last_bar_icon = GetBrowserActionsBar()->GetIcon(0);
171 EXPECT_TRUE(gfx::test::AreImagesEqual(last_bar_icon,
172 GetBrowserActionsBar()->GetIcon(0)));
192 173
193 ResultCatcher catcher; 174 // The reason we don't test more standard scales (like 1x, 2x, etc.) is that
175 // these may be generated from the provided scales.
176 float kSmallIconScale = 21.f / ExtensionAction::ActionIconSize();
177 float kLargeIconScale = 42.f / ExtensionAction::ActionIconSize();
178 ASSERT_FALSE(ui::IsSupportedScale(kSmallIconScale));
179 ASSERT_FALSE(ui::IsSupportedScale(kLargeIconScale));
194 180
195 // Tell the extension to update the icon using ImageData object. 181 // Tell the extension to update the icon using ImageData object.
182 ResultCatcher catcher;
196 GetBrowserActionsBar()->Press(0); 183 GetBrowserActionsBar()->Press(0);
197 ASSERT_TRUE(catcher.GetNextResult()); 184 ASSERT_TRUE(catcher.GetNextResult());
198 185
186 EXPECT_FALSE(gfx::test::AreImagesEqual(last_bar_icon,
187 GetBrowserActionsBar()->GetIcon(0)));
188 last_bar_icon = GetBrowserActionsBar()->GetIcon(0);
189
199 action_icon = icon_factory.GetIcon(0); 190 action_icon = icon_factory.GetIcon(0);
200 191 uint32_t action_icon_current_id = action_icon.ToSkBitmap()->getGenerationID();
201 action_icon_current_id = action_icon.ToSkBitmap()->getGenerationID();
202 EXPECT_GT(action_icon_current_id, action_icon_last_id); 192 EXPECT_GT(action_icon_current_id, action_icon_last_id);
203 action_icon_last_id = action_icon_current_id; 193 action_icon_last_id = action_icon_current_id;
204 194
205 EXPECT_FALSE(action_icon.ToImageSkia()->HasRepresentation(2.0f)); 195 EXPECT_TRUE(action_icon.ToImageSkia()->HasRepresentation(kSmallIconScale));
206 196 EXPECT_FALSE(action_icon.ToImageSkia()->HasRepresentation(kLargeIconScale));
207 EXPECT_TRUE(
208 ImagesAreEqualAtScale(AddBackground(*action_icon.ToImageSkia()),
209 *GetBrowserActionsBar()->GetIcon(0).ToImageSkia(),
210 1.0f));
211 197
212 // Tell the extension to update the icon using path. 198 // Tell the extension to update the icon using path.
213 GetBrowserActionsBar()->Press(0); 199 GetBrowserActionsBar()->Press(0);
214 ASSERT_TRUE(catcher.GetNextResult()); 200 ASSERT_TRUE(catcher.GetNextResult());
215 201
202 // Make sure the browser action bar updated.
203 EXPECT_FALSE(gfx::test::AreImagesEqual(last_bar_icon,
204 GetBrowserActionsBar()->GetIcon(0)));
205 last_bar_icon = GetBrowserActionsBar()->GetIcon(0);
206
207
Devlin 2016/01/19 22:44:40 extra newline
Evan Stade 2016/01/20 23:04:36 Done.
216 action_icon = icon_factory.GetIcon(0); 208 action_icon = icon_factory.GetIcon(0);
217
218 action_icon_current_id = action_icon.ToSkBitmap()->getGenerationID(); 209 action_icon_current_id = action_icon.ToSkBitmap()->getGenerationID();
219 EXPECT_GT(action_icon_current_id, action_icon_last_id); 210 EXPECT_GT(action_icon_current_id, action_icon_last_id);
220 action_icon_last_id = action_icon_current_id; 211 action_icon_last_id = action_icon_current_id;
221 212
222 EXPECT_FALSE( 213 EXPECT_TRUE(action_icon.ToImageSkia()->HasRepresentation(kSmallIconScale));
Devlin 2016/01/19 22:44:40 nit: please comment above these why we expect/don'
Evan Stade 2016/01/20 23:04:36 done, also see comment above the kSmallIconScale d
223 action_icon.ToImageSkia()->HasRepresentation(2.0f)); 214 EXPECT_FALSE(action_icon.ToImageSkia()->HasRepresentation(kLargeIconScale));
224
225 EXPECT_TRUE(
226 ImagesAreEqualAtScale(AddBackground(*action_icon.ToImageSkia()),
227 *GetBrowserActionsBar()->GetIcon(0).ToImageSkia(),
228 1.0f));
229 215
230 // Tell the extension to update the icon using dictionary of ImageData 216 // Tell the extension to update the icon using dictionary of ImageData
231 // objects. 217 // objects.
232 GetBrowserActionsBar()->Press(0); 218 GetBrowserActionsBar()->Press(0);
233 ASSERT_TRUE(catcher.GetNextResult()); 219 ASSERT_TRUE(catcher.GetNextResult());
234 220
221 EXPECT_FALSE(gfx::test::AreImagesEqual(last_bar_icon,
222 GetBrowserActionsBar()->GetIcon(0)));
223 last_bar_icon = GetBrowserActionsBar()->GetIcon(0);
224
235 action_icon = icon_factory.GetIcon(0); 225 action_icon = icon_factory.GetIcon(0);
236
237 action_icon_current_id = action_icon.ToSkBitmap()->getGenerationID(); 226 action_icon_current_id = action_icon.ToSkBitmap()->getGenerationID();
238 EXPECT_GT(action_icon_current_id, action_icon_last_id); 227 EXPECT_GT(action_icon_current_id, action_icon_last_id);
239 action_icon_last_id = action_icon_current_id; 228 action_icon_last_id = action_icon_current_id;
240 229
241 EXPECT_TRUE(action_icon.ToImageSkia()->HasRepresentation(2.0f)); 230 EXPECT_TRUE(action_icon.ToImageSkia()->HasRepresentation(kSmallIconScale));
242 231 EXPECT_TRUE(action_icon.ToImageSkia()->HasRepresentation(kLargeIconScale));
243 EXPECT_TRUE(
244 ImagesAreEqualAtScale(AddBackground(*action_icon.ToImageSkia()),
245 *GetBrowserActionsBar()->GetIcon(0).ToImageSkia(),
246 1.0f));
247 232
248 // Tell the extension to update the icon using dictionary of paths. 233 // Tell the extension to update the icon using dictionary of paths.
249 GetBrowserActionsBar()->Press(0); 234 GetBrowserActionsBar()->Press(0);
250 ASSERT_TRUE(catcher.GetNextResult()); 235 ASSERT_TRUE(catcher.GetNextResult());
251 236
237 EXPECT_FALSE(gfx::test::AreImagesEqual(last_bar_icon,
238 GetBrowserActionsBar()->GetIcon(0)));
239 last_bar_icon = GetBrowserActionsBar()->GetIcon(0);
240
252 action_icon = icon_factory.GetIcon(0); 241 action_icon = icon_factory.GetIcon(0);
253
254 action_icon_current_id = action_icon.ToSkBitmap()->getGenerationID(); 242 action_icon_current_id = action_icon.ToSkBitmap()->getGenerationID();
255 EXPECT_GT(action_icon_current_id, action_icon_last_id); 243 EXPECT_GT(action_icon_current_id, action_icon_last_id);
256 action_icon_last_id = action_icon_current_id; 244 action_icon_last_id = action_icon_current_id;
257 245
258 EXPECT_TRUE(action_icon.ToImageSkia()->HasRepresentation(2.0f)); 246 EXPECT_TRUE(action_icon.ToImageSkia()->HasRepresentation(kSmallIconScale));
259 247 EXPECT_TRUE(action_icon.ToImageSkia()->HasRepresentation(kLargeIconScale));
260 EXPECT_TRUE(
261 ImagesAreEqualAtScale(AddBackground(*action_icon.ToImageSkia()),
262 *GetBrowserActionsBar()->GetIcon(0).ToImageSkia(),
263 1.0f));
264 248
265 // Tell the extension to update the icon using dictionary of ImageData 249 // Tell the extension to update the icon using dictionary of ImageData
266 // objects, but setting only size 19. 250 // objects, but setting only size 19.
267 GetBrowserActionsBar()->Press(0); 251 GetBrowserActionsBar()->Press(0);
268 ASSERT_TRUE(catcher.GetNextResult()); 252 ASSERT_TRUE(catcher.GetNextResult());
269 253
254 EXPECT_FALSE(gfx::test::AreImagesEqual(last_bar_icon,
255 GetBrowserActionsBar()->GetIcon(0)));
256 last_bar_icon = GetBrowserActionsBar()->GetIcon(0);
257
270 action_icon = icon_factory.GetIcon(0); 258 action_icon = icon_factory.GetIcon(0);
271
272 action_icon_current_id = action_icon.ToSkBitmap()->getGenerationID(); 259 action_icon_current_id = action_icon.ToSkBitmap()->getGenerationID();
273 EXPECT_GT(action_icon_current_id, action_icon_last_id); 260 EXPECT_GT(action_icon_current_id, action_icon_last_id);
274 action_icon_last_id = action_icon_current_id; 261 action_icon_last_id = action_icon_current_id;
275 262
276 EXPECT_FALSE(action_icon.ToImageSkia()->HasRepresentation(2.0f)); 263 EXPECT_TRUE(action_icon.ToImageSkia()->HasRepresentation(kSmallIconScale));
277 264 EXPECT_FALSE(action_icon.ToImageSkia()->HasRepresentation(kLargeIconScale));
278 EXPECT_TRUE(
279 ImagesAreEqualAtScale(AddBackground(*action_icon.ToImageSkia()),
280 *GetBrowserActionsBar()->GetIcon(0).ToImageSkia(),
281 1.0f));
282 265
283 // Tell the extension to update the icon using dictionary of paths, but 266 // Tell the extension to update the icon using dictionary of paths, but
284 // setting only size 19. 267 // setting only size 19.
Devlin 2016/01/19 22:44:40 These comments (also on line 250) need to be updat
Evan Stade 2016/01/20 23:04:36 Done.
285 GetBrowserActionsBar()->Press(0); 268 GetBrowserActionsBar()->Press(0);
286 ASSERT_TRUE(catcher.GetNextResult()); 269 ASSERT_TRUE(catcher.GetNextResult());
287 270
271 EXPECT_FALSE(gfx::test::AreImagesEqual(last_bar_icon,
272 GetBrowserActionsBar()->GetIcon(0)));
273 last_bar_icon = GetBrowserActionsBar()->GetIcon(0);
274
288 action_icon = icon_factory.GetIcon(0); 275 action_icon = icon_factory.GetIcon(0);
289
290 action_icon_current_id = action_icon.ToSkBitmap()->getGenerationID(); 276 action_icon_current_id = action_icon.ToSkBitmap()->getGenerationID();
291 EXPECT_GT(action_icon_current_id, action_icon_last_id); 277 EXPECT_GT(action_icon_current_id, action_icon_last_id);
292 action_icon_last_id = action_icon_current_id; 278 action_icon_last_id = action_icon_current_id;
293 279
294 EXPECT_FALSE(action_icon.ToImageSkia()->HasRepresentation(2.0f)); 280 EXPECT_TRUE(action_icon.ToImageSkia()->HasRepresentation(kSmallIconScale));
295 281 EXPECT_FALSE(action_icon.ToImageSkia()->HasRepresentation(kLargeIconScale));
296 EXPECT_TRUE(
297 ImagesAreEqualAtScale(AddBackground(*action_icon.ToImageSkia()),
298 *GetBrowserActionsBar()->GetIcon(0).ToImageSkia(),
299 1.0f));
300 282
301 // Tell the extension to update the icon using dictionary of ImageData 283 // Tell the extension to update the icon using dictionary of ImageData
302 // objects, but setting only size 38. 284 // objects, but setting only size 42.
303 GetBrowserActionsBar()->Press(0); 285 GetBrowserActionsBar()->Press(0);
304 ASSERT_TRUE(catcher.GetNextResult()); 286 ASSERT_TRUE(catcher.GetNextResult());
305 287
288 EXPECT_FALSE(gfx::test::AreImagesEqual(last_bar_icon,
289 GetBrowserActionsBar()->GetIcon(0)));
290 last_bar_icon = GetBrowserActionsBar()->GetIcon(0);
291
306 action_icon = icon_factory.GetIcon(0); 292 action_icon = icon_factory.GetIcon(0);
307
308 const gfx::ImageSkia* action_icon_skia = action_icon.ToImageSkia();
309
310 EXPECT_FALSE(action_icon_skia->HasRepresentation(1.0f));
311 EXPECT_TRUE(action_icon_skia->HasRepresentation(2.0f));
312
313 action_icon_current_id = action_icon.ToSkBitmap()->getGenerationID(); 293 action_icon_current_id = action_icon.ToSkBitmap()->getGenerationID();
314 EXPECT_GT(action_icon_current_id, action_icon_last_id); 294 EXPECT_GT(action_icon_current_id, action_icon_last_id);
315 action_icon_last_id = action_icon_current_id; 295 action_icon_last_id = action_icon_current_id;
316 296
317 EXPECT_TRUE(gfx::BitmapsAreEqual( 297 EXPECT_FALSE(action_icon.ToImageSkia()->HasRepresentation(kSmallIconScale));
318 *action_icon.ToSkBitmap(), 298 EXPECT_TRUE(action_icon.ToImageSkia()->HasRepresentation(kLargeIconScale));
319 action_icon_skia->GetRepresentation(2.0f).sk_bitmap()));
320
321 EXPECT_TRUE(
322 ImagesAreEqualAtScale(AddBackground(*action_icon_skia),
323 *GetBrowserActionsBar()->GetIcon(0).ToImageSkia(),
324 2.0f));
325 299
326 // Try setting icon with empty dictionary of ImageData objects. 300 // Try setting icon with empty dictionary of ImageData objects.
327 GetBrowserActionsBar()->Press(0); 301 GetBrowserActionsBar()->Press(0);
328 ASSERT_FALSE(catcher.GetNextResult()); 302 ASSERT_FALSE(catcher.GetNextResult());
329 EXPECT_EQ(kEmptyImageDataError, catcher.message()); 303 EXPECT_EQ(kEmptyImageDataError, catcher.message());
330 304
331 // Try setting icon with empty dictionary of path objects. 305 // Try setting icon with empty dictionary of path objects.
332 GetBrowserActionsBar()->Press(0); 306 GetBrowserActionsBar()->Press(0);
333 ASSERT_FALSE(catcher.GetNextResult()); 307 ASSERT_FALSE(catcher.GetNextResult());
334 EXPECT_EQ(kEmptyPathError, catcher.message()); 308 EXPECT_EQ(kEmptyPathError, catcher.message());
(...skipping 395 matching lines...)
730 std::string result; 704 std::string result;
731 EXPECT_TRUE( 705 EXPECT_TRUE(
732 content::ExecuteScriptAndExtractString(frame_host, script, &result)); 706 content::ExecuteScriptAndExtractString(frame_host, script, &result));
733 EXPECT_EQ("DONE", result); 707 EXPECT_EQ("DONE", result);
734 708
735 EXPECT_TRUE(actions_bar->HidePopup()); 709 EXPECT_TRUE(actions_bar->HidePopup());
736 } 710 }
737 711
738 } // namespace 712 } // namespace
739 } // namespace extensions 713 } // namespace extensions
OLDNEW

Powered by Google App Engine