Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1032)

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

Issue 1647903003: Fix the dynamic browser action setIcon path to work with any size icon. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@2623
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | chrome/browser/extensions/extension_action.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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...) Expand all
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 // Makes sure |bar_rendering| has |model_icon| in the middle (there's additional
72 // Macs don't, but still need a 29x29-sized image (and the easiest way to do 73 // padding that correlates to the rest of the button, and this is ignored).
73 // that is to superimpose the icon over a blank background). 74 void VerifyIconsMatch(const gfx::Image& bar_rendering,
74 gfx::ImageSkia AddBackground(const gfx::ImageSkia& icon) { 75 const gfx::Image& model_icon) {
75 #if !defined(OS_MACOSX) 76 gfx::Rect icon_portion(gfx::Point(), bar_rendering.Size());
76 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 77 icon_portion.ClampToCenteredSize(model_icon.Size());
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 78
85 bool ImagesAreEqualAtScale(const gfx::ImageSkia& i1, 79 EXPECT_TRUE(gfx::test::AreBitmapsEqual(
86 const gfx::ImageSkia& i2, 80 model_icon.AsImageSkia().GetRepresentation(1.0f).sk_bitmap(),
87 float scale) { 81 gfx::ImageSkiaOperations::ExtractSubset(bar_rendering.AsImageSkia(),
88 SkBitmap bitmap1 = i1.GetRepresentation(scale).sk_bitmap(); 82 icon_portion)
89 SkBitmap bitmap2 = i2.GetRepresentation(scale).sk_bitmap(); 83 .GetRepresentation(1.0f)
90 return gfx::BitmapsAreEqual(bitmap1, bitmap2); 84 .sk_bitmap()));
91 } 85 }
92 86
93 class BrowserActionApiTest : public ExtensionApiTest { 87 class BrowserActionApiTest : public ExtensionApiTest {
94 public: 88 public:
95 BrowserActionApiTest() {} 89 BrowserActionApiTest() {}
96 ~BrowserActionApiTest() override {} 90 ~BrowserActionApiTest() override {}
97 91
98 protected: 92 protected:
99 BrowserActionTestUtil* GetBrowserActionsBar() { 93 BrowserActionTestUtil* GetBrowserActionsBar() {
100 if (!browser_action_test_util_) 94 if (!browser_action_test_util_)
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 ASSERT_EQ(1, GetBrowserActionsBar()->NumberOfBrowserActions()); 175 ASSERT_EQ(1, GetBrowserActionsBar()->NumberOfBrowserActions());
182 EXPECT_TRUE(GetBrowserActionsBar()->HasIcon(0)); 176 EXPECT_TRUE(GetBrowserActionsBar()->HasIcon(0));
183 177
184 gfx::Image action_icon = icon_factory.GetIcon(0); 178 gfx::Image action_icon = icon_factory.GetIcon(0);
185 uint32_t action_icon_last_id = action_icon.ToSkBitmap()->getGenerationID(); 179 uint32_t action_icon_last_id = action_icon.ToSkBitmap()->getGenerationID();
186 180
187 // Let's check that |GetIcon| doesn't always return bitmap with new id. 181 // Let's check that |GetIcon| doesn't always return bitmap with new id.
188 ASSERT_EQ(action_icon_last_id, 182 ASSERT_EQ(action_icon_last_id,
189 icon_factory.GetIcon(0).ToSkBitmap()->getGenerationID()); 183 icon_factory.GetIcon(0).ToSkBitmap()->getGenerationID());
190 184
191 uint32_t action_icon_current_id = 0; 185 gfx::Image last_bar_icon = GetBrowserActionsBar()->GetIcon(0);
186 EXPECT_TRUE(gfx::test::AreImagesEqual(last_bar_icon,
187 GetBrowserActionsBar()->GetIcon(0)));
192 188
193 ResultCatcher catcher; 189 // The reason we don't test more standard scales (like 1x, 2x, etc.) is that
190 // these may be generated from the provided scales.
191 float kSmallIconScale = 21.f / ExtensionAction::ActionIconSize();
192 float kLargeIconScale = 42.f / ExtensionAction::ActionIconSize();
193 ASSERT_FALSE(ui::IsSupportedScale(kSmallIconScale));
194 ASSERT_FALSE(ui::IsSupportedScale(kLargeIconScale));
194 195
195 // Tell the extension to update the icon using ImageData object. 196 // Tell the extension to update the icon using ImageData object.
197 ResultCatcher catcher;
196 GetBrowserActionsBar()->Press(0); 198 GetBrowserActionsBar()->Press(0);
197 ASSERT_TRUE(catcher.GetNextResult()); 199 ASSERT_TRUE(catcher.GetNextResult());
198 200
201 EXPECT_FALSE(gfx::test::AreImagesEqual(last_bar_icon,
202 GetBrowserActionsBar()->GetIcon(0)));
203 last_bar_icon = GetBrowserActionsBar()->GetIcon(0);
204
199 action_icon = icon_factory.GetIcon(0); 205 action_icon = icon_factory.GetIcon(0);
200 206 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); 207 EXPECT_GT(action_icon_current_id, action_icon_last_id);
203 action_icon_last_id = action_icon_current_id; 208 action_icon_last_id = action_icon_current_id;
209 VerifyIconsMatch(last_bar_icon, action_icon);
204 210
205 EXPECT_FALSE(action_icon.ToImageSkia()->HasRepresentation(2.0f)); 211 // Check that only the smaller size was set (only a 21px icon was provided).
206 212 EXPECT_TRUE(action_icon.ToImageSkia()->HasRepresentation(kSmallIconScale));
207 EXPECT_TRUE( 213 EXPECT_FALSE(action_icon.ToImageSkia()->HasRepresentation(kLargeIconScale));
208 ImagesAreEqualAtScale(AddBackground(*action_icon.ToImageSkia()),
209 *GetBrowserActionsBar()->GetIcon(0).ToImageSkia(),
210 1.0f));
211 214
212 // Tell the extension to update the icon using path. 215 // Tell the extension to update the icon using path.
213 GetBrowserActionsBar()->Press(0); 216 GetBrowserActionsBar()->Press(0);
214 ASSERT_TRUE(catcher.GetNextResult()); 217 ASSERT_TRUE(catcher.GetNextResult());
215 218
219 // Make sure the browser action bar updated.
220 EXPECT_FALSE(gfx::test::AreImagesEqual(last_bar_icon,
221 GetBrowserActionsBar()->GetIcon(0)));
222 last_bar_icon = GetBrowserActionsBar()->GetIcon(0);
223
216 action_icon = icon_factory.GetIcon(0); 224 action_icon = icon_factory.GetIcon(0);
217
218 action_icon_current_id = action_icon.ToSkBitmap()->getGenerationID(); 225 action_icon_current_id = action_icon.ToSkBitmap()->getGenerationID();
219 EXPECT_GT(action_icon_current_id, action_icon_last_id); 226 EXPECT_GT(action_icon_current_id, action_icon_last_id);
220 action_icon_last_id = action_icon_current_id; 227 action_icon_last_id = action_icon_current_id;
228 VerifyIconsMatch(last_bar_icon, action_icon);
221 229
222 EXPECT_FALSE( 230 // Check that only the smaller size was set (only a 21px icon was provided).
223 action_icon.ToImageSkia()->HasRepresentation(2.0f)); 231 EXPECT_TRUE(action_icon.ToImageSkia()->HasRepresentation(kSmallIconScale));
224 232 EXPECT_FALSE(action_icon.ToImageSkia()->HasRepresentation(kLargeIconScale));
225 EXPECT_TRUE(
226 ImagesAreEqualAtScale(AddBackground(*action_icon.ToImageSkia()),
227 *GetBrowserActionsBar()->GetIcon(0).ToImageSkia(),
228 1.0f));
229 233
230 // Tell the extension to update the icon using dictionary of ImageData 234 // Tell the extension to update the icon using dictionary of ImageData
231 // objects. 235 // objects.
232 GetBrowserActionsBar()->Press(0); 236 GetBrowserActionsBar()->Press(0);
233 ASSERT_TRUE(catcher.GetNextResult()); 237 ASSERT_TRUE(catcher.GetNextResult());
234 238
239 EXPECT_FALSE(gfx::test::AreImagesEqual(last_bar_icon,
240 GetBrowserActionsBar()->GetIcon(0)));
241 last_bar_icon = GetBrowserActionsBar()->GetIcon(0);
242
235 action_icon = icon_factory.GetIcon(0); 243 action_icon = icon_factory.GetIcon(0);
236
237 action_icon_current_id = action_icon.ToSkBitmap()->getGenerationID(); 244 action_icon_current_id = action_icon.ToSkBitmap()->getGenerationID();
238 EXPECT_GT(action_icon_current_id, action_icon_last_id); 245 EXPECT_GT(action_icon_current_id, action_icon_last_id);
239 action_icon_last_id = action_icon_current_id; 246 action_icon_last_id = action_icon_current_id;
247 VerifyIconsMatch(last_bar_icon, action_icon);
240 248
241 EXPECT_TRUE(action_icon.ToImageSkia()->HasRepresentation(2.0f)); 249 // Check both sizes were set (as two icon sizes were provided).
242 250 EXPECT_TRUE(action_icon.ToImageSkia()->HasRepresentation(kSmallIconScale));
243 EXPECT_TRUE( 251 EXPECT_TRUE(action_icon.AsImageSkia().HasRepresentation(kLargeIconScale));
244 ImagesAreEqualAtScale(AddBackground(*action_icon.ToImageSkia()),
245 *GetBrowserActionsBar()->GetIcon(0).ToImageSkia(),
246 1.0f));
247 252
248 // Tell the extension to update the icon using dictionary of paths. 253 // Tell the extension to update the icon using dictionary of paths.
249 GetBrowserActionsBar()->Press(0); 254 GetBrowserActionsBar()->Press(0);
250 ASSERT_TRUE(catcher.GetNextResult()); 255 ASSERT_TRUE(catcher.GetNextResult());
251 256
257 EXPECT_FALSE(gfx::test::AreImagesEqual(last_bar_icon,
258 GetBrowserActionsBar()->GetIcon(0)));
259 last_bar_icon = GetBrowserActionsBar()->GetIcon(0);
260
252 action_icon = icon_factory.GetIcon(0); 261 action_icon = icon_factory.GetIcon(0);
262 action_icon_current_id = action_icon.ToSkBitmap()->getGenerationID();
263 EXPECT_GT(action_icon_current_id, action_icon_last_id);
264 action_icon_last_id = action_icon_current_id;
265 VerifyIconsMatch(last_bar_icon, action_icon);
253 266
267 // Check both sizes were set (as two icon sizes were provided).
268 EXPECT_TRUE(action_icon.ToImageSkia()->HasRepresentation(kSmallIconScale));
269 EXPECT_TRUE(action_icon.AsImageSkia().HasRepresentation(kLargeIconScale));
270
271 // Tell the extension to update the icon using dictionary of ImageData
272 // objects, but setting only one size.
273 GetBrowserActionsBar()->Press(0);
274 ASSERT_TRUE(catcher.GetNextResult());
275
276 EXPECT_FALSE(gfx::test::AreImagesEqual(last_bar_icon,
277 GetBrowserActionsBar()->GetIcon(0)));
278 last_bar_icon = GetBrowserActionsBar()->GetIcon(0);
279
280 action_icon = icon_factory.GetIcon(0);
281 action_icon_current_id = action_icon.ToSkBitmap()->getGenerationID();
282 EXPECT_GT(action_icon_current_id, action_icon_last_id);
283 action_icon_last_id = action_icon_current_id;
284 VerifyIconsMatch(last_bar_icon, action_icon);
285
286 // Check that only the smaller size was set (only a 21px icon was provided).
287 EXPECT_TRUE(action_icon.ToImageSkia()->HasRepresentation(kSmallIconScale));
288 EXPECT_FALSE(action_icon.ToImageSkia()->HasRepresentation(kLargeIconScale));
289
290 // Tell the extension to update the icon using dictionary of paths, but
291 // setting only one size.
292 GetBrowserActionsBar()->Press(0);
293 ASSERT_TRUE(catcher.GetNextResult());
294
295 EXPECT_FALSE(gfx::test::AreImagesEqual(last_bar_icon,
296 GetBrowserActionsBar()->GetIcon(0)));
297 last_bar_icon = GetBrowserActionsBar()->GetIcon(0);
298
299 action_icon = icon_factory.GetIcon(0);
300 action_icon_current_id = action_icon.ToSkBitmap()->getGenerationID();
301 EXPECT_GT(action_icon_current_id, action_icon_last_id);
302 action_icon_last_id = action_icon_current_id;
303 VerifyIconsMatch(last_bar_icon, action_icon);
304
305 // Check that only the smaller size was set (only a 21px icon was provided).
306 EXPECT_TRUE(action_icon.ToImageSkia()->HasRepresentation(kSmallIconScale));
307 EXPECT_FALSE(action_icon.ToImageSkia()->HasRepresentation(kLargeIconScale));
308
309 // Tell the extension to update the icon using dictionary of ImageData
310 // objects, but setting only size 42.
311 GetBrowserActionsBar()->Press(0);
312 ASSERT_TRUE(catcher.GetNextResult());
313
314 EXPECT_FALSE(gfx::test::AreImagesEqual(last_bar_icon,
315 GetBrowserActionsBar()->GetIcon(0)));
316 last_bar_icon = GetBrowserActionsBar()->GetIcon(0);
317
318 action_icon = icon_factory.GetIcon(0);
254 action_icon_current_id = action_icon.ToSkBitmap()->getGenerationID(); 319 action_icon_current_id = action_icon.ToSkBitmap()->getGenerationID();
255 EXPECT_GT(action_icon_current_id, action_icon_last_id); 320 EXPECT_GT(action_icon_current_id, action_icon_last_id);
256 action_icon_last_id = action_icon_current_id; 321 action_icon_last_id = action_icon_current_id;
257 322
258 EXPECT_TRUE(action_icon.ToImageSkia()->HasRepresentation(2.0f)); 323 // Check that only the larger size was set (only a 42px icon was provided).
259 324 EXPECT_FALSE(action_icon.ToImageSkia()->HasRepresentation(kSmallIconScale));
260 EXPECT_TRUE( 325 EXPECT_TRUE(action_icon.AsImageSkia().HasRepresentation(kLargeIconScale));
261 ImagesAreEqualAtScale(AddBackground(*action_icon.ToImageSkia()),
262 *GetBrowserActionsBar()->GetIcon(0).ToImageSkia(),
263 1.0f));
264
265 // Tell the extension to update the icon using dictionary of ImageData
266 // objects, but setting only size 19.
267 GetBrowserActionsBar()->Press(0);
268 ASSERT_TRUE(catcher.GetNextResult());
269
270 action_icon = icon_factory.GetIcon(0);
271
272 action_icon_current_id = action_icon.ToSkBitmap()->getGenerationID();
273 EXPECT_GT(action_icon_current_id, action_icon_last_id);
274 action_icon_last_id = action_icon_current_id;
275
276 EXPECT_FALSE(action_icon.ToImageSkia()->HasRepresentation(2.0f));
277
278 EXPECT_TRUE(
279 ImagesAreEqualAtScale(AddBackground(*action_icon.ToImageSkia()),
280 *GetBrowserActionsBar()->GetIcon(0).ToImageSkia(),
281 1.0f));
282
283 // Tell the extension to update the icon using dictionary of paths, but
284 // setting only size 19.
285 GetBrowserActionsBar()->Press(0);
286 ASSERT_TRUE(catcher.GetNextResult());
287
288 action_icon = icon_factory.GetIcon(0);
289
290 action_icon_current_id = action_icon.ToSkBitmap()->getGenerationID();
291 EXPECT_GT(action_icon_current_id, action_icon_last_id);
292 action_icon_last_id = action_icon_current_id;
293
294 EXPECT_FALSE(action_icon.ToImageSkia()->HasRepresentation(2.0f));
295
296 EXPECT_TRUE(
297 ImagesAreEqualAtScale(AddBackground(*action_icon.ToImageSkia()),
298 *GetBrowserActionsBar()->GetIcon(0).ToImageSkia(),
299 1.0f));
300
301 // Tell the extension to update the icon using dictionary of ImageData
302 // objects, but setting only size 38.
303 GetBrowserActionsBar()->Press(0);
304 ASSERT_TRUE(catcher.GetNextResult());
305
306 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();
314 EXPECT_GT(action_icon_current_id, action_icon_last_id);
315 action_icon_last_id = action_icon_current_id;
316
317 EXPECT_TRUE(gfx::BitmapsAreEqual(
318 *action_icon.ToSkBitmap(),
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 326
326 // Try setting icon with empty dictionary of ImageData objects. 327 // Try setting icon with empty dictionary of ImageData objects.
327 GetBrowserActionsBar()->Press(0); 328 GetBrowserActionsBar()->Press(0);
328 ASSERT_FALSE(catcher.GetNextResult()); 329 ASSERT_FALSE(catcher.GetNextResult());
329 EXPECT_EQ(kEmptyImageDataError, catcher.message()); 330 EXPECT_EQ(kEmptyImageDataError, catcher.message());
330 331
331 // Try setting icon with empty dictionary of path objects. 332 // Try setting icon with empty dictionary of path objects.
332 GetBrowserActionsBar()->Press(0); 333 GetBrowserActionsBar()->Press(0);
333 ASSERT_FALSE(catcher.GetNextResult()); 334 ASSERT_FALSE(catcher.GetNextResult());
334 EXPECT_EQ(kEmptyPathError, catcher.message()); 335 EXPECT_EQ(kEmptyPathError, catcher.message());
(...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after
730 std::string result; 731 std::string result;
731 EXPECT_TRUE( 732 EXPECT_TRUE(
732 content::ExecuteScriptAndExtractString(frame_host, script, &result)); 733 content::ExecuteScriptAndExtractString(frame_host, script, &result));
733 EXPECT_EQ("DONE", result); 734 EXPECT_EQ("DONE", result);
734 735
735 EXPECT_TRUE(actions_bar->HidePopup()); 736 EXPECT_TRUE(actions_bar->HidePopup());
736 } 737 }
737 738
738 } // namespace 739 } // namespace
739 } // namespace extensions 740 } // namespace extensions
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/extensions/extension_action.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698