OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2009 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/browser_theme_pack.h" |
| 6 |
| 7 #include "app/gfx/color_utils.h" |
| 8 #include "app/theme_provider.h" |
| 9 #include "base/file_util.h" |
| 10 #include "base/json/json_reader.h" |
| 11 #include "base/path_service.h" |
| 12 #include "base/scoped_temp_dir.h" |
| 13 #include "base/values.h" |
| 14 #include "chrome/browser/theme_resources_util.h" |
| 15 #include "chrome/browser/browser_theme_provider.h" |
| 16 #include "chrome/common/chrome_paths.h" |
| 17 #include "chrome/common/json_value_serializer.h" |
| 18 #include "grit/theme_resources.h" |
| 19 #include "testing/gtest/include/gtest/gtest.h" |
| 20 |
| 21 class BrowserThemePackTest : public ::testing::Test { |
| 22 public: |
| 23 BrowserThemePackTest() : theme_pack_(new BrowserThemePack) { } |
| 24 |
| 25 // Transformation for link underline colors. |
| 26 SkColor BuildThirdOpacity(SkColor color_link) { |
| 27 return SkColorSetA(color_link, SkColorGetA(color_link) / 3); |
| 28 } |
| 29 |
| 30 void GenerateDefaultFrameColor(std::map<int, SkColor>* colors, |
| 31 int color, int tint) { |
| 32 (*colors)[color] = HSLShift( |
| 33 BrowserThemeProvider::GetDefaultColor( |
| 34 BrowserThemeProvider::COLOR_FRAME), |
| 35 BrowserThemeProvider::GetDefaultTint(tint)); |
| 36 } |
| 37 |
| 38 // Returns a mapping from each COLOR_* constant to the default value for this |
| 39 // constant. Callers get this map, and then modify expected values and then |
| 40 // run the resulting thing through VerifyColorMap(). |
| 41 std::map<int, SkColor> GetDefaultColorMap() { |
| 42 std::map<int, SkColor> colors; |
| 43 for (int i = BrowserThemeProvider::COLOR_FRAME; |
| 44 i <= BrowserThemeProvider::COLOR_BUTTON_BACKGROUND; ++i) { |
| 45 colors[i] = BrowserThemeProvider::GetDefaultColor(i); |
| 46 } |
| 47 |
| 48 GenerateDefaultFrameColor(&colors, BrowserThemeProvider::COLOR_FRAME, |
| 49 BrowserThemeProvider::TINT_FRAME); |
| 50 GenerateDefaultFrameColor(&colors, |
| 51 BrowserThemeProvider::COLOR_FRAME_INACTIVE, |
| 52 BrowserThemeProvider::TINT_FRAME_INACTIVE); |
| 53 GenerateDefaultFrameColor(&colors, |
| 54 BrowserThemeProvider::COLOR_FRAME_INCOGNITO, |
| 55 BrowserThemeProvider::TINT_FRAME_INCOGNITO); |
| 56 GenerateDefaultFrameColor( |
| 57 &colors, |
| 58 BrowserThemeProvider::COLOR_FRAME_INCOGNITO_INACTIVE, |
| 59 BrowserThemeProvider::TINT_FRAME_INCOGNITO_INACTIVE); |
| 60 |
| 61 return colors; |
| 62 } |
| 63 |
| 64 void VerifyColorMap(const std::map<int, SkColor>& color_map) { |
| 65 for (std::map<int, SkColor>::const_iterator it = color_map.begin(); |
| 66 it != color_map.end(); ++it) { |
| 67 SkColor color = BrowserThemeProvider::GetDefaultColor(it->first); |
| 68 theme_pack_->GetColor(it->first, &color); |
| 69 EXPECT_EQ(it->second, color) << "Color id = " << it->first; |
| 70 } |
| 71 } |
| 72 |
| 73 void LoadColorJSON(const std::string& json) { |
| 74 scoped_ptr<Value> value(base::JSONReader::Read(json, false)); |
| 75 ASSERT_TRUE(value->IsType(Value::TYPE_DICTIONARY)); |
| 76 theme_pack_->BuildColorsFromJSON( |
| 77 static_cast<DictionaryValue*>(value.get())); |
| 78 } |
| 79 |
| 80 void LoadTintJSON(const std::string& json) { |
| 81 scoped_ptr<Value> value(base::JSONReader::Read(json, false)); |
| 82 ASSERT_TRUE(value->IsType(Value::TYPE_DICTIONARY)); |
| 83 theme_pack_->BuildTintsFromJSON( |
| 84 static_cast<DictionaryValue*>(value.get())); |
| 85 } |
| 86 |
| 87 void LoadDisplayPropertiesJSON(const std::string& json) { |
| 88 scoped_ptr<Value> value(base::JSONReader::Read(json, false)); |
| 89 ASSERT_TRUE(value->IsType(Value::TYPE_DICTIONARY)); |
| 90 theme_pack_->BuildDisplayPropertiesFromJSON( |
| 91 static_cast<DictionaryValue*>(value.get())); |
| 92 } |
| 93 |
| 94 void ParseImageNames(const std::string& json, |
| 95 std::map<int, FilePath>* out_file_paths) { |
| 96 scoped_ptr<Value> value(base::JSONReader::Read(json, false)); |
| 97 ASSERT_TRUE(value->IsType(Value::TYPE_DICTIONARY)); |
| 98 theme_pack_->ParseImageNamesFromJSON( |
| 99 static_cast<DictionaryValue*>(value.get()), |
| 100 FilePath(), out_file_paths); |
| 101 } |
| 102 |
| 103 FilePath GetStarGazingPath() { |
| 104 FilePath test_path; |
| 105 if (!PathService::Get(chrome::DIR_TEST_DATA, &test_path)) { |
| 106 NOTREACHED(); |
| 107 return test_path; |
| 108 } |
| 109 |
| 110 test_path = test_path.AppendASCII("profiles"); |
| 111 test_path = test_path.AppendASCII("complex_theme"); |
| 112 test_path = test_path.AppendASCII("Default"); |
| 113 test_path = test_path.AppendASCII("Extensions"); |
| 114 test_path = test_path.AppendASCII("mblmlcbknbnfebdfjnolmcapmdofhmme"); |
| 115 test_path = test_path.AppendASCII("1.1"); |
| 116 return FilePath(test_path); |
| 117 } |
| 118 |
| 119 // Verifies the data in star gazing. We do this multiple times for different |
| 120 // BrowserThemePack objects to make sure it works in generated and mmapped |
| 121 // mode correctly. |
| 122 void VerifyStarGazing(BrowserThemePack* pack) { |
| 123 // First check that values we know exist, exist. |
| 124 SkColor color; |
| 125 EXPECT_TRUE(pack->GetColor(BrowserThemeProvider::COLOR_BOOKMARK_TEXT, |
| 126 &color)); |
| 127 EXPECT_EQ(SK_ColorBLACK, color); |
| 128 |
| 129 EXPECT_TRUE(pack->GetColor(BrowserThemeProvider::COLOR_NTP_BACKGROUND, |
| 130 &color)); |
| 131 EXPECT_EQ(SkColorSetRGB(57, 137, 194), color); |
| 132 |
| 133 color_utils::HSL expected = { 0.6, 0.553, 0.5 }; |
| 134 color_utils::HSL actual; |
| 135 EXPECT_TRUE(pack->GetTint(BrowserThemeProvider::TINT_BUTTONS, &actual)); |
| 136 EXPECT_DOUBLE_EQ(expected.h, actual.h); |
| 137 EXPECT_DOUBLE_EQ(expected.s, actual.s); |
| 138 EXPECT_DOUBLE_EQ(expected.l, actual.l); |
| 139 |
| 140 int val; |
| 141 EXPECT_TRUE(pack->GetDisplayProperty( |
| 142 BrowserThemeProvider::NTP_BACKGROUND_ALIGNMENT, &val)); |
| 143 EXPECT_EQ(BrowserThemeProvider::ALIGN_TOP, val); |
| 144 |
| 145 EXPECT_TRUE(pack->HasCustomImage(IDR_THEME_FRAME)); |
| 146 |
| 147 // Make sure we don't have phantom data. |
| 148 EXPECT_FALSE(pack->GetColor(BrowserThemeProvider::COLOR_CONTROL_BACKGROUND, |
| 149 &color)); |
| 150 EXPECT_FALSE(pack->GetTint(BrowserThemeProvider::TINT_FRAME, &actual)); |
| 151 } |
| 152 |
| 153 scoped_refptr<BrowserThemePack> theme_pack_; |
| 154 }; |
| 155 |
| 156 |
| 157 TEST_F(BrowserThemePackTest, DeriveUnderlineLinkColor) { |
| 158 // If we specify a link color, but don't specify the underline color, the |
| 159 // theme provider should create one. |
| 160 std::string color_json = "{ \"ntp_link\": [128, 128, 128]," |
| 161 " \"ntp_section_link\": [128, 128, 128] }"; |
| 162 LoadColorJSON(color_json); |
| 163 |
| 164 std::map<int, SkColor> colors = GetDefaultColorMap(); |
| 165 SkColor link_color = SkColorSetRGB(128, 128, 128); |
| 166 colors[BrowserThemeProvider::COLOR_NTP_LINK] = link_color; |
| 167 colors[BrowserThemeProvider::COLOR_NTP_LINK_UNDERLINE] = |
| 168 BuildThirdOpacity(link_color); |
| 169 colors[BrowserThemeProvider::COLOR_NTP_SECTION_LINK] = link_color; |
| 170 colors[BrowserThemeProvider::COLOR_NTP_SECTION_LINK_UNDERLINE] = |
| 171 BuildThirdOpacity(link_color); |
| 172 |
| 173 VerifyColorMap(colors); |
| 174 } |
| 175 |
| 176 TEST_F(BrowserThemePackTest, ProvideUnderlineLinkColor) { |
| 177 // If we specify the underline color, it shouldn't try to generate one.x |
| 178 std::string color_json = "{ \"ntp_link\": [128, 128, 128]," |
| 179 " \"ntp_link_underline\": [255, 255, 255]," |
| 180 " \"ntp_section_link\": [128, 128, 128]," |
| 181 " \"ntp_section_link_underline\": [255, 255, 255]" |
| 182 "}"; |
| 183 LoadColorJSON(color_json); |
| 184 |
| 185 std::map<int, SkColor> colors = GetDefaultColorMap(); |
| 186 SkColor link_color = SkColorSetRGB(128, 128, 128); |
| 187 SkColor underline_color = SkColorSetRGB(255, 255, 255); |
| 188 colors[BrowserThemeProvider::COLOR_NTP_LINK] = link_color; |
| 189 colors[BrowserThemeProvider::COLOR_NTP_LINK_UNDERLINE] = underline_color; |
| 190 colors[BrowserThemeProvider::COLOR_NTP_SECTION_LINK] = link_color; |
| 191 colors[BrowserThemeProvider::COLOR_NTP_SECTION_LINK_UNDERLINE] = |
| 192 underline_color; |
| 193 |
| 194 VerifyColorMap(colors); |
| 195 } |
| 196 |
| 197 TEST_F(BrowserThemePackTest, UseSectionColorAsNTPHeader) { |
| 198 std::string color_json = "{ \"ntp_section\": [190, 190, 190] }"; |
| 199 LoadColorJSON(color_json); |
| 200 |
| 201 std::map<int, SkColor> colors = GetDefaultColorMap(); |
| 202 SkColor ntp_color = SkColorSetRGB(190, 190, 190); |
| 203 colors[BrowserThemeProvider::COLOR_NTP_HEADER] = ntp_color; |
| 204 colors[BrowserThemeProvider::COLOR_NTP_SECTION] = ntp_color; |
| 205 VerifyColorMap(colors); |
| 206 } |
| 207 |
| 208 TEST_F(BrowserThemePackTest, ProvideNtpHeaderColor) { |
| 209 std::string color_json = "{ \"ntp_header\": [120, 120, 120], " |
| 210 " \"ntp_section\": [190, 190, 190] }"; |
| 211 LoadColorJSON(color_json); |
| 212 |
| 213 std::map<int, SkColor> colors = GetDefaultColorMap(); |
| 214 SkColor ntp_header = SkColorSetRGB(120, 120, 120); |
| 215 SkColor ntp_section = SkColorSetRGB(190, 190, 190); |
| 216 colors[BrowserThemeProvider::COLOR_NTP_HEADER] = ntp_header; |
| 217 colors[BrowserThemeProvider::COLOR_NTP_SECTION] = ntp_section; |
| 218 VerifyColorMap(colors); |
| 219 } |
| 220 |
| 221 TEST_F(BrowserThemePackTest, CanReadTints) { |
| 222 std::string tint_json = "{ \"buttons\": [ 0.5, 0.5, 0.5 ] }"; |
| 223 LoadTintJSON(tint_json); |
| 224 |
| 225 color_utils::HSL expected = { 0.5, 0.5, 0.5 }; |
| 226 color_utils::HSL actual = { -1, -1, -1 }; |
| 227 EXPECT_TRUE(theme_pack_->GetTint( |
| 228 BrowserThemeProvider::TINT_BUTTONS, &actual)); |
| 229 EXPECT_DOUBLE_EQ(expected.h, actual.h); |
| 230 EXPECT_DOUBLE_EQ(expected.s, actual.s); |
| 231 EXPECT_DOUBLE_EQ(expected.l, actual.l); |
| 232 } |
| 233 |
| 234 TEST_F(BrowserThemePackTest, CanReadDisplayProperties) { |
| 235 std::string json = "{ \"ntp_background_alignment\": \"bottom\", " |
| 236 " \"ntp_background_repeat\": \"repeat-x\", " |
| 237 " \"ntp_logo_alternate\": 0 }"; |
| 238 LoadDisplayPropertiesJSON(json); |
| 239 |
| 240 int out_val; |
| 241 EXPECT_TRUE(theme_pack_->GetDisplayProperty( |
| 242 BrowserThemeProvider::NTP_BACKGROUND_ALIGNMENT, &out_val)); |
| 243 EXPECT_EQ(BrowserThemeProvider::ALIGN_BOTTOM, out_val); |
| 244 |
| 245 EXPECT_TRUE(theme_pack_->GetDisplayProperty( |
| 246 BrowserThemeProvider::NTP_BACKGROUND_TILING, &out_val)); |
| 247 EXPECT_EQ(BrowserThemeProvider::REPEAT_X, out_val); |
| 248 |
| 249 EXPECT_TRUE(theme_pack_->GetDisplayProperty( |
| 250 BrowserThemeProvider::NTP_LOGO_ALTERNATE, &out_val)); |
| 251 EXPECT_EQ(0, out_val); |
| 252 } |
| 253 |
| 254 TEST_F(BrowserThemePackTest, CanParsePaths) { |
| 255 std::string tint_json = "{ \"theme_button_background\": \"one\", " |
| 256 " \"theme_toolbar\": \"two\" }"; |
| 257 std::map<int, FilePath> out_file_paths; |
| 258 ParseImageNames(tint_json, &out_file_paths); |
| 259 |
| 260 EXPECT_EQ(2u, out_file_paths.size()); |
| 261 EXPECT_TRUE(FilePath(FILE_PATH_LITERAL("one")) == out_file_paths[ |
| 262 ThemeResourcesUtil::GetId("theme_button_background")]); |
| 263 EXPECT_TRUE(FilePath(FILE_PATH_LITERAL("two")) == |
| 264 out_file_paths[ThemeResourcesUtil::GetId("theme_toolbar")]); |
| 265 } |
| 266 |
| 267 TEST_F(BrowserThemePackTest, InvalidColors) { |
| 268 std::string invalid_color = "{ \"toolbar\": [\"dog\", \"cat\", [12]], " |
| 269 " \"sound\": \"woof\" }"; |
| 270 LoadColorJSON(invalid_color); |
| 271 std::map<int, SkColor> colors = GetDefaultColorMap(); |
| 272 VerifyColorMap(colors); |
| 273 } |
| 274 |
| 275 TEST_F(BrowserThemePackTest, InvalidTints) { |
| 276 std::string invalid_tints = "{ \"buttons\": [ \"dog\", \"cat\", [\"x\"]], " |
| 277 " \"invalid\": \"entry\" }"; |
| 278 LoadTintJSON(invalid_tints); |
| 279 |
| 280 // We shouldn't have a buttons tint, as it was invalid. |
| 281 color_utils::HSL actual = { -1, -1, -1 }; |
| 282 EXPECT_FALSE(theme_pack_->GetTint(BrowserThemeProvider::TINT_BUTTONS, |
| 283 &actual)); |
| 284 } |
| 285 |
| 286 TEST_F(BrowserThemePackTest, InvalidDisplayProperties) { |
| 287 std::string invalid_properties = "{ \"ntp_background_alignment\": [15], " |
| 288 " \"junk\": [15.3] }"; |
| 289 LoadDisplayPropertiesJSON(invalid_properties); |
| 290 |
| 291 int out_val; |
| 292 EXPECT_FALSE(theme_pack_->GetDisplayProperty( |
| 293 BrowserThemeProvider::NTP_BACKGROUND_ALIGNMENT, &out_val)); |
| 294 } |
| 295 |
| 296 // TODO(erg): This test should actually test more of the built resources from |
| 297 // the extension data, but for now, exists so valgrind can test some of the |
| 298 // tricky memory stuff that BrowserThemePack does. |
| 299 TEST_F(BrowserThemePackTest, CanBuildAndReadPack) { |
| 300 ScopedTempDir dir; |
| 301 ASSERT_TRUE(dir.CreateUniqueTempDir()); |
| 302 FilePath file = dir.path().Append(FILE_PATH_LITERAL("data.pak")); |
| 303 |
| 304 // Part 1: Build the pack from an extension. |
| 305 { |
| 306 FilePath star_gazing_path = GetStarGazingPath(); |
| 307 Extension extension(star_gazing_path); |
| 308 |
| 309 FilePath manifest_path = |
| 310 star_gazing_path.AppendASCII("manifest.json"); |
| 311 std::string error; |
| 312 JSONFileValueSerializer serializer(manifest_path); |
| 313 scoped_ptr<DictionaryValue> valid_value( |
| 314 static_cast<DictionaryValue*>(serializer.Deserialize(&error))); |
| 315 EXPECT_EQ("", error); |
| 316 ASSERT_TRUE(valid_value.get()); |
| 317 ASSERT_TRUE(extension.InitFromValue(*valid_value, true, &error)); |
| 318 ASSERT_EQ("", error); |
| 319 |
| 320 scoped_refptr<BrowserThemePack> pack = |
| 321 BrowserThemePack::BuildFromExtension(&extension); |
| 322 ASSERT_TRUE(pack.get()); |
| 323 ASSERT_TRUE(pack->WriteToDisk(file)); |
| 324 VerifyStarGazing(pack.get()); |
| 325 } |
| 326 |
| 327 // Part 2: Try to read back the data pack that we just wrote to disk. |
| 328 { |
| 329 scoped_refptr<BrowserThemePack> pack = |
| 330 BrowserThemePack::BuildFromDataPack( |
| 331 file, "mblmlcbknbnfebdfjnolmcapmdofhmme"); |
| 332 ASSERT_TRUE(pack.get()); |
| 333 VerifyStarGazing(pack.get()); |
| 334 } |
| 335 } |
OLD | NEW |