| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/themes/browser_theme_pack.h" |
| |
| #include "base/files/scoped_temp_dir.h" |
| #include "base/json/json_file_value_serializer.h" |
| #include "base/json/json_reader.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/path_service.h" |
| #include "base/values.h" |
| #include "chrome/browser/themes/theme_properties.h" |
| #include "chrome/common/chrome_paths.h" |
| #include "content/public/test/test_browser_thread.h" |
| #include "grit/theme_resources.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/gfx/color_utils.h" |
| #include "ui/gfx/image/image.h" |
| #include "ui/gfx/image/image_skia.h" |
| #include "ui/gfx/image/image_skia_rep.h" |
| |
| using content::BrowserThread; |
| using extensions::Extension; |
| |
| // Maps scale factors (enum values) to file path. |
| // A similar typedef in BrowserThemePack is private. |
| typedef std::map<ui::ScaleFactor, base::FilePath> TestScaleFactorToFileMap; |
| |
| // Maps image ids to maps of scale factors to file paths. |
| // A similar typedef in BrowserThemePack is private. |
| typedef std::map<int, TestScaleFactorToFileMap> TestFilePathMap; |
| |
| class BrowserThemePackTest : public ::testing::Test { |
| public: |
| BrowserThemePackTest() |
| : message_loop(), |
| fake_ui_thread(BrowserThread::UI, &message_loop), |
| fake_file_thread(BrowserThread::FILE, &message_loop) { |
| std::vector<ui::ScaleFactor> scale_factors; |
| scale_factors.push_back(ui::SCALE_FACTOR_100P); |
| scale_factors.push_back(ui::SCALE_FACTOR_200P); |
| scoped_set_supported_scale_factors_.reset( |
| new ui::test::ScopedSetSupportedScaleFactors(scale_factors)); |
| theme_pack_ = new BrowserThemePack(); |
| } |
| |
| // Transformation for link underline colors. |
| SkColor BuildThirdOpacity(SkColor color_link) { |
| return SkColorSetA(color_link, SkColorGetA(color_link) / 3); |
| } |
| |
| void GenerateDefaultFrameColor(std::map<int, SkColor>* colors, |
| int color, int tint) { |
| (*colors)[color] = HSLShift( |
| ThemeProperties::GetDefaultColor( |
| ThemeProperties::COLOR_FRAME), |
| ThemeProperties::GetDefaultTint(tint)); |
| } |
| |
| // Returns a mapping from each COLOR_* constant to the default value for this |
| // constant. Callers get this map, and then modify expected values and then |
| // run the resulting thing through VerifyColorMap(). |
| std::map<int, SkColor> GetDefaultColorMap() { |
| std::map<int, SkColor> colors; |
| for (int i = ThemeProperties::COLOR_FRAME; |
| i <= ThemeProperties::COLOR_BUTTON_BACKGROUND; ++i) { |
| colors[i] = ThemeProperties::GetDefaultColor(i); |
| } |
| |
| GenerateDefaultFrameColor(&colors, ThemeProperties::COLOR_FRAME, |
| ThemeProperties::TINT_FRAME); |
| GenerateDefaultFrameColor(&colors, |
| ThemeProperties::COLOR_FRAME_INACTIVE, |
| ThemeProperties::TINT_FRAME_INACTIVE); |
| GenerateDefaultFrameColor(&colors, |
| ThemeProperties::COLOR_FRAME_INCOGNITO, |
| ThemeProperties::TINT_FRAME_INCOGNITO); |
| GenerateDefaultFrameColor( |
| &colors, |
| ThemeProperties::COLOR_FRAME_INCOGNITO_INACTIVE, |
| ThemeProperties::TINT_FRAME_INCOGNITO_INACTIVE); |
| |
| return colors; |
| } |
| |
| void VerifyColorMap(const std::map<int, SkColor>& color_map) { |
| for (std::map<int, SkColor>::const_iterator it = color_map.begin(); |
| it != color_map.end(); ++it) { |
| SkColor color = ThemeProperties::GetDefaultColor(it->first); |
| theme_pack_->GetColor(it->first, &color); |
| EXPECT_EQ(it->second, color) << "Color id = " << it->first; |
| } |
| } |
| |
| void LoadColorJSON(const std::string& json) { |
| scoped_ptr<base::Value> value(base::JSONReader::Read(json)); |
| ASSERT_TRUE(value->IsType(base::Value::TYPE_DICTIONARY)); |
| LoadColorDictionary(static_cast<base::DictionaryValue*>(value.get())); |
| } |
| |
| void LoadColorDictionary(base::DictionaryValue* value) { |
| theme_pack_->BuildColorsFromJSON(value); |
| } |
| |
| void LoadTintJSON(const std::string& json) { |
| scoped_ptr<base::Value> value(base::JSONReader::Read(json)); |
| ASSERT_TRUE(value->IsType(base::Value::TYPE_DICTIONARY)); |
| LoadTintDictionary(static_cast<base::DictionaryValue*>(value.get())); |
| } |
| |
| void LoadTintDictionary(base::DictionaryValue* value) { |
| theme_pack_->BuildTintsFromJSON(value); |
| } |
| |
| void LoadDisplayPropertiesJSON(const std::string& json) { |
| scoped_ptr<base::Value> value(base::JSONReader::Read(json)); |
| ASSERT_TRUE(value->IsType(base::Value::TYPE_DICTIONARY)); |
| LoadDisplayPropertiesDictionary( |
| static_cast<base::DictionaryValue*>(value.get())); |
| } |
| |
| void LoadDisplayPropertiesDictionary(base::DictionaryValue* value) { |
| theme_pack_->BuildDisplayPropertiesFromJSON(value); |
| } |
| |
| void ParseImageNamesJSON(const std::string& json, |
| TestFilePathMap* out_file_paths) { |
| scoped_ptr<base::Value> value(base::JSONReader::Read(json)); |
| ASSERT_TRUE(value->IsType(base::Value::TYPE_DICTIONARY)); |
| ParseImageNamesDictionary(static_cast<base::DictionaryValue*>(value.get()), |
| out_file_paths); |
| } |
| |
| void ParseImageNamesDictionary( |
| base::DictionaryValue* value, |
| TestFilePathMap* out_file_paths) { |
| theme_pack_->ParseImageNamesFromJSON(value, base::FilePath(), |
| out_file_paths); |
| |
| // Build the source image list for HasCustomImage(). |
| theme_pack_->BuildSourceImagesArray(*out_file_paths); |
| } |
| |
| bool LoadRawBitmapsTo(const TestFilePathMap& out_file_paths) { |
| return theme_pack_->LoadRawBitmapsTo(out_file_paths, |
| &theme_pack_->images_on_ui_thread_); |
| } |
| |
| // This function returns void in order to be able use ASSERT_... |
| // The BrowserThemePack is returned in |pack|. |
| void BuildFromUnpackedExtension(const base::FilePath& extension_path, |
| scoped_refptr<BrowserThemePack>& pack) { |
| base::FilePath manifest_path = |
| extension_path.AppendASCII("manifest.json"); |
| std::string error; |
| JSONFileValueSerializer serializer(manifest_path); |
| scoped_ptr<base::DictionaryValue> valid_value( |
| static_cast<base::DictionaryValue*>( |
| serializer.Deserialize(NULL, &error))); |
| EXPECT_EQ("", error); |
| ASSERT_TRUE(valid_value.get()); |
| scoped_refptr<Extension> extension( |
| Extension::Create( |
| extension_path, |
| extensions::Manifest::INVALID_LOCATION, |
| *valid_value, |
| Extension::REQUIRE_KEY, |
| &error)); |
| ASSERT_TRUE(extension.get()); |
| ASSERT_EQ("", error); |
| pack = BrowserThemePack::BuildFromExtension(extension.get()); |
| ASSERT_TRUE(pack.get()); |
| } |
| |
| base::FilePath GetStarGazingPath() { |
| base::FilePath test_path; |
| if (!PathService::Get(chrome::DIR_TEST_DATA, &test_path)) { |
| NOTREACHED(); |
| return test_path; |
| } |
| |
| test_path = test_path.AppendASCII("profiles"); |
| test_path = test_path.AppendASCII("profile_with_complex_theme"); |
| test_path = test_path.AppendASCII("Default"); |
| test_path = test_path.AppendASCII("Extensions"); |
| test_path = test_path.AppendASCII("mblmlcbknbnfebdfjnolmcapmdofhmme"); |
| test_path = test_path.AppendASCII("1.1"); |
| return base::FilePath(test_path); |
| } |
| |
| base::FilePath GetHiDpiThemePath() { |
| base::FilePath test_path; |
| if (!PathService::Get(chrome::DIR_TEST_DATA, &test_path)) { |
| NOTREACHED(); |
| return test_path; |
| } |
| test_path = test_path.AppendASCII("extensions"); |
| test_path = test_path.AppendASCII("theme_hidpi"); |
| return base::FilePath(test_path); |
| } |
| |
| // Verifies the data in star gazing. We do this multiple times for different |
| // BrowserThemePack objects to make sure it works in generated and mmapped |
| // mode correctly. |
| void VerifyStarGazing(BrowserThemePack* pack) { |
| // First check that values we know exist, exist. |
| SkColor color; |
| EXPECT_TRUE(pack->GetColor(ThemeProperties::COLOR_BOOKMARK_TEXT, |
| &color)); |
| EXPECT_EQ(SK_ColorBLACK, color); |
| |
| EXPECT_TRUE(pack->GetColor(ThemeProperties::COLOR_NTP_BACKGROUND, |
| &color)); |
| EXPECT_EQ(SkColorSetRGB(57, 137, 194), color); |
| |
| color_utils::HSL expected = { 0.6, 0.553, 0.5 }; |
| color_utils::HSL actual; |
| EXPECT_TRUE(pack->GetTint(ThemeProperties::TINT_BUTTONS, &actual)); |
| EXPECT_DOUBLE_EQ(expected.h, actual.h); |
| EXPECT_DOUBLE_EQ(expected.s, actual.s); |
| EXPECT_DOUBLE_EQ(expected.l, actual.l); |
| |
| int val; |
| EXPECT_TRUE(pack->GetDisplayProperty( |
| ThemeProperties::NTP_BACKGROUND_ALIGNMENT, &val)); |
| EXPECT_EQ(ThemeProperties::ALIGN_TOP, val); |
| |
| // The stargazing theme defines the following images: |
| EXPECT_TRUE(pack->HasCustomImage(IDR_THEME_BUTTON_BACKGROUND)); |
| EXPECT_TRUE(pack->HasCustomImage(IDR_THEME_FRAME)); |
| EXPECT_TRUE(pack->HasCustomImage(IDR_THEME_NTP_BACKGROUND)); |
| EXPECT_TRUE(pack->HasCustomImage(IDR_THEME_TAB_BACKGROUND)); |
| EXPECT_TRUE(pack->HasCustomImage(IDR_THEME_TOOLBAR)); |
| EXPECT_TRUE(pack->HasCustomImage(IDR_THEME_WINDOW_CONTROL_BACKGROUND)); |
| |
| // Here are a few images that we shouldn't expect because even though |
| // they're included in the theme pack, they were autogenerated and |
| // therefore shouldn't show up when calling HasCustomImage(). |
| EXPECT_FALSE(pack->HasCustomImage(IDR_THEME_FRAME_INACTIVE)); |
| EXPECT_FALSE(pack->HasCustomImage(IDR_THEME_FRAME_INCOGNITO)); |
| EXPECT_FALSE(pack->HasCustomImage(IDR_THEME_FRAME_INCOGNITO_INACTIVE)); |
| #if !defined(OS_MACOSX) |
| EXPECT_FALSE(pack->HasCustomImage(IDR_THEME_TAB_BACKGROUND_INCOGNITO)); |
| #endif |
| |
| // Make sure we don't have phantom data. |
| EXPECT_FALSE(pack->GetColor(ThemeProperties::COLOR_CONTROL_BACKGROUND, |
| &color)); |
| EXPECT_FALSE(pack->GetTint(ThemeProperties::TINT_FRAME, &actual)); |
| } |
| |
| void VerifyHiDpiTheme(BrowserThemePack* pack) { |
| // The high DPI theme defines the following images: |
| EXPECT_TRUE(pack->HasCustomImage(IDR_THEME_FRAME)); |
| EXPECT_TRUE(pack->HasCustomImage(IDR_THEME_FRAME_INACTIVE)); |
| EXPECT_TRUE(pack->HasCustomImage(IDR_THEME_FRAME_INCOGNITO)); |
| EXPECT_TRUE(pack->HasCustomImage(IDR_THEME_FRAME_INCOGNITO_INACTIVE)); |
| EXPECT_TRUE(pack->HasCustomImage(IDR_THEME_TOOLBAR)); |
| |
| // The high DPI theme does not define the following images: |
| EXPECT_FALSE(pack->HasCustomImage(IDR_THEME_TAB_BACKGROUND)); |
| #if !defined(OS_MACOSX) |
| EXPECT_FALSE(pack->HasCustomImage(IDR_THEME_TAB_BACKGROUND_INCOGNITO)); |
| #endif |
| EXPECT_FALSE(pack->HasCustomImage(IDR_THEME_TAB_BACKGROUND_V)); |
| EXPECT_FALSE(pack->HasCustomImage(IDR_THEME_NTP_BACKGROUND)); |
| EXPECT_FALSE(pack->HasCustomImage(IDR_THEME_FRAME_OVERLAY)); |
| EXPECT_FALSE(pack->HasCustomImage(IDR_THEME_FRAME_OVERLAY_INACTIVE)); |
| EXPECT_FALSE(pack->HasCustomImage(IDR_THEME_BUTTON_BACKGROUND)); |
| EXPECT_FALSE(pack->HasCustomImage(IDR_THEME_NTP_ATTRIBUTION)); |
| EXPECT_FALSE(pack->HasCustomImage(IDR_THEME_WINDOW_CONTROL_BACKGROUND)); |
| |
| // Compare some known pixel colors at know locations for a theme |
| // image where two different PNG files were specified for scales 100% |
| // and 200% respectively. |
| int idr = IDR_THEME_FRAME; |
| gfx::Image image = pack->GetImageNamed(idr); |
| EXPECT_FALSE(image.IsEmpty()); |
| const gfx::ImageSkia* image_skia = image.ToImageSkia(); |
| ASSERT_TRUE(image_skia); |
| // Scale 100%. |
| const gfx::ImageSkiaRep& rep1 = image_skia->GetRepresentation(1.0f); |
| ASSERT_FALSE(rep1.is_null()); |
| EXPECT_EQ(80, rep1.sk_bitmap().width()); |
| EXPECT_EQ(80, rep1.sk_bitmap().height()); |
| rep1.sk_bitmap().lockPixels(); |
| EXPECT_EQ(SkColorSetRGB(255, 255, 255), rep1.sk_bitmap().getColor( 4, 4)); |
| EXPECT_EQ(SkColorSetRGB(255, 255, 255), rep1.sk_bitmap().getColor( 8, 8)); |
| EXPECT_EQ(SkColorSetRGB( 0, 241, 237), rep1.sk_bitmap().getColor(16, 16)); |
| EXPECT_EQ(SkColorSetRGB(255, 255, 255), rep1.sk_bitmap().getColor(24, 24)); |
| EXPECT_EQ(SkColorSetRGB( 0, 241, 237), rep1.sk_bitmap().getColor(32, 32)); |
| rep1.sk_bitmap().unlockPixels(); |
| // Scale 200%. |
| const gfx::ImageSkiaRep& rep2 = image_skia->GetRepresentation(2.0f); |
| ASSERT_FALSE(rep2.is_null()); |
| EXPECT_EQ(160, rep2.sk_bitmap().width()); |
| EXPECT_EQ(160, rep2.sk_bitmap().height()); |
| rep2.sk_bitmap().lockPixels(); |
| EXPECT_EQ(SkColorSetRGB(255, 255, 255), rep2.sk_bitmap().getColor( 4, 4)); |
| EXPECT_EQ(SkColorSetRGB(223, 42, 0), rep2.sk_bitmap().getColor( 8, 8)); |
| EXPECT_EQ(SkColorSetRGB(223, 42, 0), rep2.sk_bitmap().getColor(16, 16)); |
| EXPECT_EQ(SkColorSetRGB(223, 42, 0), rep2.sk_bitmap().getColor(24, 24)); |
| EXPECT_EQ(SkColorSetRGB(255, 255, 255), rep2.sk_bitmap().getColor(32, 32)); |
| rep2.sk_bitmap().unlockPixels(); |
| |
| // TODO(sschmitz): I plan to remove the following (to the end of the fct) |
| // Reason: this test may be brittle. It depends on details of how we scale |
| // an 100% image to an 200% image. If there's filtering etc, this test would |
| // break. Also High DPI is new, but scaling from 100% to 200% is not new |
| // and need not be tested here. But in the interrim it is useful to verify |
| // that this image was scaled and did not appear in the input. |
| |
| // Compare pixel colors and locations for a theme image that had |
| // only one PNG file specified (for scale 100%). The representation |
| // for scale of 200% was computed. |
| idr = IDR_THEME_FRAME_INCOGNITO_INACTIVE; |
| image = pack->GetImageNamed(idr); |
| EXPECT_FALSE(image.IsEmpty()); |
| image_skia = image.ToImageSkia(); |
| ASSERT_TRUE(image_skia); |
| // Scale 100%. |
| const gfx::ImageSkiaRep& rep3 = image_skia->GetRepresentation(1.0f); |
| ASSERT_FALSE(rep3.is_null()); |
| EXPECT_EQ(80, rep3.sk_bitmap().width()); |
| EXPECT_EQ(80, rep3.sk_bitmap().height()); |
| rep3.sk_bitmap().lockPixels(); |
| // We take samples of colors and locations along the diagonal whenever |
| // the color changes. Note these colors are slightly different from |
| // the input PNG file due to input processing. |
| std::vector<std::pair<int, SkColor> > normal; |
| int xy = 0; |
| SkColor color = rep3.sk_bitmap().getColor(xy, xy); |
| normal.push_back(std::make_pair(xy, color)); |
| for (int xy = 0; xy < 40; ++xy) { |
| SkColor next_color = rep3.sk_bitmap().getColor(xy, xy); |
| if (next_color != color) { |
| color = next_color; |
| normal.push_back(std::make_pair(xy, color)); |
| } |
| } |
| EXPECT_EQ(static_cast<size_t>(9), normal.size()); |
| rep3.sk_bitmap().unlockPixels(); |
| // Scale 200%. |
| const gfx::ImageSkiaRep& rep4 = image_skia->GetRepresentation(2.0f); |
| ASSERT_FALSE(rep4.is_null()); |
| EXPECT_EQ(160, rep4.sk_bitmap().width()); |
| EXPECT_EQ(160, rep4.sk_bitmap().height()); |
| rep4.sk_bitmap().lockPixels(); |
| // We expect the same colors and at locations scaled by 2 |
| // since this bitmap was scaled by 2. |
| for (size_t i = 0; i < normal.size(); ++i) { |
| int xy = 2 * normal[i].first; |
| SkColor color = normal[i].second; |
| EXPECT_EQ(color, rep4.sk_bitmap().getColor(xy, xy)); |
| } |
| rep4.sk_bitmap().unlockPixels(); |
| } |
| |
| base::MessageLoop message_loop; |
| content::TestBrowserThread fake_ui_thread; |
| content::TestBrowserThread fake_file_thread; |
| |
| typedef scoped_ptr<ui::test::ScopedSetSupportedScaleFactors> |
| ScopedSetSupportedScaleFactors; |
| ScopedSetSupportedScaleFactors scoped_set_supported_scale_factors_; |
| scoped_refptr<BrowserThemePack> theme_pack_; |
| }; |
| |
| |
| TEST_F(BrowserThemePackTest, DeriveUnderlineLinkColor) { |
| // If we specify a link color, but don't specify the underline color, the |
| // theme provider should create one. |
| std::string color_json = "{ \"ntp_link\": [128, 128, 128]," |
| " \"ntp_section_link\": [128, 128, 128] }"; |
| LoadColorJSON(color_json); |
| |
| std::map<int, SkColor> colors = GetDefaultColorMap(); |
| SkColor link_color = SkColorSetRGB(128, 128, 128); |
| colors[ThemeProperties::COLOR_NTP_LINK] = link_color; |
| colors[ThemeProperties::COLOR_NTP_LINK_UNDERLINE] = |
| BuildThirdOpacity(link_color); |
| colors[ThemeProperties::COLOR_NTP_SECTION_LINK] = link_color; |
| colors[ThemeProperties::COLOR_NTP_SECTION_LINK_UNDERLINE] = |
| BuildThirdOpacity(link_color); |
| |
| VerifyColorMap(colors); |
| } |
| |
| TEST_F(BrowserThemePackTest, ProvideUnderlineLinkColor) { |
| // If we specify the underline color, it shouldn't try to generate one. |
| std::string color_json = "{ \"ntp_link\": [128, 128, 128]," |
| " \"ntp_link_underline\": [255, 255, 255]," |
| " \"ntp_section_link\": [128, 128, 128]," |
| " \"ntp_section_link_underline\": [255, 255, 255]" |
| "}"; |
| LoadColorJSON(color_json); |
| |
| std::map<int, SkColor> colors = GetDefaultColorMap(); |
| SkColor link_color = SkColorSetRGB(128, 128, 128); |
| SkColor underline_color = SkColorSetRGB(255, 255, 255); |
| colors[ThemeProperties::COLOR_NTP_LINK] = link_color; |
| colors[ThemeProperties::COLOR_NTP_LINK_UNDERLINE] = underline_color; |
| colors[ThemeProperties::COLOR_NTP_SECTION_LINK] = link_color; |
| colors[ThemeProperties::COLOR_NTP_SECTION_LINK_UNDERLINE] = |
| underline_color; |
| |
| VerifyColorMap(colors); |
| } |
| |
| TEST_F(BrowserThemePackTest, UseSectionColorAsNTPHeader) { |
| std::string color_json = "{ \"ntp_section\": [190, 190, 190] }"; |
| LoadColorJSON(color_json); |
| |
| std::map<int, SkColor> colors = GetDefaultColorMap(); |
| SkColor ntp_color = SkColorSetRGB(190, 190, 190); |
| colors[ThemeProperties::COLOR_NTP_HEADER] = ntp_color; |
| colors[ThemeProperties::COLOR_NTP_SECTION] = ntp_color; |
| VerifyColorMap(colors); |
| } |
| |
| TEST_F(BrowserThemePackTest, ProvideNtpHeaderColor) { |
| std::string color_json = "{ \"ntp_header\": [120, 120, 120], " |
| " \"ntp_section\": [190, 190, 190] }"; |
| LoadColorJSON(color_json); |
| |
| std::map<int, SkColor> colors = GetDefaultColorMap(); |
| SkColor ntp_header = SkColorSetRGB(120, 120, 120); |
| SkColor ntp_section = SkColorSetRGB(190, 190, 190); |
| colors[ThemeProperties::COLOR_NTP_HEADER] = ntp_header; |
| colors[ThemeProperties::COLOR_NTP_SECTION] = ntp_section; |
| VerifyColorMap(colors); |
| } |
| |
| TEST_F(BrowserThemePackTest, CanReadTints) { |
| std::string tint_json = "{ \"buttons\": [ 0.5, 0.5, 0.5 ] }"; |
| LoadTintJSON(tint_json); |
| |
| color_utils::HSL expected = { 0.5, 0.5, 0.5 }; |
| color_utils::HSL actual = { -1, -1, -1 }; |
| EXPECT_TRUE(theme_pack_->GetTint( |
| ThemeProperties::TINT_BUTTONS, &actual)); |
| EXPECT_DOUBLE_EQ(expected.h, actual.h); |
| EXPECT_DOUBLE_EQ(expected.s, actual.s); |
| EXPECT_DOUBLE_EQ(expected.l, actual.l); |
| } |
| |
| TEST_F(BrowserThemePackTest, CanReadDisplayProperties) { |
| std::string json = "{ \"ntp_background_alignment\": \"bottom\", " |
| " \"ntp_background_repeat\": \"repeat-x\", " |
| " \"ntp_logo_alternate\": 0 }"; |
| LoadDisplayPropertiesJSON(json); |
| |
| int out_val; |
| EXPECT_TRUE(theme_pack_->GetDisplayProperty( |
| ThemeProperties::NTP_BACKGROUND_ALIGNMENT, &out_val)); |
| EXPECT_EQ(ThemeProperties::ALIGN_BOTTOM, out_val); |
| |
| EXPECT_TRUE(theme_pack_->GetDisplayProperty( |
| ThemeProperties::NTP_BACKGROUND_TILING, &out_val)); |
| EXPECT_EQ(ThemeProperties::REPEAT_X, out_val); |
| |
| EXPECT_TRUE(theme_pack_->GetDisplayProperty( |
| ThemeProperties::NTP_LOGO_ALTERNATE, &out_val)); |
| EXPECT_EQ(0, out_val); |
| } |
| |
| TEST_F(BrowserThemePackTest, CanParsePaths) { |
| std::string path_json = "{ \"theme_button_background\": \"one\", " |
| " \"theme_toolbar\": \"two\" }"; |
| TestFilePathMap out_file_paths; |
| ParseImageNamesJSON(path_json, &out_file_paths); |
| |
| size_t expected_file_paths = 2u; |
| #if defined(USE_ASH) && !defined(OS_CHROMEOS) |
| // On desktop builds with ash, additional theme paths are generated to map to |
| // the special resource ids like IDR_THEME_FRAME_DESKTOP, etc |
| expected_file_paths = 3u; |
| #endif |
| EXPECT_EQ(expected_file_paths, out_file_paths.size()); |
| // "12" and "5" are internal constants to BrowserThemePack and are |
| // PRS_THEME_BUTTON_BACKGROUND and PRS_THEME_TOOLBAR, but they are |
| // implementation details that shouldn't be exported. |
| // By default the scale factor is for 100%. |
| EXPECT_TRUE(base::FilePath(FILE_PATH_LITERAL("one")) == |
| out_file_paths[12][ui::SCALE_FACTOR_100P]); |
| EXPECT_TRUE(base::FilePath(FILE_PATH_LITERAL("two")) == |
| out_file_paths[5][ui::SCALE_FACTOR_100P]); |
| } |
| |
| TEST_F(BrowserThemePackTest, InvalidPathNames) { |
| std::string path_json = "{ \"wrong\": [1], " |
| " \"theme_button_background\": \"one\", " |
| " \"not_a_thing\": \"blah\" }"; |
| TestFilePathMap out_file_paths; |
| ParseImageNamesJSON(path_json, &out_file_paths); |
| |
| // We should have only parsed one valid path out of that mess above. |
| EXPECT_EQ(1u, out_file_paths.size()); |
| } |
| |
| TEST_F(BrowserThemePackTest, InvalidColors) { |
| std::string invalid_color = "{ \"toolbar\": [\"dog\", \"cat\", [12]], " |
| " \"sound\": \"woof\" }"; |
| LoadColorJSON(invalid_color); |
| std::map<int, SkColor> colors = GetDefaultColorMap(); |
| VerifyColorMap(colors); |
| } |
| |
| TEST_F(BrowserThemePackTest, InvalidTints) { |
| std::string invalid_tints = "{ \"buttons\": [ \"dog\", \"cat\", [\"x\"]], " |
| " \"invalid\": \"entry\" }"; |
| LoadTintJSON(invalid_tints); |
| |
| // We shouldn't have a buttons tint, as it was invalid. |
| color_utils::HSL actual = { -1, -1, -1 }; |
| EXPECT_FALSE(theme_pack_->GetTint(ThemeProperties::TINT_BUTTONS, |
| &actual)); |
| } |
| |
| TEST_F(BrowserThemePackTest, InvalidDisplayProperties) { |
| std::string invalid_properties = "{ \"ntp_background_alignment\": [15], " |
| " \"junk\": [15.3] }"; |
| LoadDisplayPropertiesJSON(invalid_properties); |
| |
| int out_val; |
| EXPECT_FALSE(theme_pack_->GetDisplayProperty( |
| ThemeProperties::NTP_BACKGROUND_ALIGNMENT, &out_val)); |
| } |
| |
| // These three tests should just not cause a segmentation fault. |
| TEST_F(BrowserThemePackTest, NullPaths) { |
| TestFilePathMap out_file_paths; |
| ParseImageNamesDictionary(NULL, &out_file_paths); |
| } |
| |
| TEST_F(BrowserThemePackTest, NullTints) { |
| LoadTintDictionary(NULL); |
| } |
| |
| TEST_F(BrowserThemePackTest, NullColors) { |
| LoadColorDictionary(NULL); |
| } |
| |
| TEST_F(BrowserThemePackTest, NullDisplayProperties) { |
| LoadDisplayPropertiesDictionary(NULL); |
| } |
| |
| TEST_F(BrowserThemePackTest, TestHasCustomImage) { |
| // HasCustomImage should only return true for images that exist in the |
| // extension and not for autogenerated images. |
| std::string images = "{ \"theme_frame\": \"one\" }"; |
| TestFilePathMap out_file_paths; |
| ParseImageNamesJSON(images, &out_file_paths); |
| |
| EXPECT_TRUE(theme_pack_->HasCustomImage(IDR_THEME_FRAME)); |
| EXPECT_FALSE(theme_pack_->HasCustomImage(IDR_THEME_FRAME_INCOGNITO)); |
| } |
| |
| TEST_F(BrowserThemePackTest, TestNonExistantImages) { |
| std::string images = "{ \"theme_frame\": \"does_not_exist\" }"; |
| TestFilePathMap out_file_paths; |
| ParseImageNamesJSON(images, &out_file_paths); |
| |
| EXPECT_FALSE(LoadRawBitmapsTo(out_file_paths)); |
| } |
| |
| // TODO(erg): This test should actually test more of the built resources from |
| // the extension data, but for now, exists so valgrind can test some of the |
| // tricky memory stuff that BrowserThemePack does. |
| TEST_F(BrowserThemePackTest, CanBuildAndReadPack) { |
| base::ScopedTempDir dir; |
| ASSERT_TRUE(dir.CreateUniqueTempDir()); |
| base::FilePath file = dir.path().AppendASCII("data.pak"); |
| |
| // Part 1: Build the pack from an extension. |
| { |
| base::FilePath star_gazing_path = GetStarGazingPath(); |
| scoped_refptr<BrowserThemePack> pack; |
| BuildFromUnpackedExtension(star_gazing_path, pack); |
| ASSERT_TRUE(pack->WriteToDisk(file)); |
| VerifyStarGazing(pack.get()); |
| } |
| |
| // Part 2: Try to read back the data pack that we just wrote to disk. |
| { |
| scoped_refptr<BrowserThemePack> pack = |
| BrowserThemePack::BuildFromDataPack( |
| file, "mblmlcbknbnfebdfjnolmcapmdofhmme"); |
| ASSERT_TRUE(pack.get()); |
| VerifyStarGazing(pack.get()); |
| } |
| } |
| |
| TEST_F(BrowserThemePackTest, HiDpiThemeTest) { |
| base::ScopedTempDir dir; |
| ASSERT_TRUE(dir.CreateUniqueTempDir()); |
| base::FilePath file = dir.path().AppendASCII("theme_data.pak"); |
| |
| // Part 1: Build the pack from an extension. |
| { |
| base::FilePath hidpi_path = GetHiDpiThemePath(); |
| scoped_refptr<BrowserThemePack> pack; |
| BuildFromUnpackedExtension(hidpi_path, pack); |
| ASSERT_TRUE(pack->WriteToDisk(file)); |
| VerifyHiDpiTheme(pack.get()); |
| } |
| |
| // Part 2: Try to read back the data pack that we just wrote to disk. |
| { |
| scoped_refptr<BrowserThemePack> pack = |
| BrowserThemePack::BuildFromDataPack(file, "gllekhaobjnhgeag"); |
| ASSERT_TRUE(pack.get()); |
| VerifyHiDpiTheme(pack.get()); |
| } |
| } |