Home | History | Annotate | Download | only in resource
      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 "ui/base/resource/resource_bundle.h"
      6 
      7 #include "base/base_paths.h"
      8 #include "base/file_util.h"
      9 #include "base/files/file_path.h"
     10 #include "base/files/scoped_temp_dir.h"
     11 #include "base/logging.h"
     12 #include "base/memory/ref_counted_memory.h"
     13 #include "base/path_service.h"
     14 #include "base/strings/utf_string_conversions.h"
     15 #include "net/base/big_endian.h"
     16 #include "testing/gmock/include/gmock/gmock.h"
     17 #include "testing/gtest/include/gtest/gtest.h"
     18 #include "third_party/skia/include/core/SkBitmap.h"
     19 #include "ui/base/layout.h"
     20 #include "ui/base/resource/data_pack.h"
     21 #include "ui/gfx/codec/png_codec.h"
     22 #include "ui/gfx/image/image_skia.h"
     23 
     24 #include "grit/ui_resources.h"
     25 
     26 using ::testing::_;
     27 using ::testing::Between;
     28 using ::testing::Property;
     29 using ::testing::Return;
     30 using ::testing::ReturnArg;
     31 
     32 namespace ui {
     33 
     34 extern const char kSamplePakContents[];
     35 extern const size_t kSamplePakSize;
     36 extern const char kSamplePakContents2x[];
     37 extern const size_t kSamplePakSize2x;
     38 extern const char kEmptyPakContents[];
     39 extern const size_t kEmptyPakSize;
     40 
     41 namespace {
     42 
     43 const unsigned char kPngMagic[8] = { 0x89, 'P', 'N', 'G', 13, 10, 26, 10 };
     44 const size_t kPngChunkMetadataSize = 12;
     45 const unsigned char kPngIHDRChunkType[4] = { 'I', 'H', 'D', 'R' };
     46 
     47 // Custom chunk that GRIT adds to PNG to indicate that it could not find a
     48 // bitmap at the requested scale factor and fell back to 1x.
     49 const unsigned char kPngScaleChunk[12] = { 0x00, 0x00, 0x00, 0x00,
     50                                            'c', 's', 'C', 'l',
     51                                            0xc1, 0x30, 0x60, 0x4d };
     52 
     53 // Mock for the ResourceBundle::Delegate class.
     54 class MockResourceBundleDelegate : public ui::ResourceBundle::Delegate {
     55  public:
     56   MockResourceBundleDelegate() {
     57   }
     58   virtual ~MockResourceBundleDelegate() {
     59   }
     60 
     61   MOCK_METHOD2(GetPathForResourcePack, base::FilePath(
     62       const base::FilePath& pack_path, ui::ScaleFactor scale_factor));
     63   MOCK_METHOD2(GetPathForLocalePack, base::FilePath(
     64       const base::FilePath& pack_path, const std::string& locale));
     65   MOCK_METHOD1(GetImageNamed, gfx::Image(int resource_id));
     66   MOCK_METHOD2(GetNativeImageNamed,
     67       gfx::Image(int resource_id,
     68                  ui::ResourceBundle::ImageRTL rtl));
     69   MOCK_METHOD2(LoadDataResourceBytes,
     70       base::RefCountedStaticMemory*(int resource_id,
     71                                     ui::ScaleFactor scale_factor));
     72   MOCK_METHOD2(GetRawDataResourceMock, base::StringPiece(
     73       int resource_id,
     74       ui::ScaleFactor scale_factor));
     75   virtual bool GetRawDataResource(int resource_id,
     76                                   ui::ScaleFactor scale_factor,
     77                                   base::StringPiece* value) OVERRIDE {
     78     *value = GetRawDataResourceMock(resource_id, scale_factor);
     79     return true;
     80   }
     81   MOCK_METHOD1(GetLocalizedStringMock, string16(int message_id));
     82   virtual bool GetLocalizedString(int message_id, string16* value) OVERRIDE {
     83     *value = GetLocalizedStringMock(message_id);
     84     return true;
     85   }
     86   MOCK_METHOD1(GetFontMock,
     87                gfx::Font*(ui::ResourceBundle::FontStyle style));
     88   virtual scoped_ptr<gfx::Font> GetFont(
     89       ui::ResourceBundle::FontStyle style) OVERRIDE {
     90     return scoped_ptr<gfx::Font>(GetFontMock(style));
     91   }
     92 };
     93 
     94 // Returns |bitmap_data| with |custom_chunk| inserted after the IHDR chunk.
     95 void AddCustomChunk(const base::StringPiece& custom_chunk,
     96                     std::vector<unsigned char>* bitmap_data) {
     97   EXPECT_LT(arraysize(kPngMagic) + kPngChunkMetadataSize, bitmap_data->size());
     98   EXPECT_TRUE(std::equal(
     99       bitmap_data->begin(),
    100       bitmap_data->begin() + arraysize(kPngMagic),
    101       kPngMagic));
    102   std::vector<unsigned char>::iterator ihdr_start =
    103       bitmap_data->begin() + arraysize(kPngMagic);
    104   char ihdr_length_data[sizeof(uint32)];
    105   for (size_t i = 0; i < sizeof(uint32); ++i)
    106     ihdr_length_data[i] = *(ihdr_start + i);
    107   uint32 ihdr_chunk_length = 0;
    108   net::ReadBigEndian(reinterpret_cast<char*>(ihdr_length_data),
    109                      &ihdr_chunk_length);
    110   EXPECT_TRUE(std::equal(
    111       ihdr_start + sizeof(uint32),
    112       ihdr_start + sizeof(uint32) + sizeof(kPngIHDRChunkType),
    113       kPngIHDRChunkType));
    114 
    115   bitmap_data->insert(ihdr_start + kPngChunkMetadataSize + ihdr_chunk_length,
    116                       custom_chunk.begin(), custom_chunk.end());
    117 }
    118 
    119 // Creates datapack at |path| with a single bitmap at resource ID 3
    120 // which is |edge_size|x|edge_size| pixels.
    121 // If |custom_chunk| is non empty, adds it after the IHDR chunk
    122 // in the encoded bitmap data.
    123 void CreateDataPackWithSingleBitmap(const base::FilePath& path,
    124                                     int edge_size,
    125                                     const base::StringPiece& custom_chunk) {
    126   SkBitmap bitmap;
    127   bitmap.setConfig(SkBitmap::kARGB_8888_Config, edge_size, edge_size);
    128   bitmap.allocPixels();
    129   bitmap.eraseColor(SK_ColorWHITE);
    130   std::vector<unsigned char> bitmap_data;
    131   EXPECT_TRUE(gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &bitmap_data));
    132 
    133   if (custom_chunk.size() > 0)
    134     AddCustomChunk(custom_chunk, &bitmap_data);
    135 
    136   std::map<uint16, base::StringPiece> resources;
    137   resources[3u] = base::StringPiece(
    138       reinterpret_cast<const char*>(&bitmap_data[0]), bitmap_data.size());
    139   DataPack::WritePack(path, resources, ui::DataPack::BINARY);
    140 }
    141 
    142 }  // namespace
    143 
    144 class ResourceBundleTest : public testing::Test {
    145  public:
    146   ResourceBundleTest() : resource_bundle_(NULL) {
    147   }
    148 
    149   virtual ~ResourceBundleTest() {
    150   }
    151 
    152   // Overridden from testing::Test:
    153   virtual void TearDown() OVERRIDE {
    154     delete resource_bundle_;
    155   }
    156 
    157   // Returns new ResoureBundle with the specified |delegate|. The
    158   // ResourceBundleTest class manages the lifetime of the returned
    159   // ResourceBundle.
    160   ResourceBundle* CreateResourceBundle(ResourceBundle::Delegate* delegate) {
    161     DCHECK(!resource_bundle_);
    162 
    163     resource_bundle_ = new ResourceBundle(delegate);
    164     return resource_bundle_;
    165   }
    166 
    167  protected:
    168   ResourceBundle* resource_bundle_;
    169 
    170  private:
    171   DISALLOW_COPY_AND_ASSIGN(ResourceBundleTest);
    172 };
    173 
    174 TEST_F(ResourceBundleTest, DelegateGetPathForResourcePack) {
    175   MockResourceBundleDelegate delegate;
    176   ResourceBundle* resource_bundle = CreateResourceBundle(&delegate);
    177 
    178   base::FilePath pack_path(FILE_PATH_LITERAL("/path/to/test_path.pak"));
    179   ui::ScaleFactor pack_scale_factor = ui::SCALE_FACTOR_200P;
    180 
    181   EXPECT_CALL(delegate,
    182       GetPathForResourcePack(
    183           Property(&base::FilePath::value, pack_path.value()),
    184           pack_scale_factor))
    185       .Times(1)
    186       .WillOnce(Return(pack_path));
    187 
    188   resource_bundle->AddDataPackFromPath(pack_path, pack_scale_factor);
    189 }
    190 
    191 #if defined(OS_LINUX)
    192 // Fails consistently on Linux: crbug.com/161902
    193 #define MAYBE_DelegateGetPathForLocalePack DISABLED_DelegateGetPathForLocalePack
    194 #else
    195 #define MAYBE_DelegateGetPathForLocalePack DelegateGetPathForLocalePack
    196 #endif
    197 TEST_F(ResourceBundleTest, MAYBE_DelegateGetPathForLocalePack) {
    198   MockResourceBundleDelegate delegate;
    199   ResourceBundle* resource_bundle = CreateResourceBundle(&delegate);
    200 
    201   std::string locale = "en-US";
    202 
    203   // Cancel the load.
    204   EXPECT_CALL(delegate, GetPathForLocalePack(_, locale))
    205       .Times(2)
    206       .WillRepeatedly(Return(base::FilePath()))
    207       .RetiresOnSaturation();
    208 
    209   EXPECT_FALSE(resource_bundle->LocaleDataPakExists(locale));
    210   EXPECT_EQ("", resource_bundle->LoadLocaleResources(locale));
    211 
    212   // Allow the load to proceed.
    213   EXPECT_CALL(delegate, GetPathForLocalePack(_, locale))
    214       .Times(2)
    215       .WillRepeatedly(ReturnArg<0>());
    216 
    217   EXPECT_TRUE(resource_bundle->LocaleDataPakExists(locale));
    218   EXPECT_EQ(locale, resource_bundle->LoadLocaleResources(locale));
    219 }
    220 
    221 TEST_F(ResourceBundleTest, DelegateGetImageNamed) {
    222   MockResourceBundleDelegate delegate;
    223   ResourceBundle* resource_bundle = CreateResourceBundle(&delegate);
    224 
    225   gfx::Image empty_image = resource_bundle->GetEmptyImage();
    226   int resource_id = 5;
    227 
    228   EXPECT_CALL(delegate, GetImageNamed(resource_id))
    229       .Times(1)
    230       .WillOnce(Return(empty_image));
    231 
    232   gfx::Image result = resource_bundle->GetImageNamed(resource_id);
    233   EXPECT_EQ(empty_image.ToSkBitmap(), result.ToSkBitmap());
    234 }
    235 
    236 TEST_F(ResourceBundleTest, DelegateGetNativeImageNamed) {
    237   MockResourceBundleDelegate delegate;
    238   ResourceBundle* resource_bundle = CreateResourceBundle(&delegate);
    239 
    240   gfx::Image empty_image = resource_bundle->GetEmptyImage();
    241   int resource_id = 5;
    242 
    243   // Some platforms delegate GetNativeImageNamed calls to GetImageNamed.
    244   EXPECT_CALL(delegate, GetImageNamed(resource_id))
    245       .Times(Between(0, 1))
    246       .WillOnce(Return(empty_image));
    247   EXPECT_CALL(delegate,
    248       GetNativeImageNamed(resource_id, ui::ResourceBundle::RTL_DISABLED))
    249       .Times(Between(0, 1))
    250       .WillOnce(Return(empty_image));
    251 
    252   gfx::Image result = resource_bundle->GetNativeImageNamed(resource_id);
    253   EXPECT_EQ(empty_image.ToSkBitmap(), result.ToSkBitmap());
    254 }
    255 
    256 TEST_F(ResourceBundleTest, DelegateLoadDataResourceBytes) {
    257   MockResourceBundleDelegate delegate;
    258   ResourceBundle* resource_bundle = CreateResourceBundle(&delegate);
    259 
    260   // Create the data resource for testing purposes.
    261   unsigned char data[] = "My test data";
    262   scoped_refptr<base::RefCountedStaticMemory> static_memory(
    263       new base::RefCountedStaticMemory(data, sizeof(data)));
    264 
    265   int resource_id = 5;
    266   ui::ScaleFactor scale_factor = ui::SCALE_FACTOR_NONE;
    267 
    268   EXPECT_CALL(delegate, LoadDataResourceBytes(resource_id, scale_factor))
    269       .Times(1).WillOnce(Return(static_memory.get()));
    270 
    271   scoped_refptr<base::RefCountedStaticMemory> result =
    272       resource_bundle->LoadDataResourceBytesForScale(resource_id, scale_factor);
    273   EXPECT_EQ(static_memory, result);
    274 }
    275 
    276 TEST_F(ResourceBundleTest, DelegateGetRawDataResource) {
    277   MockResourceBundleDelegate delegate;
    278   ResourceBundle* resource_bundle = CreateResourceBundle(&delegate);
    279 
    280   // Create the string piece for testing purposes.
    281   char data[] = "My test data";
    282   base::StringPiece string_piece(data);
    283 
    284   int resource_id = 5;
    285 
    286   EXPECT_CALL(delegate, GetRawDataResourceMock(
    287           resource_id, ui::SCALE_FACTOR_NONE))
    288       .Times(1)
    289       .WillOnce(Return(string_piece));
    290 
    291   base::StringPiece result = resource_bundle->GetRawDataResource(
    292       resource_id);
    293   EXPECT_EQ(string_piece.data(), result.data());
    294 }
    295 
    296 TEST_F(ResourceBundleTest, DelegateGetLocalizedString) {
    297   MockResourceBundleDelegate delegate;
    298   ResourceBundle* resource_bundle = CreateResourceBundle(&delegate);
    299 
    300   string16 data = ASCIIToUTF16("My test data");
    301   int resource_id = 5;
    302 
    303   EXPECT_CALL(delegate, GetLocalizedStringMock(resource_id))
    304       .Times(1)
    305       .WillOnce(Return(data));
    306 
    307   string16 result = resource_bundle->GetLocalizedString(resource_id);
    308   EXPECT_EQ(data, result);
    309 }
    310 
    311 TEST_F(ResourceBundleTest, DelegateGetFontList) {
    312   MockResourceBundleDelegate delegate;
    313   ResourceBundle* resource_bundle = CreateResourceBundle(&delegate);
    314 
    315   // Should be called once for each font type. When we return NULL the default
    316   // font will be created.
    317   gfx::Font* test_font = NULL;
    318   EXPECT_CALL(delegate, GetFontMock(_))
    319       .Times(8)
    320       .WillRepeatedly(Return(test_font));
    321 
    322   const gfx::FontList* font_list =
    323       &resource_bundle->GetFontList(ui::ResourceBundle::BaseFont);
    324   EXPECT_TRUE(font_list);
    325 
    326   const gfx::Font* font =
    327       &resource_bundle->GetFont(ui::ResourceBundle::BaseFont);
    328   EXPECT_TRUE(font);
    329 }
    330 
    331 TEST_F(ResourceBundleTest, LocaleDataPakExists) {
    332   ResourceBundle* resource_bundle = CreateResourceBundle(NULL);
    333 
    334   // Check that ResourceBundle::LocaleDataPakExists returns the correct results.
    335   EXPECT_TRUE(resource_bundle->LocaleDataPakExists("en-US"));
    336   EXPECT_FALSE(resource_bundle->LocaleDataPakExists("not_a_real_locale"));
    337 }
    338 
    339 class ResourceBundleImageTest : public ResourceBundleTest {
    340  public:
    341   ResourceBundleImageTest() {}
    342 
    343   virtual ~ResourceBundleImageTest() {
    344   }
    345 
    346   virtual void SetUp() OVERRIDE {
    347     // Create a temporary directory to write test resource bundles to.
    348     ASSERT_TRUE(dir_.CreateUniqueTempDir());
    349   }
    350 
    351   // Returns resource bundle which uses an empty data pak for locale data.
    352   ui::ResourceBundle* CreateResourceBundleWithEmptyLocalePak() {
    353     // Write an empty data pak for locale data.
    354     const base::FilePath& locale_path = dir_path().Append(
    355         FILE_PATH_LITERAL("locale.pak"));
    356     EXPECT_EQ(file_util::WriteFile(locale_path, kEmptyPakContents,
    357                                    kEmptyPakSize),
    358               static_cast<int>(kEmptyPakSize));
    359 
    360     ui::ResourceBundle* resource_bundle = CreateResourceBundle(NULL);
    361 
    362     // Load the empty locale data pak.
    363     resource_bundle->LoadTestResources(base::FilePath(), locale_path);
    364     return resource_bundle;
    365   }
    366 
    367   // Returns the path of temporary directory to write test data packs into.
    368   const base::FilePath& dir_path() { return dir_.path(); }
    369 
    370  private:
    371   scoped_ptr<DataPack> locale_pack_;
    372   base::ScopedTempDir dir_;
    373 
    374   DISALLOW_COPY_AND_ASSIGN(ResourceBundleImageTest);
    375 };
    376 
    377 // Verify that we don't crash when trying to load a resource that is not found.
    378 // In some cases, we fail to mmap resources.pak, but try to keep going anyway.
    379 TEST_F(ResourceBundleImageTest, LoadDataResourceBytes) {
    380   base::FilePath data_path = dir_path().Append(FILE_PATH_LITERAL("sample.pak"));
    381 
    382   // Dump contents into the pak files.
    383   ASSERT_EQ(file_util::WriteFile(data_path, kEmptyPakContents,
    384       kEmptyPakSize), static_cast<int>(kEmptyPakSize));
    385 
    386   // Create a resource bundle from the file.
    387   ResourceBundle* resource_bundle = CreateResourceBundleWithEmptyLocalePak();
    388   resource_bundle->AddDataPackFromPath(data_path, SCALE_FACTOR_100P);
    389 
    390   const int kUnfoundResourceId = 10000;
    391   EXPECT_EQ(NULL, resource_bundle->LoadDataResourceBytes(
    392       kUnfoundResourceId));
    393 
    394   // Give a .pak file that doesn't exist so we will fail to load it.
    395   resource_bundle->AddDataPackFromPath(
    396       base::FilePath(FILE_PATH_LITERAL("non-existant-file.pak")),
    397       ui::SCALE_FACTOR_NONE);
    398   EXPECT_EQ(NULL, resource_bundle->LoadDataResourceBytes(
    399       kUnfoundResourceId));
    400 }
    401 
    402 TEST_F(ResourceBundleImageTest, GetRawDataResource) {
    403   base::FilePath data_path = dir_path().Append(FILE_PATH_LITERAL("sample.pak"));
    404   base::FilePath data_2x_path =
    405       dir_path().Append(FILE_PATH_LITERAL("sample_2x.pak"));
    406 
    407   // Dump contents into the pak files.
    408   ASSERT_EQ(file_util::WriteFile(data_path, kSamplePakContents,
    409       kSamplePakSize), static_cast<int>(kSamplePakSize));
    410   ASSERT_EQ(file_util::WriteFile(data_2x_path, kSamplePakContents2x,
    411       kSamplePakSize2x), static_cast<int>(kSamplePakSize2x));
    412 
    413   // Load the regular and 2x pak files.
    414   ResourceBundle* resource_bundle = CreateResourceBundleWithEmptyLocalePak();
    415   resource_bundle->AddDataPackFromPath(data_path, SCALE_FACTOR_100P);
    416   resource_bundle->AddDataPackFromPath(data_2x_path, SCALE_FACTOR_200P);
    417 
    418   // Resource ID 4 exists in both 1x and 2x paks, so we expect a different
    419   // result when requesting the 2x scale.
    420   EXPECT_EQ("this is id 4", resource_bundle->GetRawDataResourceForScale(4,
    421       SCALE_FACTOR_100P));
    422   EXPECT_EQ("this is id 4 2x", resource_bundle->GetRawDataResourceForScale(4,
    423       SCALE_FACTOR_200P));
    424 
    425   // Resource ID 6 only exists in the 1x pak so we expect the same resource
    426   // for both scale factor requests.
    427   EXPECT_EQ("this is id 6", resource_bundle->GetRawDataResourceForScale(6,
    428       SCALE_FACTOR_100P));
    429   EXPECT_EQ("this is id 6", resource_bundle->GetRawDataResourceForScale(6,
    430       SCALE_FACTOR_200P));
    431 }
    432 
    433 // Test requesting image reps at various scale factors from the image returned
    434 // via ResourceBundle::GetImageNamed().
    435 TEST_F(ResourceBundleImageTest, GetImageNamed) {
    436   base::FilePath data_1x_path = dir_path().AppendASCII("sample_1x.pak");
    437   base::FilePath data_2x_path = dir_path().AppendASCII("sample_2x.pak");
    438 
    439   // Create the pak files.
    440   CreateDataPackWithSingleBitmap(data_1x_path, 10, base::StringPiece());
    441   CreateDataPackWithSingleBitmap(data_2x_path, 20, base::StringPiece());
    442 
    443   // Load the regular and 2x pak files.
    444   ResourceBundle* resource_bundle = CreateResourceBundleWithEmptyLocalePak();
    445   resource_bundle->AddDataPackFromPath(data_1x_path, SCALE_FACTOR_100P);
    446   resource_bundle->AddDataPackFromPath(data_2x_path, SCALE_FACTOR_200P);
    447 
    448   EXPECT_EQ(SCALE_FACTOR_200P, resource_bundle->max_scale_factor());
    449 
    450   gfx::ImageSkia* image_skia = resource_bundle->GetImageSkiaNamed(3);
    451 
    452 #if defined(OS_CHROMEOS)
    453   // ChromeOS loads highest scale factor first.
    454   EXPECT_EQ(ui::SCALE_FACTOR_200P, image_skia->image_reps()[0].scale_factor());
    455 #else
    456   EXPECT_EQ(ui::SCALE_FACTOR_100P, image_skia->image_reps()[0].scale_factor());
    457 #endif
    458 
    459   // Resource ID 3 exists in both 1x and 2x paks. Image reps should be
    460   // available for both scale factors in |image_skia|.
    461   gfx::ImageSkiaRep image_rep =
    462       image_skia->GetRepresentation(ui::SCALE_FACTOR_100P);
    463   EXPECT_EQ(ui::SCALE_FACTOR_100P, image_rep.scale_factor());
    464   image_rep = image_skia->GetRepresentation(ui::SCALE_FACTOR_200P);
    465   EXPECT_EQ(ui::SCALE_FACTOR_200P, image_rep.scale_factor());
    466 
    467   // The 1.4x pack was not loaded. Requesting the 1.4x resource should return
    468   // either the 1x or the 2x resource.
    469   image_rep = image_skia->GetRepresentation(ui::SCALE_FACTOR_140P);
    470   EXPECT_TRUE(image_rep.scale_factor() == ui::SCALE_FACTOR_100P ||
    471               image_rep.scale_factor() == ui::SCALE_FACTOR_200P);
    472 }
    473 
    474 // Test that GetImageNamed() behaves properly for images which GRIT has
    475 // annotated as having fallen back to 1x.
    476 TEST_F(ResourceBundleImageTest, GetImageNamedFallback1x) {
    477   base::FilePath data_path = dir_path().AppendASCII("sample.pak");
    478   base::FilePath data_2x_path = dir_path().AppendASCII("sample_2x.pak");
    479 
    480   // Create the pak files.
    481   CreateDataPackWithSingleBitmap(data_path, 10, base::StringPiece());
    482   // 2x data pack bitmap has custom chunk to indicate that the 2x bitmap is not
    483   // available and that GRIT fell back to 1x.
    484   CreateDataPackWithSingleBitmap(data_2x_path, 10, base::StringPiece(
    485       reinterpret_cast<const char*>(kPngScaleChunk),
    486       arraysize(kPngScaleChunk)));
    487 
    488   // Load the regular and 2x pak files.
    489   ResourceBundle* resource_bundle = CreateResourceBundleWithEmptyLocalePak();
    490   resource_bundle->AddDataPackFromPath(data_path, SCALE_FACTOR_100P);
    491   resource_bundle->AddDataPackFromPath(data_2x_path, SCALE_FACTOR_200P);
    492 
    493   gfx::ImageSkia* image_skia = resource_bundle->GetImageSkiaNamed(3);
    494 
    495   // The image rep for 2x should be available. It should be resized to the
    496   // proper 2x size.
    497   gfx::ImageSkiaRep image_rep =
    498     image_skia->GetRepresentation(ui::SCALE_FACTOR_200P);
    499   EXPECT_EQ(ui::SCALE_FACTOR_200P, image_rep.scale_factor());
    500   EXPECT_EQ(20, image_rep.pixel_width());
    501   EXPECT_EQ(20, image_rep.pixel_height());
    502 }
    503 
    504 #if defined(OS_WIN)
    505 // Tests GetImageNamed() behaves properly when the size of a scaled image
    506 // requires rounding as a result of using a non-integer scale factor.
    507 // Scale factors of 140 and 1805 are Windows specific.
    508 TEST_F(ResourceBundleImageTest, GetImageNamedFallback1xRounding) {
    509   base::FilePath data_path = dir_path().AppendASCII("sample.pak");
    510   base::FilePath data_140P_path = dir_path().AppendASCII("sample_140P.pak");
    511   base::FilePath data_180P_path = dir_path().AppendASCII("sample_180P.pak");
    512 
    513   CreateDataPackWithSingleBitmap(data_path, 8, base::StringPiece());
    514   // Mark 140% and 180% images as requiring 1x fallback.
    515   CreateDataPackWithSingleBitmap(data_140P_path, 8, base::StringPiece(
    516     reinterpret_cast<const char*>(kPngScaleChunk),
    517     arraysize(kPngScaleChunk)));
    518   CreateDataPackWithSingleBitmap(data_180P_path, 8, base::StringPiece(
    519     reinterpret_cast<const char*>(kPngScaleChunk),
    520     arraysize(kPngScaleChunk)));
    521 
    522   ResourceBundle* resource_bundle = CreateResourceBundleWithEmptyLocalePak();
    523   resource_bundle->AddDataPackFromPath(data_path, SCALE_FACTOR_100P);
    524   resource_bundle->AddDataPackFromPath(data_140P_path, SCALE_FACTOR_140P);
    525   resource_bundle->AddDataPackFromPath(data_180P_path, SCALE_FACTOR_180P);
    526 
    527   // Non-integer dimensions should be rounded up.
    528   gfx::ImageSkia* image_skia = resource_bundle->GetImageSkiaNamed(3);
    529   gfx::ImageSkiaRep image_rep =
    530     image_skia->GetRepresentation(ui::SCALE_FACTOR_140P);
    531   EXPECT_EQ(12, image_rep.pixel_width());
    532   image_rep = image_skia->GetRepresentation(ui::SCALE_FACTOR_180P);
    533   EXPECT_EQ(15, image_rep.pixel_width());
    534 }
    535 #endif
    536 
    537 TEST_F(ResourceBundleImageTest, FallbackToNone) {
    538   base::FilePath data_default_path = dir_path().AppendASCII("sample.pak");
    539 
    540   // Create the pak files.
    541   CreateDataPackWithSingleBitmap(data_default_path, 10, base::StringPiece());
    542 
    543     // Load the regular pak files only.
    544   ResourceBundle* resource_bundle = CreateResourceBundleWithEmptyLocalePak();
    545   resource_bundle->AddDataPackFromPath(data_default_path, SCALE_FACTOR_NONE);
    546 
    547   gfx::ImageSkia* image_skia = resource_bundle->GetImageSkiaNamed(3);
    548   EXPECT_EQ(1u, image_skia->image_reps().size());
    549   EXPECT_EQ(ui::SCALE_FACTOR_100P,
    550             image_skia->image_reps()[0].scale_factor());
    551 }
    552 
    553 }  // namespace ui
    554