• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/browser/android/shortcut_helper.h"
6 
7 #include "base/strings/utf_string_conversions.h"
8 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
9 #include "content/public/browser/web_contents.h"
10 #include "ui/gfx/screen.h"
11 #include "ui/gfx/screen_type_delegate.h"
12 
13 // A dummy implementation of gfx::Screen, since ShortcutHelper needs access to
14 // a gfx::Display's device scale factor.
15 // This is inspired by web_contents_video_capture_device_unittest.cc
16 // A bug has been opened to merge all those mocks: http://crbug.com/417227
17 class FakeScreen : public gfx::Screen {
18  public:
FakeScreen()19   FakeScreen() : display_(0x1337, gfx::Rect(0, 0, 2560, 1440)) {
20   }
~FakeScreen()21   virtual ~FakeScreen() {}
22 
SetDisplayDeviceScaleFactor(float device_scale_factor)23   void SetDisplayDeviceScaleFactor(float device_scale_factor) {
24     display_.set_device_scale_factor(device_scale_factor);
25   }
26 
27   // gfx::Screen implementation (only what's needed for testing).
IsDIPEnabled()28   virtual bool IsDIPEnabled() OVERRIDE { return true; }
GetCursorScreenPoint()29   virtual gfx::Point GetCursorScreenPoint() OVERRIDE { return gfx::Point(); }
GetWindowUnderCursor()30   virtual gfx::NativeWindow GetWindowUnderCursor() OVERRIDE { return NULL; }
GetWindowAtScreenPoint(const gfx::Point & point)31   virtual gfx::NativeWindow GetWindowAtScreenPoint(
32       const gfx::Point& point) OVERRIDE { return NULL; }
GetNumDisplays() const33   virtual int GetNumDisplays() const OVERRIDE { return 1; }
GetAllDisplays() const34   virtual std::vector<gfx::Display> GetAllDisplays() const OVERRIDE {
35     return std::vector<gfx::Display>(1, display_);
36   }
GetDisplayNearestWindow(gfx::NativeView view) const37   virtual gfx::Display GetDisplayNearestWindow(
38       gfx::NativeView view) const OVERRIDE {
39     return display_;
40   }
GetDisplayNearestPoint(const gfx::Point & point) const41   virtual gfx::Display GetDisplayNearestPoint(
42       const gfx::Point& point) const OVERRIDE {
43     return display_;
44   }
GetDisplayMatching(const gfx::Rect & match_rect) const45   virtual gfx::Display GetDisplayMatching(
46       const gfx::Rect& match_rect) const OVERRIDE {
47     return display_;
48   }
GetPrimaryDisplay() const49   virtual gfx::Display GetPrimaryDisplay() const OVERRIDE {
50     return display_;
51   }
AddObserver(gfx::DisplayObserver * observer)52   virtual void AddObserver(gfx::DisplayObserver* observer) OVERRIDE {}
RemoveObserver(gfx::DisplayObserver * observer)53   virtual void RemoveObserver(gfx::DisplayObserver* observer) OVERRIDE {}
54 
55  private:
56   gfx::Display display_;
57 
58   DISALLOW_COPY_AND_ASSIGN(FakeScreen);
59 };
60 
61 class ShortcutHelperTest : public ChromeRenderViewHostTestHarness  {
62  protected:
ShortcutHelperTest()63   ShortcutHelperTest() : shortcut_helper_(NULL) {}
~ShortcutHelperTest()64   virtual ~ShortcutHelperTest() {}
65 
CreateShortcutHelperJava(JNIEnv * env)66   static jobject CreateShortcutHelperJava(JNIEnv* env) {
67     jclass clazz = env->FindClass("org/chromium/chrome/browser/ShortcutHelper");
68     jmethodID constructor =
69         env->GetMethodID(clazz, "<init>",
70                          "(Landroid/content/Context;"
71                              "Lorg/chromium/chrome/browser/Tab;)V");
72     return env->NewObject(clazz, constructor, jobject(), jobject());
73   }
74 
ResetShorcutHelper()75   void ResetShorcutHelper() {
76     if (shortcut_helper_)
77       delete shortcut_helper_;
78 
79     JNIEnv* env = base::android::AttachCurrentThread();
80     shortcut_helper_ =
81         new ShortcutHelper(env, CreateShortcutHelperJava(env), web_contents());
82   }
83 
SetUp()84   virtual void SetUp() OVERRIDE {
85     gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, &fake_screen_);
86     ASSERT_EQ(&fake_screen_, gfx::Screen::GetNativeScreen());
87 
88     ChromeRenderViewHostTestHarness::SetUp();
89 
90     ResetShorcutHelper();
91   }
92 
TearDown()93   virtual void TearDown() OVERRIDE {
94     delete shortcut_helper_;
95     shortcut_helper_ = NULL;
96 
97     ChromeRenderViewHostTestHarness::TearDown();
98 
99     gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, NULL);
100   }
101 
FindBestMatchingIcon(const std::vector<content::Manifest::Icon> & icons)102   GURL FindBestMatchingIcon(const std::vector<content::Manifest::Icon>& icons) {
103     return shortcut_helper_->FindBestMatchingIcon(icons);
104   }
105 
SetDisplayDeviceScaleFactor(float device_scale_factor)106   void SetDisplayDeviceScaleFactor(float device_scale_factor) {
107     fake_screen_.SetDisplayDeviceScaleFactor(device_scale_factor);
108 
109     ResetShorcutHelper();
110   }
111 
GetPreferredIconSizeInDp()112   static int GetPreferredIconSizeInDp() {
113     return ShortcutHelper::kPreferredIconSizeInDp;
114   }
115 
CreateIcon(const std::string & url,const std::string & type,double density,const std::vector<gfx::Size> sizes)116   static content::Manifest::Icon CreateIcon(
117       const std::string& url,
118       const std::string& type,
119       double density,
120       const std::vector<gfx::Size> sizes) {
121     content::Manifest::Icon icon;
122     icon.src = GURL(url);
123     if (!type.empty())
124       icon.type = base::NullableString16(base::UTF8ToUTF16(type), false);
125     icon.density = density;
126     icon.sizes = sizes;
127 
128     return icon;
129   }
130 
131  private:
132   ShortcutHelper* shortcut_helper_;
133   FakeScreen fake_screen_;
134 
135   DISALLOW_COPY_AND_ASSIGN(ShortcutHelperTest);
136 };
137 
TEST_F(ShortcutHelperTest,NoIcons)138 TEST_F(ShortcutHelperTest, NoIcons) {
139   // No icons should return the empty URL.
140   std::vector<content::Manifest::Icon> icons;
141   GURL url = FindBestMatchingIcon(icons);
142   EXPECT_TRUE(url.is_empty());
143 }
144 
TEST_F(ShortcutHelperTest,NoSizes)145 TEST_F(ShortcutHelperTest, NoSizes) {
146   // Icon with no sizes are ignored.
147   std::vector<content::Manifest::Icon> icons;
148   icons.push_back(
149       CreateIcon("http://foo.com/icon.png", "", 1.0, std::vector<gfx::Size>()));
150 
151   GURL url = FindBestMatchingIcon(icons);
152   EXPECT_TRUE(url.is_empty());
153 }
154 
TEST_F(ShortcutHelperTest,MIMETypeFiltering)155 TEST_F(ShortcutHelperTest, MIMETypeFiltering) {
156   // Icons with type specified to a MIME type that isn't a valid image MIME type
157   // are ignored.
158   std::vector<gfx::Size> sizes;
159   sizes.push_back(gfx::Size(10, 10));
160 
161   std::vector<content::Manifest::Icon> icons;
162   icons.push_back(
163       CreateIcon("http://foo.com/icon.png", "image/foo_bar", 1.0, sizes));
164   icons.push_back(CreateIcon("http://foo.com/icon.png", "image/", 1.0, sizes));
165   icons.push_back(CreateIcon("http://foo.com/icon.png", "image/", 1.0, sizes));
166   icons.push_back(
167       CreateIcon("http://foo.com/icon.png", "video/mp4", 1.0, sizes));
168 
169   GURL url = FindBestMatchingIcon(icons);
170   EXPECT_TRUE(url.is_empty());
171 
172   icons.clear();
173   icons.push_back(
174       CreateIcon("http://foo.com/icon.png", "image/png", 1.0, sizes));
175   url = FindBestMatchingIcon(icons);
176   EXPECT_EQ("http://foo.com/icon.png", url.spec());
177 
178   icons.clear();
179   icons.push_back(
180       CreateIcon("http://foo.com/icon.png", "image/gif", 1.0, sizes));
181   url = FindBestMatchingIcon(icons);
182   EXPECT_EQ("http://foo.com/icon.png", url.spec());
183 
184   icons.clear();
185   icons.push_back(
186       CreateIcon("http://foo.com/icon.png", "image/jpeg", 1.0, sizes));
187   url = FindBestMatchingIcon(icons);
188   EXPECT_EQ("http://foo.com/icon.png", url.spec());
189 }
190 
TEST_F(ShortcutHelperTest,PreferredSizeOfCurrentDensityIsUsedFirst)191 TEST_F(ShortcutHelperTest, PreferredSizeOfCurrentDensityIsUsedFirst) {
192   // This test has three icons each are marked with sizes set to the preferred
193   // icon size for the associated density.
194   std::vector<gfx::Size> sizes_1;
195   sizes_1.push_back(gfx::Size(GetPreferredIconSizeInDp(),
196                               GetPreferredIconSizeInDp()));
197 
198   std::vector<gfx::Size> sizes_2;
199   sizes_2.push_back(gfx::Size(GetPreferredIconSizeInDp() * 2,
200                               GetPreferredIconSizeInDp() * 2));
201 
202   std::vector<gfx::Size> sizes_3;
203   sizes_3.push_back(gfx::Size(GetPreferredIconSizeInDp() * 3,
204                               GetPreferredIconSizeInDp() * 3));
205 
206   std::vector<content::Manifest::Icon> icons;
207   icons.push_back(CreateIcon("http://foo.com/icon_x1.png", "", 1.0, sizes_1));
208   icons.push_back(CreateIcon("http://foo.com/icon_x2.png", "", 2.0, sizes_2));
209   icons.push_back(CreateIcon("http://foo.com/icon_x3.png", "", 3.0, sizes_3));
210 
211   SetDisplayDeviceScaleFactor(1.0f);
212   GURL url = FindBestMatchingIcon(icons);
213   EXPECT_EQ("http://foo.com/icon_x1.png", url.spec());
214 
215   SetDisplayDeviceScaleFactor(2.0f);
216   url = FindBestMatchingIcon(icons);
217   EXPECT_EQ("http://foo.com/icon_x2.png", url.spec());
218 
219   SetDisplayDeviceScaleFactor(3.0f);
220   url = FindBestMatchingIcon(icons);
221   EXPECT_EQ("http://foo.com/icon_x3.png", url.spec());
222 }
223 
TEST_F(ShortcutHelperTest,PreferredSizeOfDefaultDensityIsUsedSecond)224 TEST_F(ShortcutHelperTest, PreferredSizeOfDefaultDensityIsUsedSecond) {
225   // This test has three icons. The first one is of density zero and is marked
226   // with three sizes which are the preferred icon size for density 1, 2 and 3.
227   // The icon for density 2 and 3 have a size set to 2x2 and 3x3.
228   // Regardless of the device scale factor, the icon of density 1 is going to be
229   // used because it matches the preferred size.
230   std::vector<gfx::Size> sizes_1;
231   sizes_1.push_back(gfx::Size(GetPreferredIconSizeInDp(),
232                               GetPreferredIconSizeInDp()));
233   sizes_1.push_back(gfx::Size(GetPreferredIconSizeInDp() * 2,
234                               GetPreferredIconSizeInDp() * 2));
235   sizes_1.push_back(gfx::Size(GetPreferredIconSizeInDp() * 3,
236                               GetPreferredIconSizeInDp() * 3));
237 
238   std::vector<gfx::Size> sizes_2;
239   sizes_2.push_back(gfx::Size(2, 2));
240 
241   std::vector<gfx::Size> sizes_3;
242   sizes_3.push_back(gfx::Size(3, 3));
243 
244   std::vector<content::Manifest::Icon> icons;
245   icons.push_back(CreateIcon("http://foo.com/icon_x1.png", "", 1.0, sizes_1));
246   icons.push_back(CreateIcon("http://foo.com/icon_x2.png", "", 2.0, sizes_2));
247   icons.push_back(CreateIcon("http://foo.com/icon_x3.png", "", 3.0, sizes_3));
248 
249   SetDisplayDeviceScaleFactor(1.0f);
250   GURL url = FindBestMatchingIcon(icons);
251   EXPECT_EQ("http://foo.com/icon_x1.png", url.spec());
252 
253   SetDisplayDeviceScaleFactor(2.0f);
254   url = FindBestMatchingIcon(icons);
255   EXPECT_EQ("http://foo.com/icon_x1.png", url.spec());
256 
257   SetDisplayDeviceScaleFactor(3.0f);
258   url = FindBestMatchingIcon(icons);
259   EXPECT_EQ("http://foo.com/icon_x1.png", url.spec());
260 }
261 
TEST_F(ShortcutHelperTest,DeviceDensityFirst)262 TEST_F(ShortcutHelperTest, DeviceDensityFirst) {
263   // If there is no perfect icon but an icon of the current device density is
264   // present, it will be picked.
265   // This test has three icons each are marked with sizes set to the preferred
266   // icon size for the associated density.
267   std::vector<gfx::Size> sizes;
268   sizes.push_back(gfx::Size(2, 2));
269 
270   std::vector<content::Manifest::Icon> icons;
271   icons.push_back(CreateIcon("http://foo.com/icon_x1.png", "", 1.0, sizes));
272   icons.push_back(CreateIcon("http://foo.com/icon_x2.png", "", 2.0, sizes));
273   icons.push_back(CreateIcon("http://foo.com/icon_x3.png", "", 3.0, sizes));
274 
275   SetDisplayDeviceScaleFactor(1.0f);
276   GURL url = FindBestMatchingIcon(icons);
277   EXPECT_EQ("http://foo.com/icon_x1.png", url.spec());
278 
279   SetDisplayDeviceScaleFactor(2.0f);
280   url = FindBestMatchingIcon(icons);
281   EXPECT_EQ("http://foo.com/icon_x2.png", url.spec());
282 
283   SetDisplayDeviceScaleFactor(3.0f);
284   url = FindBestMatchingIcon(icons);
285   EXPECT_EQ("http://foo.com/icon_x3.png", url.spec());
286 }
287 
TEST_F(ShortcutHelperTest,DeviceDensityFallback)288 TEST_F(ShortcutHelperTest, DeviceDensityFallback) {
289   // If there is no perfect icon but and no icon of the current display density,
290   // an icon of density 1.0 will be used.
291   std::vector<gfx::Size> sizes;
292   sizes.push_back(gfx::Size(2, 2));
293 
294   std::vector<content::Manifest::Icon> icons;
295   icons.push_back(CreateIcon("http://foo.com/icon_x1.png", "", 1.0, sizes));
296   icons.push_back(CreateIcon("http://foo.com/icon_x2.png", "", 2.0, sizes));
297 
298   SetDisplayDeviceScaleFactor(3.0f);
299   GURL url = FindBestMatchingIcon(icons);
300   EXPECT_EQ("http://foo.com/icon_x1.png", url.spec());
301 }
302 
TEST_F(ShortcutHelperTest,DoNotUseOtherDensities)303 TEST_F(ShortcutHelperTest, DoNotUseOtherDensities) {
304   // If there are only icons of densities that are not the current display
305   // density or the default density, they are ignored.
306   std::vector<gfx::Size> sizes;
307   sizes.push_back(gfx::Size(2, 2));
308 
309   std::vector<content::Manifest::Icon> icons;
310   icons.push_back(CreateIcon("http://foo.com/icon_x2.png", "", 2.0, sizes));
311 
312   SetDisplayDeviceScaleFactor(3.0f);
313   GURL url = FindBestMatchingIcon(icons);
314   EXPECT_TRUE(url.is_empty());
315 }
316 
TEST_F(ShortcutHelperTest,NotSquareIconsAreIgnored)317 TEST_F(ShortcutHelperTest, NotSquareIconsAreIgnored) {
318   std::vector<gfx::Size> sizes;
319   sizes.push_back(gfx::Size(20, 2));
320 
321   std::vector<content::Manifest::Icon> icons;
322   icons.push_back(CreateIcon("http://foo.com/icon.png", "", 1.0, sizes));
323 
324   GURL url = FindBestMatchingIcon(icons);
325   EXPECT_TRUE(url.is_empty());
326 }
327 
TEST_F(ShortcutHelperTest,ClosestIconToPreferred)328 TEST_F(ShortcutHelperTest, ClosestIconToPreferred) {
329   // This test verifies ShortcutHelper::FindBestMatchingIcon by passing
330   // different icon sizes and checking which one is picked.
331   // The Device Scale Factor is 1.0 and the preferred icon size is returned by
332   // GetPreferredIconSizeInDp().
333   int very_small = GetPreferredIconSizeInDp() / 4;
334   int small = GetPreferredIconSizeInDp() / 2;
335   int bit_small = GetPreferredIconSizeInDp() - 1;
336   int bit_big = GetPreferredIconSizeInDp() + 1;
337   int big = GetPreferredIconSizeInDp() * 2;
338   int very_big = GetPreferredIconSizeInDp() * 4;
339 
340   // (very_small, bit_small) => bit_small
341   {
342     std::vector<gfx::Size> sizes_1;
343     sizes_1.push_back(gfx::Size(very_small, very_small));
344 
345     std::vector<gfx::Size> sizes_2;
346     sizes_2.push_back(gfx::Size(bit_small, bit_small));
347 
348     std::vector<content::Manifest::Icon> icons;
349     icons.push_back(CreateIcon("http://foo.com/icon_no.png", "", 1.0, sizes_1));
350     icons.push_back(CreateIcon("http://foo.com/icon.png", "", 1.0, sizes_2));
351 
352     GURL url = FindBestMatchingIcon(icons);
353     EXPECT_EQ("http://foo.com/icon.png", url.spec());
354   }
355 
356   // (very_small, bit_small, smaller) => bit_small
357   {
358     std::vector<gfx::Size> sizes_1;
359     sizes_1.push_back(gfx::Size(very_small, very_small));
360 
361     std::vector<gfx::Size> sizes_2;
362     sizes_2.push_back(gfx::Size(bit_small, bit_small));
363 
364     std::vector<gfx::Size> sizes_3;
365     sizes_3.push_back(gfx::Size(small, small));
366 
367     std::vector<content::Manifest::Icon> icons;
368     icons.push_back(CreateIcon("http://foo.com/icon_no.png", "", 1.0, sizes_1));
369     icons.push_back(CreateIcon("http://foo.com/icon.png", "", 1.0, sizes_2));
370     icons.push_back(CreateIcon("http://foo.com/icon_no.png", "", 1.0, sizes_3));
371 
372     GURL url = FindBestMatchingIcon(icons);
373     EXPECT_EQ("http://foo.com/icon.png", url.spec());
374   }
375 
376   // (very_big, big) => big
377   {
378     std::vector<gfx::Size> sizes_1;
379     sizes_1.push_back(gfx::Size(very_big, very_big));
380 
381     std::vector<gfx::Size> sizes_2;
382     sizes_2.push_back(gfx::Size(big, big));
383 
384     std::vector<content::Manifest::Icon> icons;
385     icons.push_back(CreateIcon("http://foo.com/icon_no.png", "", 1.0, sizes_1));
386     icons.push_back(CreateIcon("http://foo.com/icon.png", "", 1.0, sizes_2));
387 
388     GURL url = FindBestMatchingIcon(icons);
389     EXPECT_EQ("http://foo.com/icon.png", url.spec());
390   }
391 
392   // (very_big, big, bit_big) => bit_big
393   {
394     std::vector<gfx::Size> sizes_1;
395     sizes_1.push_back(gfx::Size(very_big, very_big));
396 
397     std::vector<gfx::Size> sizes_2;
398     sizes_2.push_back(gfx::Size(big, big));
399 
400     std::vector<gfx::Size> sizes_3;
401     sizes_3.push_back(gfx::Size(bit_big, bit_big));
402 
403     std::vector<content::Manifest::Icon> icons;
404     icons.push_back(CreateIcon("http://foo.com/icon_no.png", "", 1.0, sizes_1));
405     icons.push_back(CreateIcon("http://foo.com/icon_no.png", "", 1.0, sizes_2));
406     icons.push_back(CreateIcon("http://foo.com/icon.png", "", 1.0, sizes_3));
407 
408     GURL url = FindBestMatchingIcon(icons);
409     EXPECT_EQ("http://foo.com/icon.png", url.spec());
410   }
411 
412   // (bit_small, very_big) => very_big
413   {
414     std::vector<gfx::Size> sizes_1;
415     sizes_1.push_back(gfx::Size(bit_small, bit_small));
416 
417     std::vector<gfx::Size> sizes_2;
418     sizes_2.push_back(gfx::Size(very_big, very_big));
419 
420     std::vector<content::Manifest::Icon> icons;
421     icons.push_back(CreateIcon("http://foo.com/icon_no.png", "", 1.0, sizes_1));
422     icons.push_back(CreateIcon("http://foo.com/icon.png", "", 1.0, sizes_2));
423 
424     GURL url = FindBestMatchingIcon(icons);
425     EXPECT_EQ("http://foo.com/icon.png", url.spec());
426   }
427 
428   // (bit_small, bit_big) => bit_big
429   {
430     std::vector<gfx::Size> sizes_1;
431     sizes_1.push_back(gfx::Size(bit_small, bit_small));
432 
433     std::vector<gfx::Size> sizes_2;
434     sizes_2.push_back(gfx::Size(bit_big, bit_big));
435 
436     std::vector<content::Manifest::Icon> icons;
437     icons.push_back(CreateIcon("http://foo.com/icon_no.png", "", 1.0, sizes_1));
438     icons.push_back(CreateIcon("http://foo.com/icon.png", "", 1.0, sizes_2));
439 
440     GURL url = FindBestMatchingIcon(icons);
441     EXPECT_EQ("http://foo.com/icon.png", url.spec());
442   }
443 }
444 
TEST_F(ShortcutHelperTest,UseAnyIfNoPreferredSize)445 TEST_F(ShortcutHelperTest, UseAnyIfNoPreferredSize) {
446   // 'any' (ie. gfx::Size(0,0)) should be used if there is no icon of a
447   // preferred size. An icon with the current device scale factor is preferred
448   // over one with the default density.
449 
450   // 'any' with preferred size => preferred size
451   {
452     std::vector<gfx::Size> sizes_1;
453     sizes_1.push_back(gfx::Size(GetPreferredIconSizeInDp(),
454                                 GetPreferredIconSizeInDp()));
455     std::vector<gfx::Size> sizes_2;
456     sizes_2.push_back(gfx::Size(0,0));
457 
458     std::vector<content::Manifest::Icon> icons;
459     icons.push_back(CreateIcon("http://foo.com/icon.png", "", 1.0, sizes_1));
460     icons.push_back(CreateIcon("http://foo.com/icon_no.png", "", 1.0, sizes_2));
461 
462     GURL url = FindBestMatchingIcon(icons);
463     EXPECT_EQ("http://foo.com/icon.png", url.spec());
464   }
465 
466   // 'any' with nearly preferred size => any
467   {
468     std::vector<gfx::Size> sizes_1;
469     sizes_1.push_back(gfx::Size(GetPreferredIconSizeInDp() + 1,
470                                 GetPreferredIconSizeInDp() + 1));
471     std::vector<gfx::Size> sizes_2;
472     sizes_2.push_back(gfx::Size(0,0));
473 
474     std::vector<content::Manifest::Icon> icons;
475     icons.push_back(CreateIcon("http://foo.com/icon_no.png", "", 1.0, sizes_1));
476     icons.push_back(CreateIcon("http://foo.com/icon.png", "", 1.0, sizes_2));
477 
478     GURL url = FindBestMatchingIcon(icons);
479     EXPECT_EQ("http://foo.com/icon.png", url.spec());
480   }
481 
482   // 'any' on default density and current density => current density.
483   {
484     std::vector<gfx::Size> sizes;
485     sizes.push_back(gfx::Size(0,0));
486 
487     std::vector<content::Manifest::Icon> icons;
488     icons.push_back(CreateIcon("http://foo.com/icon_no.png", "", 1.0, sizes));
489     icons.push_back(CreateIcon("http://foo.com/icon.png", "", 3.0, sizes));
490 
491     SetDisplayDeviceScaleFactor(3.0f);
492     GURL url = FindBestMatchingIcon(icons);
493     EXPECT_EQ("http://foo.com/icon.png", url.spec());
494   }
495 }
496