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