Home | History | Annotate | Download | only in extensions
      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/extension_icon_image.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/extensions/image_loader.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/manifest.h"
     15 #include "chrome/common/extensions/manifest_handlers/icons_handler.h"
     16 #include "chrome/test/base/testing_profile.h"
     17 #include "content/public/test/test_browser_thread.h"
     18 #include "grit/theme_resources.h"
     19 #include "skia/ext/image_operations.h"
     20 #include "testing/gtest/include/gtest/gtest.h"
     21 #include "ui/base/resource/resource_bundle.h"
     22 #include "ui/gfx/image/image_skia_source.h"
     23 #include "ui/gfx/skia_util.h"
     24 
     25 using content::BrowserThread;
     26 using extensions::Extension;
     27 using extensions::IconImage;
     28 using extensions::Manifest;
     29 
     30 namespace {
     31 
     32 SkBitmap CreateBlankBitmapForScale(int size_dip, ui::ScaleFactor scale_factor) {
     33   SkBitmap bitmap;
     34   const float scale = ui::GetScaleFactorScale(scale_factor);
     35   bitmap.setConfig(SkBitmap::kARGB_8888_Config,
     36                    static_cast<int>(size_dip * scale),
     37                    static_cast<int>(size_dip * scale));
     38   bitmap.allocPixels();
     39   bitmap.eraseColor(SkColorSetARGB(0, 0, 0, 0));
     40   return bitmap;
     41 }
     42 
     43 SkBitmap EnsureBitmapSize(const SkBitmap& original, int size) {
     44   if (original.width() == size && original.height() == size)
     45     return original;
     46 
     47   SkBitmap resized = skia::ImageOperations::Resize(
     48       original, skia::ImageOperations::RESIZE_LANCZOS3, size, size);
     49   return resized;
     50 }
     51 
     52 // Used to test behavior including images defined by an image skia source.
     53 // |GetImageForScale| simply returns image representation from the image given
     54 // in the ctor.
     55 class MockImageSkiaSource : public gfx::ImageSkiaSource {
     56  public:
     57   explicit MockImageSkiaSource(const gfx::ImageSkia& image)
     58       : image_(image) {
     59   }
     60   virtual ~MockImageSkiaSource() {}
     61 
     62   virtual gfx::ImageSkiaRep GetImageForScale(
     63       ui::ScaleFactor scale_factor) OVERRIDE {
     64     return image_.GetRepresentation(scale_factor);
     65   }
     66 
     67  private:
     68   gfx::ImageSkia image_;
     69 };
     70 
     71 // Helper class for synchronously loading extension image resource.
     72 class TestImageLoader {
     73  public:
     74   explicit TestImageLoader(const Extension* extension)
     75       : extension_(extension),
     76         waiting_(false),
     77         image_loaded_(false) {
     78   }
     79   virtual ~TestImageLoader() {}
     80 
     81   void OnImageLoaded(const gfx::Image& image) {
     82     image_ = image;
     83     image_loaded_ = true;
     84     if (waiting_)
     85       base::MessageLoop::current()->Quit();
     86   }
     87 
     88   SkBitmap LoadBitmap(const std::string& path,
     89                       int size) {
     90     image_loaded_ = false;
     91 
     92     image_loader_.LoadImageAsync(
     93         extension_, extension_->GetResource(path), gfx::Size(size, size),
     94         base::Bind(&TestImageLoader::OnImageLoaded,
     95                    base::Unretained(this)));
     96 
     97     // If |image_| still hasn't been loaded (i.e. it is being loaded
     98     // asynchronously), wait for it.
     99     if (!image_loaded_) {
    100       waiting_ = true;
    101       base::MessageLoop::current()->Run();
    102       waiting_ = false;
    103     }
    104 
    105     EXPECT_TRUE(image_loaded_);
    106 
    107     return image_.IsEmpty() ? SkBitmap() : *image_.ToSkBitmap();
    108   }
    109 
    110  private:
    111   const Extension* extension_;
    112   bool waiting_;
    113   bool image_loaded_;
    114   gfx::Image image_;
    115   extensions::ImageLoader image_loader_;
    116 
    117   DISALLOW_COPY_AND_ASSIGN(TestImageLoader);
    118 };
    119 
    120 class ExtensionIconImageTest : public testing::Test,
    121                                public IconImage::Observer {
    122  public:
    123   ExtensionIconImageTest()
    124       : image_loaded_count_(0),
    125         quit_in_image_loaded_(false),
    126         ui_thread_(BrowserThread::UI, &ui_loop_),
    127         file_thread_(BrowserThread::FILE),
    128         io_thread_(BrowserThread::IO) {
    129   }
    130 
    131   virtual ~ExtensionIconImageTest() {}
    132 
    133   void WaitForImageLoad() {
    134     quit_in_image_loaded_ = true;
    135     base::MessageLoop::current()->Run();
    136     quit_in_image_loaded_ = false;
    137   }
    138 
    139   int ImageLoadedCount() {
    140     int result = image_loaded_count_;
    141     image_loaded_count_ = 0;
    142     return result;
    143   }
    144 
    145   scoped_refptr<Extension> CreateExtension(const char* name,
    146                                            Manifest::Location location) {
    147     // Create and load an extension.
    148     base::FilePath test_file;
    149     if (!PathService::Get(chrome::DIR_TEST_DATA, &test_file)) {
    150       EXPECT_FALSE(true);
    151       return NULL;
    152     }
    153     test_file = test_file.AppendASCII("extensions").AppendASCII(name);
    154     int error_code = 0;
    155     std::string error;
    156     JSONFileValueSerializer serializer(test_file.AppendASCII("app.json"));
    157     scoped_ptr<DictionaryValue> valid_value(
    158         static_cast<DictionaryValue*>(serializer.Deserialize(&error_code,
    159                                                              &error)));
    160     EXPECT_EQ(0, error_code) << error;
    161     if (error_code != 0)
    162       return NULL;
    163 
    164     EXPECT_TRUE(valid_value.get());
    165     if (!valid_value)
    166       return NULL;
    167 
    168     return Extension::Create(test_file, location, *valid_value,
    169                              Extension::NO_FLAGS, &error);
    170   }
    171 
    172   // testing::Test overrides:
    173   virtual void SetUp() OVERRIDE {
    174     file_thread_.Start();
    175     io_thread_.Start();
    176   }
    177 
    178   // IconImage::Delegate overrides:
    179   virtual void OnExtensionIconImageChanged(IconImage* image) OVERRIDE {
    180     image_loaded_count_++;
    181     if (quit_in_image_loaded_)
    182       base::MessageLoop::current()->Quit();
    183   }
    184 
    185   gfx::ImageSkia GetDefaultIcon() {
    186     return *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
    187         IDR_EXTENSIONS_FAVICON);
    188   }
    189 
    190   // Loads an image to be used in test from the extension.
    191   // The image will be loaded from the relative path |path|.
    192   SkBitmap GetTestBitmap(const Extension* extension,
    193                          const std::string& path,
    194                          int size) {
    195     TestImageLoader image_loader(extension);
    196     return image_loader.LoadBitmap(path, size);
    197   }
    198 
    199  private:
    200   int image_loaded_count_;
    201   bool quit_in_image_loaded_;
    202   base::MessageLoop ui_loop_;
    203   content::TestBrowserThread ui_thread_;
    204   content::TestBrowserThread file_thread_;
    205   content::TestBrowserThread io_thread_;
    206 
    207   DISALLOW_COPY_AND_ASSIGN(ExtensionIconImageTest);
    208 };
    209 
    210 }  // namespace
    211 
    212 TEST_F(ExtensionIconImageTest, Basic) {
    213   scoped_ptr<Profile> profile(new TestingProfile());
    214   scoped_refptr<Extension> extension(CreateExtension(
    215       "extension_icon_image", Manifest::INVALID_LOCATION));
    216   ASSERT_TRUE(extension.get() != NULL);
    217 
    218   gfx::ImageSkia default_icon = GetDefaultIcon();
    219 
    220   // Load images we expect to find as representations in icon_image, so we
    221   // can later use them to validate icon_image.
    222   SkBitmap bitmap_16 = GetTestBitmap(extension.get(), "16.png", 16);
    223   ASSERT_FALSE(bitmap_16.empty());
    224 
    225   // There is no image of size 32 defined in the extension manifest, so we
    226   // should expect manifest image of size 48 resized to size 32.
    227   SkBitmap bitmap_48_resized_to_32 =
    228       GetTestBitmap(extension.get(), "48.png", 32);
    229   ASSERT_FALSE(bitmap_48_resized_to_32.empty());
    230 
    231   IconImage image(profile.get(),
    232                   extension.get(),
    233                   extensions::IconsInfo::GetIcons(extension.get()),
    234                   16,
    235                   default_icon,
    236                   this);
    237 
    238   // No representations in |image_| yet.
    239   gfx::ImageSkia::ImageSkiaReps image_reps = image.image_skia().image_reps();
    240   ASSERT_EQ(0u, image_reps.size());
    241 
    242   // Gets representation for a scale factor.
    243   gfx::ImageSkiaRep representation =
    244       image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
    245 
    246   // Before the image representation is loaded, image should contain blank
    247   // image representation.
    248   EXPECT_TRUE(gfx::BitmapsAreEqual(
    249       representation.sk_bitmap(),
    250       CreateBlankBitmapForScale(16, ui::SCALE_FACTOR_100P)));
    251 
    252   WaitForImageLoad();
    253   EXPECT_EQ(1, ImageLoadedCount());
    254   ASSERT_EQ(1u, image.image_skia().image_reps().size());
    255 
    256   representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
    257 
    258   // We should get the right representation now.
    259   EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(), bitmap_16));
    260   EXPECT_EQ(16, representation.pixel_width());
    261 
    262   // Gets representation for an additional scale factor.
    263   representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P);
    264 
    265   EXPECT_TRUE(gfx::BitmapsAreEqual(
    266       representation.sk_bitmap(),
    267       CreateBlankBitmapForScale(16, ui::SCALE_FACTOR_200P)));
    268 
    269   WaitForImageLoad();
    270   EXPECT_EQ(1, ImageLoadedCount());
    271   ASSERT_EQ(2u, image.image_skia().image_reps().size());
    272 
    273   representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P);
    274 
    275   // Image should have been resized.
    276   EXPECT_EQ(32, representation.pixel_width());
    277   EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(),
    278                                    bitmap_48_resized_to_32));
    279 }
    280 
    281 // There is no resource with either exact or bigger size, but there is a smaller
    282 // resource.
    283 TEST_F(ExtensionIconImageTest, FallbackToSmallerWhenNoBigger) {
    284   scoped_ptr<Profile> profile(new TestingProfile());
    285   scoped_refptr<Extension> extension(CreateExtension(
    286       "extension_icon_image", Manifest::INVALID_LOCATION));
    287   ASSERT_TRUE(extension.get() != NULL);
    288 
    289   gfx::ImageSkia default_icon = GetDefaultIcon();
    290 
    291   // Load images we expect to find as representations in icon_image, so we
    292   // can later use them to validate icon_image.
    293   SkBitmap bitmap_48 = GetTestBitmap(extension.get(), "48.png", 48);
    294   ASSERT_FALSE(bitmap_48.empty());
    295 
    296   IconImage image(profile.get(),
    297                   extension.get(),
    298                   extensions::IconsInfo::GetIcons(extension.get()),
    299                   32,
    300                   default_icon,
    301                   this);
    302 
    303   gfx::ImageSkiaRep representation =
    304       image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P);
    305 
    306   WaitForImageLoad();
    307   EXPECT_EQ(1, ImageLoadedCount());
    308   ASSERT_EQ(1u, image.image_skia().image_reps().size());
    309 
    310   representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_200P);
    311 
    312   // We should have loaded the biggest smaller resource resized to the actual
    313   // size.
    314   EXPECT_EQ(ui::SCALE_FACTOR_200P, representation.scale_factor());
    315   EXPECT_EQ(64, representation.pixel_width());
    316   EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(),
    317                                    EnsureBitmapSize(bitmap_48, 64)));
    318 }
    319 
    320 // There is no resource with exact size, but there is a smaller and a bigger
    321 // one. Requested size is smaller than 32 though, so the smaller resource should
    322 // be loaded.
    323 TEST_F(ExtensionIconImageTest, FallbackToSmaller) {
    324   scoped_ptr<Profile> profile(new TestingProfile());
    325   scoped_refptr<Extension> extension(CreateExtension(
    326       "extension_icon_image", Manifest::INVALID_LOCATION));
    327   ASSERT_TRUE(extension.get() != NULL);
    328 
    329   gfx::ImageSkia default_icon = GetDefaultIcon();
    330 
    331   // Load images we expect to find as representations in icon_image, so we
    332   // can later use them to validate icon_image.
    333   SkBitmap bitmap_16 = GetTestBitmap(extension.get(), "16.png", 16);
    334   ASSERT_FALSE(bitmap_16.empty());
    335 
    336   IconImage image(profile.get(),
    337                   extension.get(),
    338                   extensions::IconsInfo::GetIcons(extension.get()),
    339                   17,
    340                   default_icon,
    341                   this);
    342 
    343   gfx::ImageSkiaRep representation =
    344       image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
    345 
    346   WaitForImageLoad();
    347   EXPECT_EQ(1, ImageLoadedCount());
    348   ASSERT_EQ(1u, image.image_skia().image_reps().size());
    349 
    350   representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
    351 
    352   // We should have loaded smaller (resized) resource.
    353   EXPECT_EQ(ui::SCALE_FACTOR_100P, representation.scale_factor());
    354   EXPECT_EQ(17, representation.pixel_width());
    355   EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(),
    356                                    EnsureBitmapSize(bitmap_16, 17)));
    357 }
    358 
    359 // If resource set is empty, |GetRepresentation| should synchronously return
    360 // default icon, without notifying observer of image change.
    361 TEST_F(ExtensionIconImageTest, NoResources) {
    362   scoped_ptr<Profile> profile(new TestingProfile());
    363   scoped_refptr<Extension> extension(CreateExtension(
    364       "extension_icon_image", Manifest::INVALID_LOCATION));
    365   ASSERT_TRUE(extension.get() != NULL);
    366 
    367   ExtensionIconSet empty_icon_set;
    368   gfx::ImageSkia default_icon = GetDefaultIcon();
    369 
    370   const int kRequestedSize = 24;
    371   IconImage image(profile.get(),
    372                   extension.get(),
    373                   empty_icon_set,
    374                   kRequestedSize,
    375                   default_icon,
    376                   this);
    377 
    378   gfx::ImageSkiaRep representation =
    379       image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
    380   EXPECT_TRUE(gfx::BitmapsAreEqual(
    381       representation.sk_bitmap(),
    382       EnsureBitmapSize(
    383           default_icon.GetRepresentation(ui::SCALE_FACTOR_100P).sk_bitmap(),
    384           kRequestedSize)));
    385 
    386   EXPECT_EQ(0, ImageLoadedCount());
    387   // We should have a default icon representation.
    388   ASSERT_EQ(1u, image.image_skia().image_reps().size());
    389 
    390   representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
    391   EXPECT_TRUE(gfx::BitmapsAreEqual(
    392       representation.sk_bitmap(),
    393       EnsureBitmapSize(
    394           default_icon.GetRepresentation(ui::SCALE_FACTOR_100P).sk_bitmap(),
    395           kRequestedSize)));
    396 }
    397 
    398 // If resource set is invalid, image load should be done asynchronously and
    399 // the observer should be notified when it's done. |GetRepresentation| should
    400 // return the default icon representation once image load is done.
    401 TEST_F(ExtensionIconImageTest, InvalidResource) {
    402   scoped_ptr<Profile> profile(new TestingProfile());
    403   scoped_refptr<Extension> extension(CreateExtension(
    404       "extension_icon_image", Manifest::INVALID_LOCATION));
    405   ASSERT_TRUE(extension.get() != NULL);
    406 
    407   const int kInvalidIconSize = 24;
    408   ExtensionIconSet invalid_icon_set;
    409   invalid_icon_set.Add(kInvalidIconSize, "invalid.png");
    410 
    411   gfx::ImageSkia default_icon = GetDefaultIcon();
    412 
    413   IconImage image(profile.get(),
    414                   extension.get(),
    415                   invalid_icon_set,
    416                   kInvalidIconSize,
    417                   default_icon,
    418                   this);
    419 
    420   gfx::ImageSkiaRep representation =
    421       image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
    422   EXPECT_TRUE(gfx::BitmapsAreEqual(
    423       representation.sk_bitmap(),
    424       CreateBlankBitmapForScale(kInvalidIconSize, ui::SCALE_FACTOR_100P)));
    425 
    426   WaitForImageLoad();
    427   EXPECT_EQ(1, ImageLoadedCount());
    428   // We should have default icon representation now.
    429   ASSERT_EQ(1u, image.image_skia().image_reps().size());
    430 
    431   representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
    432   EXPECT_TRUE(gfx::BitmapsAreEqual(
    433       representation.sk_bitmap(),
    434       EnsureBitmapSize(
    435           default_icon.GetRepresentation(ui::SCALE_FACTOR_100P).sk_bitmap(),
    436           kInvalidIconSize)));
    437 }
    438 
    439 // Test that IconImage works with lazily (but synchronously) created default
    440 // icon when IconImage returns synchronously.
    441 TEST_F(ExtensionIconImageTest, LazyDefaultIcon) {
    442   scoped_ptr<Profile> profile(new TestingProfile());
    443   scoped_refptr<Extension> extension(CreateExtension(
    444       "extension_icon_image", Manifest::INVALID_LOCATION));
    445   ASSERT_TRUE(extension.get() != NULL);
    446 
    447   gfx::ImageSkia default_icon = GetDefaultIcon();
    448   gfx::ImageSkia lazy_default_icon(new MockImageSkiaSource(default_icon),
    449                                     default_icon.size());
    450 
    451   ExtensionIconSet empty_icon_set;
    452 
    453   const int kRequestedSize = 128;
    454   IconImage image(profile.get(),
    455                   extension.get(),
    456                   empty_icon_set,
    457                   kRequestedSize,
    458                   lazy_default_icon,
    459                   this);
    460 
    461   ASSERT_FALSE(lazy_default_icon.HasRepresentation(ui::SCALE_FACTOR_100P));
    462 
    463   gfx::ImageSkiaRep representation =
    464       image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
    465 
    466   // The resouce set is empty, so we should get the result right away.
    467   EXPECT_TRUE(lazy_default_icon.HasRepresentation(ui::SCALE_FACTOR_100P));
    468   EXPECT_TRUE(gfx::BitmapsAreEqual(
    469       representation.sk_bitmap(),
    470       EnsureBitmapSize(
    471           default_icon.GetRepresentation(ui::SCALE_FACTOR_100P).sk_bitmap(),
    472           kRequestedSize)));
    473 
    474   // We should have a default icon representation.
    475   ASSERT_EQ(1u, image.image_skia().image_reps().size());
    476 }
    477 
    478 // Test that IconImage works with lazily (but synchronously) created default
    479 // icon when IconImage returns asynchronously.
    480 TEST_F(ExtensionIconImageTest, LazyDefaultIcon_AsyncIconImage) {
    481   scoped_ptr<Profile> profile(new TestingProfile());
    482   scoped_refptr<Extension> extension(CreateExtension(
    483       "extension_icon_image", Manifest::INVALID_LOCATION));
    484   ASSERT_TRUE(extension.get() != NULL);
    485 
    486   gfx::ImageSkia default_icon = GetDefaultIcon();
    487   gfx::ImageSkia lazy_default_icon(new MockImageSkiaSource(default_icon),
    488                                     default_icon.size());
    489 
    490   const int kInvalidIconSize = 24;
    491   ExtensionIconSet invalid_icon_set;
    492   invalid_icon_set.Add(kInvalidIconSize, "invalid.png");
    493 
    494   IconImage image(profile.get(),
    495                   extension.get(),
    496                   invalid_icon_set,
    497                   kInvalidIconSize,
    498                   lazy_default_icon,
    499                   this);
    500 
    501   ASSERT_FALSE(lazy_default_icon.HasRepresentation(ui::SCALE_FACTOR_100P));
    502 
    503   gfx::ImageSkiaRep representation =
    504       image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
    505 
    506   WaitForImageLoad();
    507   EXPECT_EQ(1, ImageLoadedCount());
    508   // We should have default icon representation now.
    509   ASSERT_EQ(1u, image.image_skia().image_reps().size());
    510 
    511   EXPECT_TRUE(lazy_default_icon.HasRepresentation(ui::SCALE_FACTOR_100P));
    512 
    513   representation = image.image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
    514   EXPECT_TRUE(gfx::BitmapsAreEqual(
    515       representation.sk_bitmap(),
    516       EnsureBitmapSize(
    517           default_icon.GetRepresentation(ui::SCALE_FACTOR_100P).sk_bitmap(),
    518           kInvalidIconSize)));
    519 }
    520 
    521 // Tests behavior of image created by IconImage after IconImage host goes
    522 // away. The image should still return loaded representations. If requested
    523 // representation was not loaded while IconImage host was around, transparent
    524 // representations should be returned.
    525 TEST_F(ExtensionIconImageTest, IconImageDestruction) {
    526   scoped_ptr<Profile> profile(new TestingProfile());
    527   scoped_refptr<Extension> extension(CreateExtension(
    528       "extension_icon_image", Manifest::INVALID_LOCATION));
    529   ASSERT_TRUE(extension.get() != NULL);
    530 
    531   gfx::ImageSkia default_icon = GetDefaultIcon();
    532 
    533   // Load images we expect to find as representations in icon_image, so we
    534   // can later use them to validate icon_image.
    535   SkBitmap bitmap_16 = GetTestBitmap(extension.get(), "16.png", 16);
    536   ASSERT_FALSE(bitmap_16.empty());
    537 
    538   scoped_ptr<IconImage> image(
    539       new IconImage(profile.get(),
    540                     extension.get(),
    541                     extensions::IconsInfo::GetIcons(extension.get()),
    542                     16,
    543                     default_icon,
    544                     this));
    545 
    546   // Load an image representation.
    547   gfx::ImageSkiaRep representation =
    548       image->image_skia().GetRepresentation(ui::SCALE_FACTOR_100P);
    549 
    550   WaitForImageLoad();
    551   EXPECT_EQ(1, ImageLoadedCount());
    552   ASSERT_EQ(1u, image->image_skia().image_reps().size());
    553 
    554   // Stash loaded image skia, and destroy |image|.
    555   gfx::ImageSkia image_skia = image->image_skia();
    556   image.reset();
    557   extension = NULL;
    558 
    559   // Image skia should still be able to get previously loaded representation.
    560   representation = image_skia.GetRepresentation(ui::SCALE_FACTOR_100P);
    561 
    562   EXPECT_EQ(ui::SCALE_FACTOR_100P, representation.scale_factor());
    563   EXPECT_EQ(16, representation.pixel_width());
    564   EXPECT_TRUE(gfx::BitmapsAreEqual(representation.sk_bitmap(), bitmap_16));
    565 
    566   // When requesting another representation, we should get blank image.
    567   representation = image_skia.GetRepresentation(ui::SCALE_FACTOR_200P);
    568 
    569   EXPECT_TRUE(gfx::BitmapsAreEqual(
    570       representation.sk_bitmap(),
    571       CreateBlankBitmapForScale(16, ui::SCALE_FACTOR_200P)));
    572 }
    573