diff options
author | erg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-23 17:36:42 +0000 |
---|---|---|
committer | erg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-23 17:36:42 +0000 |
commit | a0ea76cbf036408912e337653500aaefd51586b9 (patch) | |
tree | ed1bf3f0a50025df8c2d4b7e083593ded4d2e01a /chrome/browser/themes | |
parent | 58492209d54a3af3e40fa0a876c9d6381d943188 (diff) | |
download | chromium_src-a0ea76cbf036408912e337653500aaefd51586b9.zip chromium_src-a0ea76cbf036408912e337653500aaefd51586b9.tar.gz chromium_src-a0ea76cbf036408912e337653500aaefd51586b9.tar.bz2 |
Theme system cleanup
- Removes useless dependencies on themeing from content/
- Renames BrowserThemeProvider to ThemeService, along with name variants such
as GtkThemeService. BrowserThemeProvider has grown by a lot to be more than
an implementation of the ui::ThemeProvider interface. This change touches
everything.
- Rename theme_service.{h,cc} (which defined ThemeServiceFactory) to
theme_service_factory.{h,cc}.
BUG=77155
TEST=compiles.
Review URL: http://codereview.chromium.org/6727005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@79145 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/themes')
-rw-r--r-- | chrome/browser/themes/browser_theme_pack.cc | 156 | ||||
-rw-r--r-- | chrome/browser/themes/browser_theme_pack_unittest.cc | 88 | ||||
-rw-r--r-- | chrome/browser/themes/browser_theme_provider.cc | 644 | ||||
-rw-r--r-- | chrome/browser/themes/browser_theme_provider.h | 288 | ||||
-rw-r--r-- | chrome/browser/themes/browser_theme_provider_unittest.cc | 51 | ||||
-rw-r--r-- | chrome/browser/themes/theme_service.cc | 677 | ||||
-rw-r--r-- | chrome/browser/themes/theme_service.h | 295 | ||||
-rw-r--r-- | chrome/browser/themes/theme_service_factory.cc | 109 | ||||
-rw-r--r-- | chrome/browser/themes/theme_service_factory.h | 59 | ||||
-rw-r--r-- | chrome/browser/themes/theme_service_gtk.cc (renamed from chrome/browser/themes/browser_theme_provider_gtk.cc) | 12 | ||||
-rw-r--r-- | chrome/browser/themes/theme_service_mac.mm (renamed from chrome/browser/themes/browser_theme_provider_mac.mm) | 24 | ||||
-rw-r--r-- | chrome/browser/themes/theme_service_unittest.cc | 51 |
12 files changed, 1225 insertions, 1229 deletions
diff --git a/chrome/browser/themes/browser_theme_pack.cc b/chrome/browser/themes/browser_theme_pack.cc index 71c6116..93633a9 100644 --- a/chrome/browser/themes/browser_theme_pack.cc +++ b/chrome/browser/themes/browser_theme_pack.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -9,7 +9,7 @@ #include "base/threading/thread_restrictions.h" #include "base/utf_string_conversions.h" #include "base/values.h" -#include "chrome/browser/themes/browser_theme_provider.h" +#include "chrome/browser/themes/theme_service.h" #include "content/browser/browser_thread.h" #include "grit/app_resources.h" #include "grit/theme_resources.h" @@ -174,57 +174,57 @@ struct StringToIntTable { // Strings used by themes to identify tints in the JSON. StringToIntTable kTintTable[] = { - { "buttons", BrowserThemeProvider::TINT_BUTTONS }, - { "frame", BrowserThemeProvider::TINT_FRAME }, - { "frame_inactive", BrowserThemeProvider::TINT_FRAME_INACTIVE }, - { "frame_incognito", BrowserThemeProvider::TINT_FRAME_INCOGNITO }, + { "buttons", ThemeService::TINT_BUTTONS }, + { "frame", ThemeService::TINT_FRAME }, + { "frame_inactive", ThemeService::TINT_FRAME_INACTIVE }, + { "frame_incognito", ThemeService::TINT_FRAME_INCOGNITO }, { "frame_incognito_inactive", - BrowserThemeProvider::TINT_FRAME_INCOGNITO_INACTIVE }, - { "background_tab", BrowserThemeProvider::TINT_BACKGROUND_TAB }, + ThemeService::TINT_FRAME_INCOGNITO_INACTIVE }, + { "background_tab", ThemeService::TINT_BACKGROUND_TAB }, { NULL, 0 } }; // Strings used by themes to identify colors in the JSON. StringToIntTable kColorTable[] = { - { "frame", BrowserThemeProvider::COLOR_FRAME }, - { "frame_inactive", BrowserThemeProvider::COLOR_FRAME_INACTIVE }, - { "frame_incognito", BrowserThemeProvider::COLOR_FRAME_INCOGNITO }, + { "frame", ThemeService::COLOR_FRAME }, + { "frame_inactive", ThemeService::COLOR_FRAME_INACTIVE }, + { "frame_incognito", ThemeService::COLOR_FRAME_INCOGNITO }, { "frame_incognito_inactive", - BrowserThemeProvider::COLOR_FRAME_INCOGNITO_INACTIVE }, - { "toolbar", BrowserThemeProvider::COLOR_TOOLBAR }, - { "tab_text", BrowserThemeProvider::COLOR_TAB_TEXT }, - { "tab_background_text", BrowserThemeProvider::COLOR_BACKGROUND_TAB_TEXT }, - { "bookmark_text", BrowserThemeProvider::COLOR_BOOKMARK_TEXT }, - { "ntp_background", BrowserThemeProvider::COLOR_NTP_BACKGROUND }, - { "ntp_text", BrowserThemeProvider::COLOR_NTP_TEXT }, - { "ntp_link", BrowserThemeProvider::COLOR_NTP_LINK }, - { "ntp_link_underline", BrowserThemeProvider::COLOR_NTP_LINK_UNDERLINE }, - { "ntp_header", BrowserThemeProvider::COLOR_NTP_HEADER }, - { "ntp_section", BrowserThemeProvider::COLOR_NTP_SECTION }, - { "ntp_section_text", BrowserThemeProvider::COLOR_NTP_SECTION_TEXT }, - { "ntp_section_link", BrowserThemeProvider::COLOR_NTP_SECTION_LINK }, + ThemeService::COLOR_FRAME_INCOGNITO_INACTIVE }, + { "toolbar", ThemeService::COLOR_TOOLBAR }, + { "tab_text", ThemeService::COLOR_TAB_TEXT }, + { "tab_background_text", ThemeService::COLOR_BACKGROUND_TAB_TEXT }, + { "bookmark_text", ThemeService::COLOR_BOOKMARK_TEXT }, + { "ntp_background", ThemeService::COLOR_NTP_BACKGROUND }, + { "ntp_text", ThemeService::COLOR_NTP_TEXT }, + { "ntp_link", ThemeService::COLOR_NTP_LINK }, + { "ntp_link_underline", ThemeService::COLOR_NTP_LINK_UNDERLINE }, + { "ntp_header", ThemeService::COLOR_NTP_HEADER }, + { "ntp_section", ThemeService::COLOR_NTP_SECTION }, + { "ntp_section_text", ThemeService::COLOR_NTP_SECTION_TEXT }, + { "ntp_section_link", ThemeService::COLOR_NTP_SECTION_LINK }, { "ntp_section_link_underline", - BrowserThemeProvider::COLOR_NTP_SECTION_LINK_UNDERLINE }, - { "control_background", BrowserThemeProvider::COLOR_CONTROL_BACKGROUND }, - { "button_background", BrowserThemeProvider::COLOR_BUTTON_BACKGROUND }, + ThemeService::COLOR_NTP_SECTION_LINK_UNDERLINE }, + { "control_background", ThemeService::COLOR_CONTROL_BACKGROUND }, + { "button_background", ThemeService::COLOR_BUTTON_BACKGROUND }, { NULL, 0 } }; // Strings used by themes to identify display properties keys in JSON. StringToIntTable kDisplayProperties[] = { { "ntp_background_alignment", - BrowserThemeProvider::NTP_BACKGROUND_ALIGNMENT }, - { "ntp_background_repeat", BrowserThemeProvider::NTP_BACKGROUND_TILING }, - { "ntp_logo_alternate", BrowserThemeProvider::NTP_LOGO_ALTERNATE }, + ThemeService::NTP_BACKGROUND_ALIGNMENT }, + { "ntp_background_repeat", ThemeService::NTP_BACKGROUND_TILING }, + { "ntp_logo_alternate", ThemeService::NTP_LOGO_ALTERNATE }, { NULL, 0 } }; // Strings used by the tiling values in JSON. StringToIntTable kTilingStrings[] = { - { "no-repeat", BrowserThemeProvider::NO_REPEAT }, - { "repeat-x", BrowserThemeProvider::REPEAT_X }, - { "repeat-y", BrowserThemeProvider::REPEAT_Y }, - { "repeat", BrowserThemeProvider::REPEAT }, + { "no-repeat", ThemeService::NO_REPEAT }, + { "repeat-x", ThemeService::REPEAT_X }, + { "repeat-y", ThemeService::REPEAT_Y }, + { "repeat", ThemeService::REPEAT }, { NULL, 0 } }; @@ -246,14 +246,14 @@ struct IntToIntTable { // Mapping used in GenerateFrameImages() to associate frame images with the // tint ID that should maybe be applied to it. IntToIntTable kFrameTintMap[] = { - { PRS_THEME_FRAME, BrowserThemeProvider::TINT_FRAME }, - { PRS_THEME_FRAME_INACTIVE, BrowserThemeProvider::TINT_FRAME_INACTIVE }, - { PRS_THEME_FRAME_OVERLAY, BrowserThemeProvider::TINT_FRAME }, + { PRS_THEME_FRAME, ThemeService::TINT_FRAME }, + { PRS_THEME_FRAME_INACTIVE, ThemeService::TINT_FRAME_INACTIVE }, + { PRS_THEME_FRAME_OVERLAY, ThemeService::TINT_FRAME }, { PRS_THEME_FRAME_OVERLAY_INACTIVE, - BrowserThemeProvider::TINT_FRAME_INACTIVE }, - { PRS_THEME_FRAME_INCOGNITO, BrowserThemeProvider::TINT_FRAME_INCOGNITO }, + ThemeService::TINT_FRAME_INACTIVE }, + { PRS_THEME_FRAME_INCOGNITO, ThemeService::TINT_FRAME_INCOGNITO }, { PRS_THEME_FRAME_INCOGNITO_INACTIVE, - BrowserThemeProvider::TINT_FRAME_INCOGNITO_INACTIVE } + ThemeService::TINT_FRAME_INCOGNITO_INACTIVE } }; // Mapping used in GenerateTabBackgroundImages() to associate what frame image @@ -355,7 +355,7 @@ BrowserThemePack* BrowserThemePack::BuildFromExtension( // OSX uses its own special buttons that are PDFs that do odd sorts of vector // graphics tricks. Other platforms use bitmaps and we must pre-tint them. pack->GenerateTintedButtons( - pack->GetTintInternal(BrowserThemeProvider::TINT_BUTTONS), + pack->GetTintInternal(ThemeService::TINT_BUTTONS), &pack->prepared_images_); #endif @@ -705,56 +705,56 @@ void BrowserThemePack::ReadColorsFromJSON( void BrowserThemePack::GenerateMissingColors( std::map<int, SkColor>* colors) { // Generate link colors, if missing. (See GetColor()). - if (!colors->count(BrowserThemeProvider::COLOR_NTP_HEADER) && - colors->count(BrowserThemeProvider::COLOR_NTP_SECTION)) { - (*colors)[BrowserThemeProvider::COLOR_NTP_HEADER] = - (*colors)[BrowserThemeProvider::COLOR_NTP_SECTION]; + if (!colors->count(ThemeService::COLOR_NTP_HEADER) && + colors->count(ThemeService::COLOR_NTP_SECTION)) { + (*colors)[ThemeService::COLOR_NTP_HEADER] = + (*colors)[ThemeService::COLOR_NTP_SECTION]; } - if (!colors->count(BrowserThemeProvider::COLOR_NTP_SECTION_LINK_UNDERLINE) && - colors->count(BrowserThemeProvider::COLOR_NTP_SECTION_LINK)) { + if (!colors->count(ThemeService::COLOR_NTP_SECTION_LINK_UNDERLINE) && + colors->count(ThemeService::COLOR_NTP_SECTION_LINK)) { SkColor color_section_link = - (*colors)[BrowserThemeProvider::COLOR_NTP_SECTION_LINK]; - (*colors)[BrowserThemeProvider::COLOR_NTP_SECTION_LINK_UNDERLINE] = + (*colors)[ThemeService::COLOR_NTP_SECTION_LINK]; + (*colors)[ThemeService::COLOR_NTP_SECTION_LINK_UNDERLINE] = SkColorSetA(color_section_link, SkColorGetA(color_section_link) / 3); } - if (!colors->count(BrowserThemeProvider::COLOR_NTP_LINK_UNDERLINE) && - colors->count(BrowserThemeProvider::COLOR_NTP_LINK)) { - SkColor color_link = (*colors)[BrowserThemeProvider::COLOR_NTP_LINK]; - (*colors)[BrowserThemeProvider::COLOR_NTP_LINK_UNDERLINE] = + if (!colors->count(ThemeService::COLOR_NTP_LINK_UNDERLINE) && + colors->count(ThemeService::COLOR_NTP_LINK)) { + SkColor color_link = (*colors)[ThemeService::COLOR_NTP_LINK]; + (*colors)[ThemeService::COLOR_NTP_LINK_UNDERLINE] = SkColorSetA(color_link, SkColorGetA(color_link) / 3); } // Generate frame colors, if missing. (See GenerateFrameColors()). SkColor frame; std::map<int, SkColor>::const_iterator it = - colors->find(BrowserThemeProvider::COLOR_FRAME); + colors->find(ThemeService::COLOR_FRAME); if (it != colors->end()) { frame = it->second; } else { - frame = BrowserThemeProvider::GetDefaultColor( - BrowserThemeProvider::COLOR_FRAME); + frame = ThemeService::GetDefaultColor( + ThemeService::COLOR_FRAME); } - if (!colors->count(BrowserThemeProvider::COLOR_FRAME)) { - (*colors)[BrowserThemeProvider::COLOR_FRAME] = - HSLShift(frame, GetTintInternal(BrowserThemeProvider::TINT_FRAME)); + if (!colors->count(ThemeService::COLOR_FRAME)) { + (*colors)[ThemeService::COLOR_FRAME] = + HSLShift(frame, GetTintInternal(ThemeService::TINT_FRAME)); } - if (!colors->count(BrowserThemeProvider::COLOR_FRAME_INACTIVE)) { - (*colors)[BrowserThemeProvider::COLOR_FRAME_INACTIVE] = + if (!colors->count(ThemeService::COLOR_FRAME_INACTIVE)) { + (*colors)[ThemeService::COLOR_FRAME_INACTIVE] = HSLShift(frame, GetTintInternal( - BrowserThemeProvider::TINT_FRAME_INACTIVE)); + ThemeService::TINT_FRAME_INACTIVE)); } - if (!colors->count(BrowserThemeProvider::COLOR_FRAME_INCOGNITO)) { - (*colors)[BrowserThemeProvider::COLOR_FRAME_INCOGNITO] = + if (!colors->count(ThemeService::COLOR_FRAME_INCOGNITO)) { + (*colors)[ThemeService::COLOR_FRAME_INCOGNITO] = HSLShift(frame, GetTintInternal( - BrowserThemeProvider::TINT_FRAME_INCOGNITO)); + ThemeService::TINT_FRAME_INCOGNITO)); } - if (!colors->count(BrowserThemeProvider::COLOR_FRAME_INCOGNITO_INACTIVE)) { - (*colors)[BrowserThemeProvider::COLOR_FRAME_INCOGNITO_INACTIVE] = + if (!colors->count(ThemeService::COLOR_FRAME_INCOGNITO_INACTIVE)) { + (*colors)[ThemeService::COLOR_FRAME_INCOGNITO_INACTIVE] = HSLShift(frame, GetTintInternal( - BrowserThemeProvider::TINT_FRAME_INCOGNITO_INACTIVE)); + ThemeService::TINT_FRAME_INCOGNITO_INACTIVE)); } } @@ -775,26 +775,26 @@ void BrowserThemePack::BuildDisplayPropertiesFromJSON( iter != display_properties_value->end_keys(); ++iter) { int property_id = GetIntForString(*iter, kDisplayProperties); switch (property_id) { - case BrowserThemeProvider::NTP_BACKGROUND_ALIGNMENT: { + case ThemeService::NTP_BACKGROUND_ALIGNMENT: { std::string val; if (display_properties_value->GetString(*iter, &val)) { - temp_properties[BrowserThemeProvider::NTP_BACKGROUND_ALIGNMENT] = - BrowserThemeProvider::StringToAlignment(val); + temp_properties[ThemeService::NTP_BACKGROUND_ALIGNMENT] = + ThemeService::StringToAlignment(val); } break; } - case BrowserThemeProvider::NTP_BACKGROUND_TILING: { + case ThemeService::NTP_BACKGROUND_TILING: { std::string val; if (display_properties_value->GetString(*iter, &val)) { - temp_properties[BrowserThemeProvider::NTP_BACKGROUND_TILING] = + temp_properties[ThemeService::NTP_BACKGROUND_TILING] = GetIntForString(val, kTilingStrings); } break; } - case BrowserThemeProvider::NTP_LOGO_ALTERNATE: { + case ThemeService::NTP_LOGO_ALTERNATE: { int val = 0; if (display_properties_value->GetInteger(*iter, &val)) - temp_properties[BrowserThemeProvider::NTP_LOGO_ALTERNATE] = val; + temp_properties[ThemeService::NTP_LOGO_ALTERNATE] = val; break; } } @@ -945,7 +945,7 @@ void BrowserThemePack::GenerateTintedButtons( if (button_tint.h != -1 || button_tint.s != -1 || button_tint.l != -1) { ResourceBundle& rb = ResourceBundle::GetSharedInstance(); const std::set<int>& idr_ids = - BrowserThemeProvider::GetTintableToolbarButtons(); + ThemeService::GetTintableToolbarButtons(); for (std::set<int>::const_iterator it = idr_ids.begin(); it != idr_ids.end(); ++it) { int prs_id = GetPersistentIDByIDR(*it); @@ -973,7 +973,7 @@ void BrowserThemePack::GenerateTabBackgroundImages(ImageCache* bitmaps) const { if (it != bitmaps->end()) { SkBitmap bg_tint = SkBitmapOperations::CreateHSLShiftedBitmap( *(it->second), GetTintInternal( - BrowserThemeProvider::TINT_BACKGROUND_TAB)); + ThemeService::TINT_BACKGROUND_TAB)); int vertical_offset = bitmaps->count(prs_id) ? kRestoredTabVerticalOffset : 0; SkBitmap* bg_tab = new SkBitmap(SkBitmapOperations::CreateTiledBitmap( @@ -1046,5 +1046,5 @@ color_utils::HSL BrowserThemePack::GetTintInternal(int id) const { } } - return BrowserThemeProvider::GetDefaultTint(id); + return ThemeService::GetDefaultTint(id); } diff --git a/chrome/browser/themes/browser_theme_pack_unittest.cc b/chrome/browser/themes/browser_theme_pack_unittest.cc index 72219f0..7eb8b5f 100644 --- a/chrome/browser/themes/browser_theme_pack_unittest.cc +++ b/chrome/browser/themes/browser_theme_pack_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -10,7 +10,7 @@ #include "base/path_service.h" #include "base/scoped_temp_dir.h" #include "base/values.h" -#include "chrome/browser/themes/browser_theme_provider.h" +#include "chrome/browser/themes/theme_service.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/json_value_serializer.h" #include "content/browser/browser_thread.h" @@ -35,9 +35,9 @@ class BrowserThemePackTest : public ::testing::Test { void GenerateDefaultFrameColor(std::map<int, SkColor>* colors, int color, int tint) { (*colors)[color] = HSLShift( - BrowserThemeProvider::GetDefaultColor( - BrowserThemeProvider::COLOR_FRAME), - BrowserThemeProvider::GetDefaultTint(tint)); + ThemeService::GetDefaultColor( + ThemeService::COLOR_FRAME), + ThemeService::GetDefaultTint(tint)); } // Returns a mapping from each COLOR_* constant to the default value for this @@ -45,23 +45,23 @@ class BrowserThemePackTest : public ::testing::Test { // run the resulting thing through VerifyColorMap(). std::map<int, SkColor> GetDefaultColorMap() { std::map<int, SkColor> colors; - for (int i = BrowserThemeProvider::COLOR_FRAME; - i <= BrowserThemeProvider::COLOR_BUTTON_BACKGROUND; ++i) { - colors[i] = BrowserThemeProvider::GetDefaultColor(i); + for (int i = ThemeService::COLOR_FRAME; + i <= ThemeService::COLOR_BUTTON_BACKGROUND; ++i) { + colors[i] = ThemeService::GetDefaultColor(i); } - GenerateDefaultFrameColor(&colors, BrowserThemeProvider::COLOR_FRAME, - BrowserThemeProvider::TINT_FRAME); + GenerateDefaultFrameColor(&colors, ThemeService::COLOR_FRAME, + ThemeService::TINT_FRAME); GenerateDefaultFrameColor(&colors, - BrowserThemeProvider::COLOR_FRAME_INACTIVE, - BrowserThemeProvider::TINT_FRAME_INACTIVE); + ThemeService::COLOR_FRAME_INACTIVE, + ThemeService::TINT_FRAME_INACTIVE); GenerateDefaultFrameColor(&colors, - BrowserThemeProvider::COLOR_FRAME_INCOGNITO, - BrowserThemeProvider::TINT_FRAME_INCOGNITO); + ThemeService::COLOR_FRAME_INCOGNITO, + ThemeService::TINT_FRAME_INCOGNITO); GenerateDefaultFrameColor( &colors, - BrowserThemeProvider::COLOR_FRAME_INCOGNITO_INACTIVE, - BrowserThemeProvider::TINT_FRAME_INCOGNITO_INACTIVE); + ThemeService::COLOR_FRAME_INCOGNITO_INACTIVE, + ThemeService::TINT_FRAME_INCOGNITO_INACTIVE); return colors; } @@ -69,7 +69,7 @@ class BrowserThemePackTest : public ::testing::Test { 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 = BrowserThemeProvider::GetDefaultColor(it->first); + SkColor color = ThemeService::GetDefaultColor(it->first); theme_pack_->GetColor(it->first, &color); EXPECT_EQ(it->second, color) << "Color id = " << it->first; } @@ -148,25 +148,25 @@ class BrowserThemePackTest : public ::testing::Test { void VerifyStarGazing(BrowserThemePack* pack) { // First check that values we know exist, exist. SkColor color; - EXPECT_TRUE(pack->GetColor(BrowserThemeProvider::COLOR_BOOKMARK_TEXT, + EXPECT_TRUE(pack->GetColor(ThemeService::COLOR_BOOKMARK_TEXT, &color)); EXPECT_EQ(SK_ColorBLACK, color); - EXPECT_TRUE(pack->GetColor(BrowserThemeProvider::COLOR_NTP_BACKGROUND, + EXPECT_TRUE(pack->GetColor(ThemeService::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(BrowserThemeProvider::TINT_BUTTONS, &actual)); + EXPECT_TRUE(pack->GetTint(ThemeService::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( - BrowserThemeProvider::NTP_BACKGROUND_ALIGNMENT, &val)); - EXPECT_EQ(BrowserThemeProvider::ALIGN_TOP, val); + ThemeService::NTP_BACKGROUND_ALIGNMENT, &val)); + EXPECT_EQ(ThemeService::ALIGN_TOP, val); // The stargazing theme defines the following images: EXPECT_TRUE(pack->HasCustomImage(IDR_THEME_BUTTON_BACKGROUND)); @@ -185,9 +185,9 @@ class BrowserThemePackTest : public ::testing::Test { EXPECT_FALSE(pack->HasCustomImage(IDR_THEME_TAB_BACKGROUND_INCOGNITO)); // Make sure we don't have phantom data. - EXPECT_FALSE(pack->GetColor(BrowserThemeProvider::COLOR_CONTROL_BACKGROUND, + EXPECT_FALSE(pack->GetColor(ThemeService::COLOR_CONTROL_BACKGROUND, &color)); - EXPECT_FALSE(pack->GetTint(BrowserThemeProvider::TINT_FRAME, &actual)); + EXPECT_FALSE(pack->GetTint(ThemeService::TINT_FRAME, &actual)); } MessageLoop message_loop; @@ -207,11 +207,11 @@ TEST_F(BrowserThemePackTest, DeriveUnderlineLinkColor) { std::map<int, SkColor> colors = GetDefaultColorMap(); SkColor link_color = SkColorSetRGB(128, 128, 128); - colors[BrowserThemeProvider::COLOR_NTP_LINK] = link_color; - colors[BrowserThemeProvider::COLOR_NTP_LINK_UNDERLINE] = + colors[ThemeService::COLOR_NTP_LINK] = link_color; + colors[ThemeService::COLOR_NTP_LINK_UNDERLINE] = BuildThirdOpacity(link_color); - colors[BrowserThemeProvider::COLOR_NTP_SECTION_LINK] = link_color; - colors[BrowserThemeProvider::COLOR_NTP_SECTION_LINK_UNDERLINE] = + colors[ThemeService::COLOR_NTP_SECTION_LINK] = link_color; + colors[ThemeService::COLOR_NTP_SECTION_LINK_UNDERLINE] = BuildThirdOpacity(link_color); VerifyColorMap(colors); @@ -229,10 +229,10 @@ TEST_F(BrowserThemePackTest, ProvideUnderlineLinkColor) { std::map<int, SkColor> colors = GetDefaultColorMap(); SkColor link_color = SkColorSetRGB(128, 128, 128); SkColor underline_color = SkColorSetRGB(255, 255, 255); - colors[BrowserThemeProvider::COLOR_NTP_LINK] = link_color; - colors[BrowserThemeProvider::COLOR_NTP_LINK_UNDERLINE] = underline_color; - colors[BrowserThemeProvider::COLOR_NTP_SECTION_LINK] = link_color; - colors[BrowserThemeProvider::COLOR_NTP_SECTION_LINK_UNDERLINE] = + colors[ThemeService::COLOR_NTP_LINK] = link_color; + colors[ThemeService::COLOR_NTP_LINK_UNDERLINE] = underline_color; + colors[ThemeService::COLOR_NTP_SECTION_LINK] = link_color; + colors[ThemeService::COLOR_NTP_SECTION_LINK_UNDERLINE] = underline_color; VerifyColorMap(colors); @@ -244,8 +244,8 @@ TEST_F(BrowserThemePackTest, UseSectionColorAsNTPHeader) { std::map<int, SkColor> colors = GetDefaultColorMap(); SkColor ntp_color = SkColorSetRGB(190, 190, 190); - colors[BrowserThemeProvider::COLOR_NTP_HEADER] = ntp_color; - colors[BrowserThemeProvider::COLOR_NTP_SECTION] = ntp_color; + colors[ThemeService::COLOR_NTP_HEADER] = ntp_color; + colors[ThemeService::COLOR_NTP_SECTION] = ntp_color; VerifyColorMap(colors); } @@ -257,8 +257,8 @@ TEST_F(BrowserThemePackTest, ProvideNtpHeaderColor) { std::map<int, SkColor> colors = GetDefaultColorMap(); SkColor ntp_header = SkColorSetRGB(120, 120, 120); SkColor ntp_section = SkColorSetRGB(190, 190, 190); - colors[BrowserThemeProvider::COLOR_NTP_HEADER] = ntp_header; - colors[BrowserThemeProvider::COLOR_NTP_SECTION] = ntp_section; + colors[ThemeService::COLOR_NTP_HEADER] = ntp_header; + colors[ThemeService::COLOR_NTP_SECTION] = ntp_section; VerifyColorMap(colors); } @@ -269,7 +269,7 @@ TEST_F(BrowserThemePackTest, CanReadTints) { color_utils::HSL expected = { 0.5, 0.5, 0.5 }; color_utils::HSL actual = { -1, -1, -1 }; EXPECT_TRUE(theme_pack_->GetTint( - BrowserThemeProvider::TINT_BUTTONS, &actual)); + ThemeService::TINT_BUTTONS, &actual)); EXPECT_DOUBLE_EQ(expected.h, actual.h); EXPECT_DOUBLE_EQ(expected.s, actual.s); EXPECT_DOUBLE_EQ(expected.l, actual.l); @@ -283,15 +283,15 @@ TEST_F(BrowserThemePackTest, CanReadDisplayProperties) { int out_val; EXPECT_TRUE(theme_pack_->GetDisplayProperty( - BrowserThemeProvider::NTP_BACKGROUND_ALIGNMENT, &out_val)); - EXPECT_EQ(BrowserThemeProvider::ALIGN_BOTTOM, out_val); + ThemeService::NTP_BACKGROUND_ALIGNMENT, &out_val)); + EXPECT_EQ(ThemeService::ALIGN_BOTTOM, out_val); EXPECT_TRUE(theme_pack_->GetDisplayProperty( - BrowserThemeProvider::NTP_BACKGROUND_TILING, &out_val)); - EXPECT_EQ(BrowserThemeProvider::REPEAT_X, out_val); + ThemeService::NTP_BACKGROUND_TILING, &out_val)); + EXPECT_EQ(ThemeService::REPEAT_X, out_val); EXPECT_TRUE(theme_pack_->GetDisplayProperty( - BrowserThemeProvider::NTP_LOGO_ALTERNATE, &out_val)); + ThemeService::NTP_LOGO_ALTERNATE, &out_val)); EXPECT_EQ(0, out_val); } @@ -335,7 +335,7 @@ TEST_F(BrowserThemePackTest, InvalidTints) { // We shouldn't have a buttons tint, as it was invalid. color_utils::HSL actual = { -1, -1, -1 }; - EXPECT_FALSE(theme_pack_->GetTint(BrowserThemeProvider::TINT_BUTTONS, + EXPECT_FALSE(theme_pack_->GetTint(ThemeService::TINT_BUTTONS, &actual)); } @@ -346,7 +346,7 @@ TEST_F(BrowserThemePackTest, InvalidDisplayProperties) { int out_val; EXPECT_FALSE(theme_pack_->GetDisplayProperty( - BrowserThemeProvider::NTP_BACKGROUND_ALIGNMENT, &out_val)); + ThemeService::NTP_BACKGROUND_ALIGNMENT, &out_val)); } // These three tests should just not cause a segmentation fault. diff --git a/chrome/browser/themes/browser_theme_provider.cc b/chrome/browser/themes/browser_theme_provider.cc deleted file mode 100644 index 3c8ee4a..0000000 --- a/chrome/browser/themes/browser_theme_provider.cc +++ /dev/null @@ -1,644 +0,0 @@ -// Copyright (c) 2011 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_provider.h" - -#include "base/string_split.h" -#include "base/string_util.h" -#include "base/utf_string_conversions.h" -#include "chrome/browser/extensions/extension_service.h" -#include "chrome/browser/metrics/user_metrics.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/themes/browser_theme_pack.h" -#include "chrome/common/chrome_constants.h" -#include "chrome/common/pref_names.h" -#include "content/common/notification_service.h" -#include "content/common/notification_type.h" -#include "grit/app_resources.h" -#include "grit/theme_resources.h" -#include "ui/base/resource/resource_bundle.h" - -#if defined(OS_WIN) -#include "views/widget/widget_win.h" -#endif - -// Strings used in alignment properties. -const char* BrowserThemeProvider::kAlignmentTop = "top"; -const char* BrowserThemeProvider::kAlignmentBottom = "bottom"; -const char* BrowserThemeProvider::kAlignmentLeft = "left"; -const char* BrowserThemeProvider::kAlignmentRight = "right"; - -// Strings used in background tiling repetition properties. -const char* BrowserThemeProvider::kTilingNoRepeat = "no-repeat"; -const char* BrowserThemeProvider::kTilingRepeatX = "repeat-x"; -const char* BrowserThemeProvider::kTilingRepeatY = "repeat-y"; -const char* BrowserThemeProvider::kTilingRepeat = "repeat"; - -// The default theme if we haven't installed a theme yet or if we've clicked -// the "Use Classic" button. -const char* BrowserThemeProvider::kDefaultThemeID = ""; - -namespace { - -// The default theme if we've gone to the theme gallery and installed the -// "Default" theme. We have to detect this case specifically. (By the time we -// realize we've installed the default theme, we already have an extension -// unpacked on the filesystem.) -const char* kDefaultThemeGalleryID = "hkacjpbfdknhflllbcmjibkdeoafencn"; - -SkColor TintForUnderline(SkColor input) { - return SkColorSetA(input, SkColorGetA(input) / 3); -} - -SkColor IncreaseLightness(SkColor color, double percent) { - color_utils::HSL result; - color_utils::SkColorToHSL(color, &result); - result.l += (1 - result.l) * percent; - return color_utils::HSLToSkColor(result, SkColorGetA(color)); -} - -// Default colors. -const SkColor kDefaultColorFrame = SkColorSetRGB(66, 116, 201); -const SkColor kDefaultColorFrameInactive = SkColorSetRGB(161, 182, 228); -const SkColor kDefaultColorFrameIncognito = SkColorSetRGB(83, 106, 139); -const SkColor kDefaultColorFrameIncognitoInactive = - SkColorSetRGB(126, 139, 156); -#if defined(OS_MACOSX) -const SkColor kDefaultColorToolbar = SkColorSetRGB(230, 230, 230); -#else -const SkColor kDefaultColorToolbar = SkColorSetRGB(223, 223, 223); -#endif -const SkColor kDefaultColorTabText = SK_ColorBLACK; -#if defined(OS_MACOSX) -const SkColor kDefaultColorBackgroundTabText = SK_ColorBLACK; -const SkColor kDefaultColorBookmarkText = SK_ColorBLACK; -#else -const SkColor kDefaultColorBackgroundTabText = SkColorSetRGB(64, 64, 64); -const SkColor kDefaultColorBookmarkText = SkColorSetRGB(18, 50, 114); -#endif -#if defined(OS_WIN) -const SkColor kDefaultColorNTPBackground = - color_utils::GetSysSkColor(COLOR_WINDOW); -const SkColor kDefaultColorNTPText = - color_utils::GetSysSkColor(COLOR_WINDOWTEXT); -const SkColor kDefaultColorNTPLink = - color_utils::GetSysSkColor(COLOR_HOTLIGHT); -#else -// TODO(beng): source from theme provider. -const SkColor kDefaultColorNTPBackground = SK_ColorWHITE; -const SkColor kDefaultColorNTPText = SK_ColorBLACK; -const SkColor kDefaultColorNTPLink = SkColorSetRGB(6, 55, 116); -#endif -const SkColor kDefaultColorNTPHeader = SkColorSetRGB(150, 150, 150); -const SkColor kDefaultColorNTPSection = SkColorSetRGB(229, 229, 229); -const SkColor kDefaultColorNTPSectionText = SK_ColorBLACK; -const SkColor kDefaultColorNTPSectionLink = SkColorSetRGB(6, 55, 116); -const SkColor kDefaultColorControlBackground = SkColorSetARGB(0, 0, 0, 0); -const SkColor kDefaultColorButtonBackground = SkColorSetARGB(0, 0, 0, 0); -#if defined(OS_MACOSX) -const SkColor kDefaultColorToolbarButtonStroke = SkColorSetARGB(75, 81, 81, 81); -const SkColor kDefaultColorToolbarButtonStrokeInactive = - SkColorSetARGB(75, 99, 99, 99); -const SkColor kDefaultColorToolbarBezel = SkColorSetRGB(247, 247, 247); -const SkColor kDefaultColorToolbarStroke = SkColorSetRGB(103, 103, 103); -const SkColor kDefaultColorToolbarStrokeInactive = SkColorSetRGB(123, 123, 123); -#endif - -// Default tints. -const color_utils::HSL kDefaultTintButtons = { -1, -1, -1 }; -const color_utils::HSL kDefaultTintFrame = { -1, -1, -1 }; -const color_utils::HSL kDefaultTintFrameInactive = { -1, -1, 0.75f }; -const color_utils::HSL kDefaultTintFrameIncognito = { -1, 0.2f, 0.35f }; -const color_utils::HSL kDefaultTintFrameIncognitoInactive = { -1, 0.3f, 0.6f }; -const color_utils::HSL kDefaultTintBackgroundTab = { -1, 0.5, 0.75 }; - -// Default display properties. -const int kDefaultDisplayPropertyNTPAlignment = - BrowserThemeProvider::ALIGN_BOTTOM; -const int kDefaultDisplayPropertyNTPTiling = - BrowserThemeProvider::NO_REPEAT; -const int kDefaultDisplayPropertyNTPInverseLogo = 0; - -// The sum of kFrameBorderThickness and kNonClientRestoredExtraThickness from -// OpaqueBrowserFrameView. -const int kRestoredTabVerticalOffset = 15; - -// The image resources we will allow people to theme. -const int kThemeableImages[] = { - IDR_THEME_FRAME, - IDR_THEME_FRAME_INACTIVE, - IDR_THEME_FRAME_INCOGNITO, - IDR_THEME_FRAME_INCOGNITO_INACTIVE, - IDR_THEME_TOOLBAR, - IDR_THEME_TAB_BACKGROUND, - IDR_THEME_TAB_BACKGROUND_INCOGNITO, - IDR_THEME_TAB_BACKGROUND_V, - IDR_THEME_NTP_BACKGROUND, - IDR_THEME_FRAME_OVERLAY, - IDR_THEME_FRAME_OVERLAY_INACTIVE, - IDR_THEME_BUTTON_BACKGROUND, - IDR_THEME_NTP_ATTRIBUTION, - IDR_THEME_WINDOW_CONTROL_BACKGROUND -}; - -bool HasThemeableImage(int themeable_image_id) { - static std::set<int> themeable_images; - if (themeable_images.empty()) { - themeable_images.insert( - kThemeableImages, kThemeableImages + arraysize(kThemeableImages)); - } - return themeable_images.count(themeable_image_id) > 0; -} - -// The image resources that will be tinted by the 'button' tint value. -// If you change this list, you must increment the version number in -// browser_theme_pack.cc, and you should assign persistent IDs to the -// data table at the start of said file or else tinted versions of -// these resources will not be created. -const int kToolbarButtonIDs[] = { - IDR_BACK, IDR_BACK_D, IDR_BACK_H, IDR_BACK_P, - IDR_FORWARD, IDR_FORWARD_D, IDR_FORWARD_H, IDR_FORWARD_P, - IDR_HOME, IDR_HOME_H, IDR_HOME_P, - IDR_RELOAD, IDR_RELOAD_H, IDR_RELOAD_P, - IDR_STOP, IDR_STOP_D, IDR_STOP_H, IDR_STOP_P, - IDR_LOCATIONBG_C, IDR_LOCATIONBG_L, IDR_LOCATIONBG_R, - IDR_BROWSER_ACTIONS_OVERFLOW, IDR_BROWSER_ACTIONS_OVERFLOW_H, - IDR_BROWSER_ACTIONS_OVERFLOW_P, - IDR_TOOLS, IDR_TOOLS_H, IDR_TOOLS_P, - IDR_MENU_DROPARROW, - IDR_THROBBER, IDR_THROBBER_WAITING, IDR_THROBBER_LIGHT, -}; - -// Writes the theme pack to disk on a separate thread. -class WritePackToDiskTask : public Task { - public: - WritePackToDiskTask(BrowserThemePack* pack, const FilePath& path) - : theme_pack_(pack), pack_path_(path) {} - - virtual void Run() { - if (!theme_pack_->WriteToDisk(pack_path_)) { - NOTREACHED() << "Could not write theme pack to disk"; - } - } - - private: - scoped_refptr<BrowserThemePack> theme_pack_; - FilePath pack_path_; -}; - -} // namespace - -bool BrowserThemeProvider::IsThemeableImage(int resource_id) { - return HasThemeableImage(resource_id); -} - -BrowserThemeProvider::BrowserThemeProvider() - : rb_(ResourceBundle::GetSharedInstance()), - profile_(NULL), - number_of_infobars_(0) { - // Initialize the themeable image map so we can use it on other threads. - HasThemeableImage(0); -} - -BrowserThemeProvider::~BrowserThemeProvider() { - FreePlatformCaches(); -} - -void BrowserThemeProvider::Init(Profile* profile) { - DCHECK(CalledOnValidThread()); - profile_ = profile; - - LoadThemePrefs(); -} - -SkBitmap* BrowserThemeProvider::GetBitmapNamed(int id) const { - DCHECK(CalledOnValidThread()); - - SkBitmap* bitmap = NULL; - - if (theme_pack_.get()) - bitmap = theme_pack_->GetBitmapNamed(id); - - if (!bitmap) - bitmap = rb_.GetBitmapNamed(id); - - return bitmap; -} - -SkColor BrowserThemeProvider::GetColor(int id) const { - DCHECK(CalledOnValidThread()); - - SkColor color; - if (theme_pack_.get() && theme_pack_->GetColor(id, &color)) - return color; - - // For backward compat with older themes, some newer colors are generated from - // older ones if they are missing. - switch (id) { - case COLOR_NTP_SECTION_HEADER_TEXT: - return IncreaseLightness(GetColor(COLOR_NTP_TEXT), 0.30); - case COLOR_NTP_SECTION_HEADER_TEXT_HOVER: - return GetColor(COLOR_NTP_TEXT); - case COLOR_NTP_SECTION_HEADER_RULE: - return IncreaseLightness(GetColor(COLOR_NTP_TEXT), 0.70); - case COLOR_NTP_SECTION_HEADER_RULE_LIGHT: - return IncreaseLightness(GetColor(COLOR_NTP_TEXT), 0.86); - case COLOR_NTP_TEXT_LIGHT: - return IncreaseLightness(GetColor(COLOR_NTP_TEXT), 0.40); - } - - return GetDefaultColor(id); -} - -bool BrowserThemeProvider::GetDisplayProperty(int id, int* result) const { - if (theme_pack_.get()) - return theme_pack_->GetDisplayProperty(id, result); - - return GetDefaultDisplayProperty(id, result); -} - -bool BrowserThemeProvider::ShouldUseNativeFrame() const { - if (HasCustomImage(IDR_THEME_FRAME)) - return false; -#if defined(OS_WIN) - return views::WidgetWin::IsAeroGlassEnabled(); -#else - return false; -#endif -} - -bool BrowserThemeProvider::HasCustomImage(int id) const { - if (!HasThemeableImage(id)) - return false; - - if (theme_pack_) - return theme_pack_->HasCustomImage(id); - - return false; -} - -RefCountedMemory* BrowserThemeProvider::GetRawData(int id) const { - // Check to see whether we should substitute some images. - int ntp_alternate; - GetDisplayProperty(NTP_LOGO_ALTERNATE, &ntp_alternate); - if (id == IDR_PRODUCT_LOGO && ntp_alternate != 0) - id = IDR_PRODUCT_LOGO_WHITE; - - RefCountedMemory* data = NULL; - if (theme_pack_.get()) - data = theme_pack_->GetRawData(id); - if (!data) - data = rb_.LoadDataResourceBytes(id); - - return data; -} - -void BrowserThemeProvider::SetTheme(const Extension* extension) { - // Clear our image cache. - FreePlatformCaches(); - - DCHECK(extension); - DCHECK(extension->is_theme()); - - BuildFromExtension(extension); - SaveThemeID(extension->id()); - - NotifyThemeChanged(extension); - UserMetrics::RecordAction(UserMetricsAction("Themes_Installed"), profile_); -} - -void BrowserThemeProvider::RemoveUnusedThemes() { - if (!profile_) - return; - ExtensionService* service = profile_->GetExtensionService(); - if (!service) - return; - std::string current_theme = GetThemeID(); - std::vector<std::string> remove_list; - const ExtensionList* extensions = service->extensions(); - for (ExtensionList::const_iterator it = extensions->begin(); - it != extensions->end(); ++it) { - if ((*it)->is_theme() && (*it)->id() != current_theme) { - remove_list.push_back((*it)->id()); - } - } - for (size_t i = 0; i < remove_list.size(); ++i) - service->UninstallExtension(remove_list[i], false); -} - -void BrowserThemeProvider::UseDefaultTheme() { - ClearAllThemeData(); - NotifyThemeChanged(NULL); - UserMetrics::RecordAction(UserMetricsAction("Themes_Reset"), profile_); -} - -void BrowserThemeProvider::SetNativeTheme() { - UseDefaultTheme(); -} - -bool BrowserThemeProvider::UsingDefaultTheme() { - std::string id = GetThemeID(); - return id == BrowserThemeProvider::kDefaultThemeID || - id == kDefaultThemeGalleryID; -} - -std::string BrowserThemeProvider::GetThemeID() const { - return profile_->GetPrefs()->GetString(prefs::kCurrentThemeID); -} - -// static -std::string BrowserThemeProvider::AlignmentToString(int alignment) { - // Convert from an AlignmentProperty back into a string. - std::string vertical_string; - std::string horizontal_string; - - if (alignment & BrowserThemeProvider::ALIGN_TOP) - vertical_string = kAlignmentTop; - else if (alignment & BrowserThemeProvider::ALIGN_BOTTOM) - vertical_string = kAlignmentBottom; - - if (alignment & BrowserThemeProvider::ALIGN_LEFT) - horizontal_string = kAlignmentLeft; - else if (alignment & BrowserThemeProvider::ALIGN_RIGHT) - horizontal_string = kAlignmentRight; - - if (vertical_string.empty()) - return horizontal_string; - if (horizontal_string.empty()) - return vertical_string; - return vertical_string + " " + horizontal_string; -} - -// static -int BrowserThemeProvider::StringToAlignment(const std::string& alignment) { - std::vector<std::wstring> split; - base::SplitStringAlongWhitespace(UTF8ToWide(alignment), &split); - - int alignment_mask = 0; - for (std::vector<std::wstring>::iterator alignments(split.begin()); - alignments != split.end(); ++alignments) { - std::string comp = WideToUTF8(*alignments); - const char* component = comp.c_str(); - - if (base::strcasecmp(component, kAlignmentTop) == 0) - alignment_mask |= BrowserThemeProvider::ALIGN_TOP; - else if (base::strcasecmp(component, kAlignmentBottom) == 0) - alignment_mask |= BrowserThemeProvider::ALIGN_BOTTOM; - - if (base::strcasecmp(component, kAlignmentLeft) == 0) - alignment_mask |= BrowserThemeProvider::ALIGN_LEFT; - else if (base::strcasecmp(component, kAlignmentRight) == 0) - alignment_mask |= BrowserThemeProvider::ALIGN_RIGHT; - } - return alignment_mask; -} - -// static -std::string BrowserThemeProvider::TilingToString(int tiling) { - // Convert from a TilingProperty back into a string. - if (tiling == BrowserThemeProvider::REPEAT_X) - return kTilingRepeatX; - if (tiling == BrowserThemeProvider::REPEAT_Y) - return kTilingRepeatY; - if (tiling == BrowserThemeProvider::REPEAT) - return kTilingRepeat; - return kTilingNoRepeat; -} - -// static -int BrowserThemeProvider::StringToTiling(const std::string& tiling) { - const char* component = tiling.c_str(); - - if (base::strcasecmp(component, kTilingRepeatX) == 0) - return BrowserThemeProvider::REPEAT_X; - if (base::strcasecmp(component, kTilingRepeatY) == 0) - return BrowserThemeProvider::REPEAT_Y; - if (base::strcasecmp(component, kTilingRepeat) == 0) - return BrowserThemeProvider::REPEAT; - // NO_REPEAT is the default choice. - return BrowserThemeProvider::NO_REPEAT; -} - -// static -color_utils::HSL BrowserThemeProvider::GetDefaultTint(int id) { - switch (id) { - case TINT_FRAME: - return kDefaultTintFrame; - case TINT_FRAME_INACTIVE: - return kDefaultTintFrameInactive; - case TINT_FRAME_INCOGNITO: - return kDefaultTintFrameIncognito; - case TINT_FRAME_INCOGNITO_INACTIVE: - return kDefaultTintFrameIncognitoInactive; - case TINT_BUTTONS: - return kDefaultTintButtons; - case TINT_BACKGROUND_TAB: - return kDefaultTintBackgroundTab; - default: - color_utils::HSL result = {-1, -1, -1}; - return result; - } -} - -// static -SkColor BrowserThemeProvider::GetDefaultColor(int id) { - switch (id) { - case COLOR_FRAME: - return kDefaultColorFrame; - case COLOR_FRAME_INACTIVE: - return kDefaultColorFrameInactive; - case COLOR_FRAME_INCOGNITO: - return kDefaultColorFrameIncognito; - case COLOR_FRAME_INCOGNITO_INACTIVE: - return kDefaultColorFrameIncognitoInactive; - case COLOR_TOOLBAR: - return kDefaultColorToolbar; - case COLOR_TAB_TEXT: - return kDefaultColorTabText; - case COLOR_BACKGROUND_TAB_TEXT: - return kDefaultColorBackgroundTabText; - case COLOR_BOOKMARK_TEXT: - return kDefaultColorBookmarkText; - case COLOR_NTP_BACKGROUND: - return kDefaultColorNTPBackground; - case COLOR_NTP_TEXT: - return kDefaultColorNTPText; - case COLOR_NTP_LINK: - return kDefaultColorNTPLink; - case COLOR_NTP_LINK_UNDERLINE: - return TintForUnderline(kDefaultColorNTPLink); - case COLOR_NTP_HEADER: - return kDefaultColorNTPHeader; - case COLOR_NTP_SECTION: - return kDefaultColorNTPSection; - case COLOR_NTP_SECTION_TEXT: - return kDefaultColorNTPSectionText; - case COLOR_NTP_SECTION_LINK: - return kDefaultColorNTPSectionLink; - case COLOR_NTP_SECTION_LINK_UNDERLINE: - return TintForUnderline(kDefaultColorNTPSectionLink); - case COLOR_CONTROL_BACKGROUND: - return kDefaultColorControlBackground; - case COLOR_BUTTON_BACKGROUND: - return kDefaultColorButtonBackground; -#if defined(OS_MACOSX) - case COLOR_TOOLBAR_BUTTON_STROKE: - return kDefaultColorToolbarButtonStroke; - case COLOR_TOOLBAR_BUTTON_STROKE_INACTIVE: - return kDefaultColorToolbarButtonStrokeInactive; - case COLOR_TOOLBAR_BEZEL: - return kDefaultColorToolbarBezel; - case COLOR_TOOLBAR_STROKE: - return kDefaultColorToolbarStroke; - case COLOR_TOOLBAR_STROKE_INACTIVE: - return kDefaultColorToolbarStrokeInactive; -#endif - default: - // Return a debugging red color. - return 0xffff0000; - } -} - -// static -bool BrowserThemeProvider::GetDefaultDisplayProperty(int id, int* result) { - switch (id) { - case NTP_BACKGROUND_ALIGNMENT: - *result = kDefaultDisplayPropertyNTPAlignment; - return true; - case NTP_BACKGROUND_TILING: - *result = kDefaultDisplayPropertyNTPTiling; - return true; - case NTP_LOGO_ALTERNATE: - *result = kDefaultDisplayPropertyNTPInverseLogo; - return true; - } - - return false; -} - -// static -const std::set<int>& BrowserThemeProvider::GetTintableToolbarButtons() { - static std::set<int> button_set; - if (button_set.empty()) { - button_set = std::set<int>( - kToolbarButtonIDs, - kToolbarButtonIDs + arraysize(kToolbarButtonIDs)); - } - - return button_set; -} - -color_utils::HSL BrowserThemeProvider::GetTint(int id) const { - DCHECK(CalledOnValidThread()); - - color_utils::HSL hsl; - if (theme_pack_.get() && theme_pack_->GetTint(id, &hsl)) - return hsl; - - return GetDefaultTint(id); -} - -void BrowserThemeProvider::ClearAllThemeData() { - // Clear our image cache. - FreePlatformCaches(); - theme_pack_ = NULL; - - profile_->GetPrefs()->ClearPref(prefs::kCurrentThemePackFilename); - SaveThemeID(kDefaultThemeID); -} - -void BrowserThemeProvider::LoadThemePrefs() { - PrefService* prefs = profile_->GetPrefs(); - - std::string current_id = GetThemeID(); - if (current_id != kDefaultThemeID) { - bool loaded_pack = false; - - // If we don't have a file pack, we're updating from an old version. - FilePath path = prefs->GetFilePath(prefs::kCurrentThemePackFilename); - if (path != FilePath()) { - theme_pack_ = BrowserThemePack::BuildFromDataPack(path, current_id); - loaded_pack = theme_pack_.get() != NULL; - } - - if (loaded_pack) { - UserMetrics::RecordAction(UserMetricsAction("Themes.Loaded"), profile_); - } else { - // TODO(erg): We need to pop up a dialog informing the user that their - // theme is being migrated. - ExtensionService* service = profile_->GetExtensionService(); - if (service) { - const Extension* extension = - service->GetExtensionById(current_id, false); - if (extension) { - DLOG(ERROR) << "Migrating theme"; - BuildFromExtension(extension); - UserMetrics::RecordAction(UserMetricsAction("Themes.Migrated"), - profile_); - } else { - DLOG(ERROR) << "Theme is mysteriously gone."; - ClearAllThemeData(); - UserMetrics::RecordAction(UserMetricsAction("Themes.Gone"), profile_); - } - } - } - } -} - -void BrowserThemeProvider::NotifyThemeChanged(const Extension* extension) { - VLOG(1) << "Sending BROWSER_THEME_CHANGED"; - // Redraw! - NotificationService* service = NotificationService::current(); - service->Notify(NotificationType::BROWSER_THEME_CHANGED, - Source<BrowserThemeProvider>(this), - Details<const Extension>(extension)); -#if defined(OS_MACOSX) - NotifyPlatformThemeChanged(); -#endif // OS_MACOSX -} - -#if defined(OS_WIN) -void BrowserThemeProvider::FreePlatformCaches() { - // Views (Skia) has no platform image cache to clear. -} -#endif - -void BrowserThemeProvider::SavePackName(const FilePath& pack_path) { - profile_->GetPrefs()->SetFilePath( - prefs::kCurrentThemePackFilename, pack_path); -} - -void BrowserThemeProvider::SaveThemeID(const std::string& id) { - profile_->GetPrefs()->SetString(prefs::kCurrentThemeID, id); -} - -void BrowserThemeProvider::BuildFromExtension(const Extension* extension) { - scoped_refptr<BrowserThemePack> pack( - BrowserThemePack::BuildFromExtension(extension)); - if (!pack.get()) { - // TODO(erg): We've failed to install the theme; perhaps we should tell the - // user? http://crbug.com/34780 - LOG(ERROR) << "Could not load theme."; - return; - } - - // Write the packed file to disk. - FilePath pack_path = extension->path().Append(chrome::kThemePackFilename); - BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, - new WritePackToDiskTask(pack, pack_path)); - - SavePackName(pack_path); - theme_pack_ = pack; -} - -void BrowserThemeProvider::OnInfobarDisplayed() { - number_of_infobars_++; -} - -void BrowserThemeProvider::OnInfobarDestroyed() { - number_of_infobars_--; - - if (number_of_infobars_ == 0) - RemoveUnusedThemes(); -} diff --git a/chrome/browser/themes/browser_theme_provider.h b/chrome/browser/themes/browser_theme_provider.h deleted file mode 100644 index 92a5c57..0000000 --- a/chrome/browser/themes/browser_theme_provider.h +++ /dev/null @@ -1,288 +0,0 @@ -// Copyright (c) 2011 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. - -#ifndef CHROME_BROWSER_THEMES_BROWSER_THEME_PROVIDER_H_ -#define CHROME_BROWSER_THEMES_BROWSER_THEME_PROVIDER_H_ -#pragma once - -#include <map> -#include <set> -#include <string> - -#include "base/ref_counted.h" -#include "base/threading/non_thread_safe.h" -#include "ui/base/theme_provider.h" - -class BrowserThemePack; -class BrowserThemeProviderTest; -class Extension; -class FilePath; -class Profile; - -namespace color_utils { -struct HSL; -} - -namespace ui { -class ResourceBundle; -} -using ui::ResourceBundle; - -#ifdef __OBJC__ -@class NSString; -// Sent whenever the browser theme changes. Object => NSValue wrapping the -// BrowserThemeProvider that changed. -extern "C" NSString* const kBrowserThemeDidChangeNotification; -#endif // __OBJC__ - -class BrowserThemeProvider : public base::NonThreadSafe, - public ui::ThemeProvider { - public: - // Public constants used in BrowserThemeProvider and its subclasses: - - // Strings used in alignment properties. - static const char* kAlignmentTop; - static const char* kAlignmentBottom; - static const char* kAlignmentLeft; - static const char* kAlignmentRight; - - // Strings used in tiling properties. - static const char* kTilingNoRepeat; - static const char* kTilingRepeatX; - static const char* kTilingRepeatY; - static const char* kTilingRepeat; - - static const char* kDefaultThemeID; - - // Returns true if the image is themeable. Safe to call on any thread. - static bool IsThemeableImage(int resource_id); - - BrowserThemeProvider(); - virtual ~BrowserThemeProvider(); - - enum { - COLOR_FRAME, - COLOR_FRAME_INACTIVE, - COLOR_FRAME_INCOGNITO, - COLOR_FRAME_INCOGNITO_INACTIVE, - COLOR_TOOLBAR, - COLOR_TAB_TEXT, - COLOR_BACKGROUND_TAB_TEXT, - COLOR_BOOKMARK_TEXT, - COLOR_NTP_BACKGROUND, - COLOR_NTP_TEXT, - COLOR_NTP_LINK, - COLOR_NTP_LINK_UNDERLINE, - COLOR_NTP_HEADER, - COLOR_NTP_SECTION, - COLOR_NTP_SECTION_TEXT, - COLOR_NTP_SECTION_LINK, - COLOR_NTP_SECTION_LINK_UNDERLINE, - COLOR_CONTROL_BACKGROUND, - COLOR_BUTTON_BACKGROUND, - - // These colors don't have constant default values. They are derived from - // the runtime value of other colors. - COLOR_NTP_SECTION_HEADER_TEXT, - COLOR_NTP_SECTION_HEADER_TEXT_HOVER, - COLOR_NTP_SECTION_HEADER_RULE, - COLOR_NTP_SECTION_HEADER_RULE_LIGHT, - COLOR_NTP_TEXT_LIGHT, - - TINT_BUTTONS, - TINT_FRAME, - TINT_FRAME_INACTIVE, - TINT_FRAME_INCOGNITO, - TINT_FRAME_INCOGNITO_INACTIVE, - TINT_BACKGROUND_TAB, - NTP_BACKGROUND_ALIGNMENT, - NTP_BACKGROUND_TILING, - NTP_LOGO_ALTERNATE -#if defined(OS_MACOSX) - , - COLOR_TOOLBAR_BEZEL = 1000, - COLOR_TOOLBAR_STROKE, - COLOR_TOOLBAR_STROKE_INACTIVE, - COLOR_TOOLBAR_BUTTON_STROKE, - COLOR_TOOLBAR_BUTTON_STROKE_INACTIVE, - GRADIENT_FRAME_INCOGNITO, - GRADIENT_FRAME_INCOGNITO_INACTIVE, - GRADIENT_TOOLBAR, - GRADIENT_TOOLBAR_INACTIVE, - GRADIENT_TOOLBAR_BUTTON, - GRADIENT_TOOLBAR_BUTTON_INACTIVE, - GRADIENT_TOOLBAR_BUTTON_PRESSED, - GRADIENT_TOOLBAR_BUTTON_PRESSED_INACTIVE -#endif // OS_MACOSX - }; - - // A bitfield mask for alignments. - typedef enum { - ALIGN_CENTER = 0x0, - ALIGN_LEFT = 0x1, - ALIGN_TOP = 0x2, - ALIGN_RIGHT = 0x4, - ALIGN_BOTTOM = 0x8, - } AlignmentMasks; - - // Background tiling choices. - typedef enum { - NO_REPEAT = 0, - REPEAT_X = 1, - REPEAT_Y = 2, - REPEAT = 3 - } Tiling; - - // ui::ThemeProvider implementation. - virtual void Init(Profile* profile); - virtual SkBitmap* GetBitmapNamed(int id) const; - virtual SkColor GetColor(int id) const; - virtual bool GetDisplayProperty(int id, int* result) const; - virtual bool ShouldUseNativeFrame() const; - virtual bool HasCustomImage(int id) const; - virtual RefCountedMemory* GetRawData(int id) const; -#if defined(TOOLKIT_USES_GTK) - // GdkPixbufs returned by GetPixbufNamed and GetRTLEnabledPixbufNamed are - // shared instances owned by the theme provider and should not be freed. - virtual GdkPixbuf* GetPixbufNamed(int id) const; - virtual GdkPixbuf* GetRTLEnabledPixbufNamed(int id) const; -#elif defined(OS_MACOSX) - virtual NSImage* GetNSImageNamed(int id, bool allow_default) const; - virtual NSColor* GetNSImageColorNamed(int id, bool allow_default) const; - virtual NSColor* GetNSColor(int id, bool allow_default) const; - virtual NSColor* GetNSColorTint(int id, bool allow_default) const; - virtual NSGradient* GetNSGradient(int id) const; -#endif - - // Set the current theme to the theme defined in |extension|. - virtual void SetTheme(const Extension* extension); - - // Reset the theme to default. - virtual void UseDefaultTheme(); - - // Set the current theme to the native theme. On some platforms, the native - // theme is the default theme. - virtual void SetNativeTheme(); - - // Whether we're using the chrome default theme. Virtual so linux can check - // if we're using the GTK theme. - virtual bool UsingDefaultTheme(); - - // Gets the id of the last installed theme. (The theme may have been further - // locally customized.) - virtual std::string GetThemeID() const; - - // This class needs to keep track of the number of theme infobars so that we - // clean up unused themes. - void OnInfobarDisplayed(); - - // Decrements the number of theme infobars. If the last infobar has been - // destroyed, uninstalls all themes that aren't the currently selected. - void OnInfobarDestroyed(); - - // Convert a bitfield alignment into a string like "top left". Public so that - // it can be used to generate CSS values. Takes a bitfield of AlignmentMasks. - static std::string AlignmentToString(int alignment); - - // Parse alignments from something like "top left" into a bitfield of - // AlignmentMasks - static int StringToAlignment(const std::string& alignment); - - // Convert a tiling value into a string like "no-repeat". Public - // so that it can be used to generate CSS values. Takes a Tiling. - static std::string TilingToString(int tiling); - - // Parse tiling values from something like "no-repeat" into a Tiling value. - static int StringToTiling(const std::string& tiling); - - // Returns the default tint for the given tint |id| TINT_* enum value. - static color_utils::HSL GetDefaultTint(int id); - - // Returns the default color for the given color |id| COLOR_* enum value. - static SkColor GetDefaultColor(int id); - - // Returns true and sets |result| to the requested default property, if |id| - // is valid. - static bool GetDefaultDisplayProperty(int id, int* result); - - // Returns the set of IDR_* resources that should be tinted. - static const std::set<int>& GetTintableToolbarButtons(); - - // Remove preference values for themes that are no longer in use. - void RemoveUnusedThemes(); - - // Save the images to be written to disk, mapping file path to id. - typedef std::map<FilePath, int> ImagesDiskCache; - - protected: - // Get the specified tint - |id| is one of the TINT_* enum values. - color_utils::HSL GetTint(int id) const; - - // Clears all the override fields and saves the dictionary. - virtual void ClearAllThemeData(); - - // Load theme data from preferences. - virtual void LoadThemePrefs(); - - // Let all the browser views know that themes have changed. - // extension is NULL iff the theme is being set to the - // default/system theme. - virtual void NotifyThemeChanged(const Extension* extension); - -#if defined(OS_MACOSX) - // Let all the browser views know that themes have changed in a platform way. - virtual void NotifyPlatformThemeChanged(); -#endif // OS_MACOSX - - // Clears the platform-specific caches. Do not call directly; it's called - // from ClearCaches(). - virtual void FreePlatformCaches(); - - Profile* profile() { return profile_; } - - private: - friend class BrowserThemeProviderTest; - - // Saves the filename of the cached theme pack. - void SavePackName(const FilePath& pack_path); - - // Save the id of the last theme installed. - void SaveThemeID(const std::string& id); - - // Implementation of SetTheme() (and the fallback from LoadThemePrefs() in - // case we don't have a theme pack). - void BuildFromExtension(const Extension* extension); - -#if defined(TOOLKIT_USES_GTK) - // Loads an image and flips it horizontally if |rtl_enabled| is true. - GdkPixbuf* GetPixbufImpl(int id, bool rtl_enabled) const; -#endif - -#if defined(TOOLKIT_USES_GTK) - typedef std::map<int, GdkPixbuf*> GdkPixbufMap; - mutable GdkPixbufMap gdk_pixbufs_; -#elif defined(OS_MACOSX) - typedef std::map<int, NSImage*> NSImageMap; - mutable NSImageMap nsimage_cache_; - - // The bool member of the pair is whether the color is a default color. - typedef std::map<int, std::pair<NSColor*, bool> > NSColorMap; - mutable NSColorMap nscolor_cache_; - - typedef std::map<int, NSGradient*> NSGradientMap; - mutable NSGradientMap nsgradient_cache_; -#endif - - ResourceBundle& rb_; - Profile* profile_; - - scoped_refptr<BrowserThemePack> theme_pack_; - - // The number of infobars currently displayed. - int number_of_infobars_; - - DISALLOW_COPY_AND_ASSIGN(BrowserThemeProvider); -}; - -#endif // CHROME_BROWSER_THEMES_BROWSER_THEME_PROVIDER_H_ diff --git a/chrome/browser/themes/browser_theme_provider_unittest.cc b/chrome/browser/themes/browser_theme_provider_unittest.cc deleted file mode 100644 index c99a946..0000000 --- a/chrome/browser/themes/browser_theme_provider_unittest.cc +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2009 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_provider.h" - -#include "testing/gtest/include/gtest/gtest.h" -#include "base/json/json_reader.h" - -TEST(BrowserThemeProviderTest, AlignmentConversion) { - // Verify that we get out what we put in. - std::string top_left = "top left"; - int alignment = BrowserThemeProvider::StringToAlignment(top_left); - EXPECT_EQ(BrowserThemeProvider::ALIGN_TOP | BrowserThemeProvider::ALIGN_LEFT, - alignment); - EXPECT_EQ(top_left, BrowserThemeProvider::AlignmentToString(alignment)); - - alignment = BrowserThemeProvider::StringToAlignment("top"); - EXPECT_EQ(BrowserThemeProvider::ALIGN_TOP, alignment); - EXPECT_EQ("top", BrowserThemeProvider::AlignmentToString(alignment)); - - alignment = BrowserThemeProvider::StringToAlignment("left"); - EXPECT_EQ(BrowserThemeProvider::ALIGN_LEFT, alignment); - EXPECT_EQ("left", BrowserThemeProvider::AlignmentToString(alignment)); - - alignment = BrowserThemeProvider::StringToAlignment("right"); - EXPECT_EQ(BrowserThemeProvider::ALIGN_RIGHT, alignment); - EXPECT_EQ("right", BrowserThemeProvider::AlignmentToString(alignment)); - - alignment = BrowserThemeProvider::StringToAlignment("righttopbottom"); - EXPECT_EQ(BrowserThemeProvider::ALIGN_CENTER, alignment); - EXPECT_EQ("", BrowserThemeProvider::AlignmentToString(alignment)); -} - -TEST(BrowserThemeProviderTest, AlignmentConversionInput) { - // Verify that we output in an expected format. - int alignment = BrowserThemeProvider::StringToAlignment("right bottom"); - EXPECT_EQ("bottom right", BrowserThemeProvider::AlignmentToString(alignment)); - - // Verify that bad strings don't cause explosions. - alignment = BrowserThemeProvider::StringToAlignment("new zealand"); - EXPECT_EQ("", BrowserThemeProvider::AlignmentToString(alignment)); - - // Verify that bad strings don't cause explosions. - alignment = BrowserThemeProvider::StringToAlignment("new zealand top"); - EXPECT_EQ("top", BrowserThemeProvider::AlignmentToString(alignment)); - - // Verify that bad strings don't cause explosions. - alignment = BrowserThemeProvider::StringToAlignment("new zealandtop"); - EXPECT_EQ("", BrowserThemeProvider::AlignmentToString(alignment)); -} diff --git a/chrome/browser/themes/theme_service.cc b/chrome/browser/themes/theme_service.cc index eae2b76..1731b47 100644 --- a/chrome/browser/themes/theme_service.cc +++ b/chrome/browser/themes/theme_service.cc @@ -4,106 +4,641 @@ #include "chrome/browser/themes/theme_service.h" -#include "base/logging.h" +#include "base/string_split.h" +#include "base/string_util.h" +#include "base/utf_string_conversions.h" #include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/profiles/profile.h" -#include "chrome/browser/themes/browser_theme_provider.h" +#include "chrome/browser/themes/browser_theme_pack.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/pref_names.h" #include "content/common/notification_service.h" +#include "content/common/notification_type.h" +#include "grit/app_resources.h" +#include "grit/theme_resources.h" +#include "ui/base/resource/resource_bundle.h" -#if defined(TOOLKIT_USES_GTK) -#include "chrome/browser/ui/gtk/gtk_theme_provider.h" +#if defined(OS_WIN) +#include "views/widget/widget_win.h" #endif -// static -BrowserThemeProvider* ThemeServiceFactory::GetForProfile(Profile* top_profile) { - // We may be asked for the Theme of an incognito profile. Make sure we're - // operating on the real profile. - Profile* profile = top_profile->GetOriginalProfile(); +// Strings used in alignment properties. +const char* ThemeService::kAlignmentTop = "top"; +const char* ThemeService::kAlignmentBottom = "bottom"; +const char* ThemeService::kAlignmentLeft = "left"; +const char* ThemeService::kAlignmentRight = "right"; + +// Strings used in background tiling repetition properties. +const char* ThemeService::kTilingNoRepeat = "no-repeat"; +const char* ThemeService::kTilingRepeatX = "repeat-x"; +const char* ThemeService::kTilingRepeatY = "repeat-y"; +const char* ThemeService::kTilingRepeat = "repeat"; + +// The default theme if we haven't installed a theme yet or if we've clicked +// the "Use Classic" button. +const char* ThemeService::kDefaultThemeID = ""; + +namespace { - ThemeServiceFactory* service = GetInstance(); +// The default theme if we've gone to the theme gallery and installed the +// "Default" theme. We have to detect this case specifically. (By the time we +// realize we've installed the default theme, we already have an extension +// unpacked on the filesystem.) +const char* kDefaultThemeGalleryID = "hkacjpbfdknhflllbcmjibkdeoafencn"; - std::map<Profile*, BrowserThemeProvider*>::const_iterator it = - service->mapping_.find(profile); - if (it != service->mapping_.end()) - return it->second; +SkColor TintForUnderline(SkColor input) { + return SkColorSetA(input, SkColorGetA(input) / 3); +} + +SkColor IncreaseLightness(SkColor color, double percent) { + color_utils::HSL result; + color_utils::SkColorToHSL(color, &result); + result.l += (1 - result.l) * percent; + return color_utils::HSLToSkColor(result, SkColorGetA(color)); +} - BrowserThemeProvider* provider = NULL; -#if defined(TOOLKIT_USES_GTK) - provider = new GtkThemeProvider; +// Default colors. +const SkColor kDefaultColorFrame = SkColorSetRGB(66, 116, 201); +const SkColor kDefaultColorFrameInactive = SkColorSetRGB(161, 182, 228); +const SkColor kDefaultColorFrameIncognito = SkColorSetRGB(83, 106, 139); +const SkColor kDefaultColorFrameIncognitoInactive = + SkColorSetRGB(126, 139, 156); +#if defined(OS_MACOSX) +const SkColor kDefaultColorToolbar = SkColorSetRGB(230, 230, 230); +#else +const SkColor kDefaultColorToolbar = SkColorSetRGB(223, 223, 223); +#endif +const SkColor kDefaultColorTabText = SK_ColorBLACK; +#if defined(OS_MACOSX) +const SkColor kDefaultColorBackgroundTabText = SK_ColorBLACK; +const SkColor kDefaultColorBookmarkText = SK_ColorBLACK; +#else +const SkColor kDefaultColorBackgroundTabText = SkColorSetRGB(64, 64, 64); +const SkColor kDefaultColorBookmarkText = SkColorSetRGB(18, 50, 114); +#endif +#if defined(OS_WIN) +const SkColor kDefaultColorNTPBackground = + color_utils::GetSysSkColor(COLOR_WINDOW); +const SkColor kDefaultColorNTPText = + color_utils::GetSysSkColor(COLOR_WINDOWTEXT); +const SkColor kDefaultColorNTPLink = + color_utils::GetSysSkColor(COLOR_HOTLIGHT); #else - provider = new BrowserThemeProvider; +// TODO(beng): source from theme provider. +const SkColor kDefaultColorNTPBackground = SK_ColorWHITE; +const SkColor kDefaultColorNTPText = SK_ColorBLACK; +const SkColor kDefaultColorNTPLink = SkColorSetRGB(6, 55, 116); +#endif +const SkColor kDefaultColorNTPHeader = SkColorSetRGB(150, 150, 150); +const SkColor kDefaultColorNTPSection = SkColorSetRGB(229, 229, 229); +const SkColor kDefaultColorNTPSectionText = SK_ColorBLACK; +const SkColor kDefaultColorNTPSectionLink = SkColorSetRGB(6, 55, 116); +const SkColor kDefaultColorControlBackground = SkColorSetARGB(0, 0, 0, 0); +const SkColor kDefaultColorButtonBackground = SkColorSetARGB(0, 0, 0, 0); +#if defined(OS_MACOSX) +const SkColor kDefaultColorToolbarButtonStroke = SkColorSetARGB(75, 81, 81, 81); +const SkColor kDefaultColorToolbarButtonStrokeInactive = + SkColorSetARGB(75, 99, 99, 99); +const SkColor kDefaultColorToolbarBezel = SkColorSetRGB(247, 247, 247); +const SkColor kDefaultColorToolbarStroke = SkColorSetRGB(103, 103, 103); +const SkColor kDefaultColorToolbarStrokeInactive = SkColorSetRGB(123, 123, 123); #endif - provider->Init(profile); - service->Associate(profile, provider); - return provider; +// Default tints. +const color_utils::HSL kDefaultTintButtons = { -1, -1, -1 }; +const color_utils::HSL kDefaultTintFrame = { -1, -1, -1 }; +const color_utils::HSL kDefaultTintFrameInactive = { -1, -1, 0.75f }; +const color_utils::HSL kDefaultTintFrameIncognito = { -1, 0.2f, 0.35f }; +const color_utils::HSL kDefaultTintFrameIncognitoInactive = { -1, 0.3f, 0.6f }; +const color_utils::HSL kDefaultTintBackgroundTab = { -1, 0.5, 0.75 }; + +// Default display properties. +const int kDefaultDisplayPropertyNTPAlignment = + ThemeService::ALIGN_BOTTOM; +const int kDefaultDisplayPropertyNTPTiling = + ThemeService::NO_REPEAT; +const int kDefaultDisplayPropertyNTPInverseLogo = 0; + +// The sum of kFrameBorderThickness and kNonClientRestoredExtraThickness from +// OpaqueBrowserFrameView. +const int kRestoredTabVerticalOffset = 15; + +// The image resources we will allow people to theme. +const int kThemeableImages[] = { + IDR_THEME_FRAME, + IDR_THEME_FRAME_INACTIVE, + IDR_THEME_FRAME_INCOGNITO, + IDR_THEME_FRAME_INCOGNITO_INACTIVE, + IDR_THEME_TOOLBAR, + IDR_THEME_TAB_BACKGROUND, + IDR_THEME_TAB_BACKGROUND_INCOGNITO, + IDR_THEME_TAB_BACKGROUND_V, + IDR_THEME_NTP_BACKGROUND, + IDR_THEME_FRAME_OVERLAY, + IDR_THEME_FRAME_OVERLAY_INACTIVE, + IDR_THEME_BUTTON_BACKGROUND, + IDR_THEME_NTP_ATTRIBUTION, + IDR_THEME_WINDOW_CONTROL_BACKGROUND +}; + +bool HasThemeableImage(int themeable_image_id) { + static std::set<int> themeable_images; + if (themeable_images.empty()) { + themeable_images.insert( + kThemeableImages, kThemeableImages + arraysize(kThemeableImages)); + } + return themeable_images.count(themeable_image_id) > 0; +} + +// The image resources that will be tinted by the 'button' tint value. +// If you change this list, you must increment the version number in +// browser_theme_pack.cc, and you should assign persistent IDs to the +// data table at the start of said file or else tinted versions of +// these resources will not be created. +const int kToolbarButtonIDs[] = { + IDR_BACK, IDR_BACK_D, IDR_BACK_H, IDR_BACK_P, + IDR_FORWARD, IDR_FORWARD_D, IDR_FORWARD_H, IDR_FORWARD_P, + IDR_HOME, IDR_HOME_H, IDR_HOME_P, + IDR_RELOAD, IDR_RELOAD_H, IDR_RELOAD_P, + IDR_STOP, IDR_STOP_D, IDR_STOP_H, IDR_STOP_P, + IDR_LOCATIONBG_C, IDR_LOCATIONBG_L, IDR_LOCATIONBG_R, + IDR_BROWSER_ACTIONS_OVERFLOW, IDR_BROWSER_ACTIONS_OVERFLOW_H, + IDR_BROWSER_ACTIONS_OVERFLOW_P, + IDR_TOOLS, IDR_TOOLS_H, IDR_TOOLS_P, + IDR_MENU_DROPARROW, + IDR_THROBBER, IDR_THROBBER_WAITING, IDR_THROBBER_LIGHT, +}; + +// Writes the theme pack to disk on a separate thread. +class WritePackToDiskTask : public Task { + public: + WritePackToDiskTask(BrowserThemePack* pack, const FilePath& path) + : theme_pack_(pack), pack_path_(path) {} + + virtual void Run() { + if (!theme_pack_->WriteToDisk(pack_path_)) { + NOTREACHED() << "Could not write theme pack to disk"; + } + } + + private: + scoped_refptr<BrowserThemePack> theme_pack_; + FilePath pack_path_; +}; + +} // namespace + +bool ThemeService::IsThemeableImage(int resource_id) { + return HasThemeableImage(resource_id); +} + +ThemeService::ThemeService() + : rb_(ResourceBundle::GetSharedInstance()), + profile_(NULL), + number_of_infobars_(0) { + // Initialize the themeable image map so we can use it on other threads. + HasThemeableImage(0); +} + +ThemeService::~ThemeService() { + FreePlatformCaches(); +} + +void ThemeService::Init(Profile* profile) { + DCHECK(CalledOnValidThread()); + profile_ = profile; + + LoadThemePrefs(); } -const Extension* ThemeServiceFactory::GetThemeForProfile(Profile* profile) { - std::string id = GetForProfile(profile)->GetThemeID(); - if (id == BrowserThemeProvider::kDefaultThemeID) - return NULL; +SkBitmap* ThemeService::GetBitmapNamed(int id) const { + DCHECK(CalledOnValidThread()); - return profile->GetExtensionService()->GetExtensionById(id, false); + SkBitmap* bitmap = NULL; + + if (theme_pack_.get()) + bitmap = theme_pack_->GetBitmapNamed(id); + + if (!bitmap) + bitmap = rb_.GetBitmapNamed(id); + + return bitmap; +} + +SkColor ThemeService::GetColor(int id) const { + DCHECK(CalledOnValidThread()); + + SkColor color; + if (theme_pack_.get() && theme_pack_->GetColor(id, &color)) + return color; + + // For backward compat with older themes, some newer colors are generated from + // older ones if they are missing. + switch (id) { + case COLOR_NTP_SECTION_HEADER_TEXT: + return IncreaseLightness(GetColor(COLOR_NTP_TEXT), 0.30); + case COLOR_NTP_SECTION_HEADER_TEXT_HOVER: + return GetColor(COLOR_NTP_TEXT); + case COLOR_NTP_SECTION_HEADER_RULE: + return IncreaseLightness(GetColor(COLOR_NTP_TEXT), 0.70); + case COLOR_NTP_SECTION_HEADER_RULE_LIGHT: + return IncreaseLightness(GetColor(COLOR_NTP_TEXT), 0.86); + case COLOR_NTP_TEXT_LIGHT: + return IncreaseLightness(GetColor(COLOR_NTP_TEXT), 0.40); + } + + return GetDefaultColor(id); } -void ThemeServiceFactory::ForceAssociationBetween(Profile* top_profile, - BrowserThemeProvider* provider) { - ThemeServiceFactory* service = GetInstance(); - Profile* profile = top_profile->GetOriginalProfile(); +bool ThemeService::GetDisplayProperty(int id, int* result) const { + if (theme_pack_.get()) + return theme_pack_->GetDisplayProperty(id, result); - service->Associate(profile, provider); + return GetDefaultDisplayProperty(id, result); } -ThemeServiceFactory* ThemeServiceFactory::GetInstance() { - return Singleton<ThemeServiceFactory>::get(); +bool ThemeService::ShouldUseNativeFrame() const { + if (HasCustomImage(IDR_THEME_FRAME)) + return false; +#if defined(OS_WIN) + return views::WidgetWin::IsAeroGlassEnabled(); +#else + return false; +#endif } -ThemeServiceFactory::ThemeServiceFactory() {} +bool ThemeService::HasCustomImage(int id) const { + if (!HasThemeableImage(id)) + return false; + + if (theme_pack_) + return theme_pack_->HasCustomImage(id); -ThemeServiceFactory::~ThemeServiceFactory() { - DCHECK(mapping_.empty()); + return false; } -void ThemeServiceFactory::Associate(Profile* profile, - BrowserThemeProvider* provider) { - DCHECK(mapping_.find(profile) == mapping_.end()); - mapping_.insert(std::make_pair(profile, provider)); +RefCountedMemory* ThemeService::GetRawData(int id) const { + // Check to see whether we should substitute some images. + int ntp_alternate; + GetDisplayProperty(NTP_LOGO_ALTERNATE, &ntp_alternate); + if (id == IDR_PRODUCT_LOGO && ntp_alternate != 0) + id = IDR_PRODUCT_LOGO_WHITE; - registrar_.Add(this, - NotificationType::PROFILE_DESTROYED, - Source<Profile>(profile)); - registrar_.Add(this, - NotificationType::THEME_INSTALLED, - Source<Profile>(profile)); + RefCountedMemory* data = NULL; + if (theme_pack_.get()) + data = theme_pack_->GetRawData(id); + if (!data) + data = rb_.LoadDataResourceBytes(id); + + return data; } -void ThemeServiceFactory::Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - std::map<Profile*, BrowserThemeProvider*>::iterator it = - mapping_.find(Source<Profile>(source).ptr()); - DCHECK(it != mapping_.end()); +void ThemeService::SetTheme(const Extension* extension) { + // Clear our image cache. + FreePlatformCaches(); + + DCHECK(extension); + DCHECK(extension->is_theme()); - if (NotificationType::PROFILE_DESTROYED == type) { - delete it->second; - mapping_.erase(it); + BuildFromExtension(extension); + SaveThemeID(extension->id()); + + NotifyThemeChanged(extension); + UserMetrics::RecordAction(UserMetricsAction("Themes_Installed"), profile_); +} - // Remove ourselves from listening to all notifications because the source - // profile has been deleted. We have to do this because several unit tests - // are set up so a Profile is on the same place on the stack multiple - // times, so while they are different instances, they have the same - // addresses. - registrar_.Remove(this, - NotificationType::PROFILE_DESTROYED, - source); - registrar_.Remove(this, - NotificationType::THEME_INSTALLED, - source); - } else if (NotificationType::THEME_INSTALLED == type) { - const Extension* extension = Details<const Extension>(details).ptr(); - it->second->SetTheme(extension); - } else { - NOTREACHED(); +void ThemeService::RemoveUnusedThemes() { + if (!profile_) + return; + ExtensionService* service = profile_->GetExtensionService(); + if (!service) + return; + std::string current_theme = GetThemeID(); + std::vector<std::string> remove_list; + const ExtensionList* extensions = service->extensions(); + for (ExtensionList::const_iterator it = extensions->begin(); + it != extensions->end(); ++it) { + if ((*it)->is_theme() && (*it)->id() != current_theme) { + remove_list.push_back((*it)->id()); + } } + for (size_t i = 0; i < remove_list.size(); ++i) + service->UninstallExtension(remove_list[i], false); +} + +void ThemeService::UseDefaultTheme() { + ClearAllThemeData(); + NotifyThemeChanged(NULL); + UserMetrics::RecordAction(UserMetricsAction("Themes_Reset"), profile_); +} + +void ThemeService::SetNativeTheme() { + UseDefaultTheme(); +} + +bool ThemeService::UsingDefaultTheme() { + std::string id = GetThemeID(); + return id == ThemeService::kDefaultThemeID || + id == kDefaultThemeGalleryID; +} + +std::string ThemeService::GetThemeID() const { + return profile_->GetPrefs()->GetString(prefs::kCurrentThemeID); +} + +// static +std::string ThemeService::AlignmentToString(int alignment) { + // Convert from an AlignmentProperty back into a string. + std::string vertical_string; + std::string horizontal_string; + + if (alignment & ThemeService::ALIGN_TOP) + vertical_string = kAlignmentTop; + else if (alignment & ThemeService::ALIGN_BOTTOM) + vertical_string = kAlignmentBottom; + + if (alignment & ThemeService::ALIGN_LEFT) + horizontal_string = kAlignmentLeft; + else if (alignment & ThemeService::ALIGN_RIGHT) + horizontal_string = kAlignmentRight; + + if (vertical_string.empty()) + return horizontal_string; + if (horizontal_string.empty()) + return vertical_string; + return vertical_string + " " + horizontal_string; +} + +// static +int ThemeService::StringToAlignment(const std::string& alignment) { + std::vector<std::wstring> split; + base::SplitStringAlongWhitespace(UTF8ToWide(alignment), &split); + + int alignment_mask = 0; + for (std::vector<std::wstring>::iterator alignments(split.begin()); + alignments != split.end(); ++alignments) { + std::string comp = WideToUTF8(*alignments); + const char* component = comp.c_str(); + + if (base::strcasecmp(component, kAlignmentTop) == 0) + alignment_mask |= ThemeService::ALIGN_TOP; + else if (base::strcasecmp(component, kAlignmentBottom) == 0) + alignment_mask |= ThemeService::ALIGN_BOTTOM; + + if (base::strcasecmp(component, kAlignmentLeft) == 0) + alignment_mask |= ThemeService::ALIGN_LEFT; + else if (base::strcasecmp(component, kAlignmentRight) == 0) + alignment_mask |= ThemeService::ALIGN_RIGHT; + } + return alignment_mask; +} + +// static +std::string ThemeService::TilingToString(int tiling) { + // Convert from a TilingProperty back into a string. + if (tiling == ThemeService::REPEAT_X) + return kTilingRepeatX; + if (tiling == ThemeService::REPEAT_Y) + return kTilingRepeatY; + if (tiling == ThemeService::REPEAT) + return kTilingRepeat; + return kTilingNoRepeat; +} + +// static +int ThemeService::StringToTiling(const std::string& tiling) { + const char* component = tiling.c_str(); + + if (base::strcasecmp(component, kTilingRepeatX) == 0) + return ThemeService::REPEAT_X; + if (base::strcasecmp(component, kTilingRepeatY) == 0) + return ThemeService::REPEAT_Y; + if (base::strcasecmp(component, kTilingRepeat) == 0) + return ThemeService::REPEAT; + // NO_REPEAT is the default choice. + return ThemeService::NO_REPEAT; +} + +// static +color_utils::HSL ThemeService::GetDefaultTint(int id) { + switch (id) { + case TINT_FRAME: + return kDefaultTintFrame; + case TINT_FRAME_INACTIVE: + return kDefaultTintFrameInactive; + case TINT_FRAME_INCOGNITO: + return kDefaultTintFrameIncognito; + case TINT_FRAME_INCOGNITO_INACTIVE: + return kDefaultTintFrameIncognitoInactive; + case TINT_BUTTONS: + return kDefaultTintButtons; + case TINT_BACKGROUND_TAB: + return kDefaultTintBackgroundTab; + default: + color_utils::HSL result = {-1, -1, -1}; + return result; + } +} + +// static +SkColor ThemeService::GetDefaultColor(int id) { + switch (id) { + case COLOR_FRAME: + return kDefaultColorFrame; + case COLOR_FRAME_INACTIVE: + return kDefaultColorFrameInactive; + case COLOR_FRAME_INCOGNITO: + return kDefaultColorFrameIncognito; + case COLOR_FRAME_INCOGNITO_INACTIVE: + return kDefaultColorFrameIncognitoInactive; + case COLOR_TOOLBAR: + return kDefaultColorToolbar; + case COLOR_TAB_TEXT: + return kDefaultColorTabText; + case COLOR_BACKGROUND_TAB_TEXT: + return kDefaultColorBackgroundTabText; + case COLOR_BOOKMARK_TEXT: + return kDefaultColorBookmarkText; + case COLOR_NTP_BACKGROUND: + return kDefaultColorNTPBackground; + case COLOR_NTP_TEXT: + return kDefaultColorNTPText; + case COLOR_NTP_LINK: + return kDefaultColorNTPLink; + case COLOR_NTP_LINK_UNDERLINE: + return TintForUnderline(kDefaultColorNTPLink); + case COLOR_NTP_HEADER: + return kDefaultColorNTPHeader; + case COLOR_NTP_SECTION: + return kDefaultColorNTPSection; + case COLOR_NTP_SECTION_TEXT: + return kDefaultColorNTPSectionText; + case COLOR_NTP_SECTION_LINK: + return kDefaultColorNTPSectionLink; + case COLOR_NTP_SECTION_LINK_UNDERLINE: + return TintForUnderline(kDefaultColorNTPSectionLink); + case COLOR_CONTROL_BACKGROUND: + return kDefaultColorControlBackground; + case COLOR_BUTTON_BACKGROUND: + return kDefaultColorButtonBackground; +#if defined(OS_MACOSX) + case COLOR_TOOLBAR_BUTTON_STROKE: + return kDefaultColorToolbarButtonStroke; + case COLOR_TOOLBAR_BUTTON_STROKE_INACTIVE: + return kDefaultColorToolbarButtonStrokeInactive; + case COLOR_TOOLBAR_BEZEL: + return kDefaultColorToolbarBezel; + case COLOR_TOOLBAR_STROKE: + return kDefaultColorToolbarStroke; + case COLOR_TOOLBAR_STROKE_INACTIVE: + return kDefaultColorToolbarStrokeInactive; +#endif + default: + // Return a debugging red color. + return 0xffff0000; + } +} + +// static +bool ThemeService::GetDefaultDisplayProperty(int id, int* result) { + switch (id) { + case NTP_BACKGROUND_ALIGNMENT: + *result = kDefaultDisplayPropertyNTPAlignment; + return true; + case NTP_BACKGROUND_TILING: + *result = kDefaultDisplayPropertyNTPTiling; + return true; + case NTP_LOGO_ALTERNATE: + *result = kDefaultDisplayPropertyNTPInverseLogo; + return true; + } + + return false; +} + +// static +const std::set<int>& ThemeService::GetTintableToolbarButtons() { + static std::set<int> button_set; + if (button_set.empty()) { + button_set = std::set<int>( + kToolbarButtonIDs, + kToolbarButtonIDs + arraysize(kToolbarButtonIDs)); + } + + return button_set; +} + +color_utils::HSL ThemeService::GetTint(int id) const { + DCHECK(CalledOnValidThread()); + + color_utils::HSL hsl; + if (theme_pack_.get() && theme_pack_->GetTint(id, &hsl)) + return hsl; + + return GetDefaultTint(id); +} + +void ThemeService::ClearAllThemeData() { + // Clear our image cache. + FreePlatformCaches(); + theme_pack_ = NULL; + + profile_->GetPrefs()->ClearPref(prefs::kCurrentThemePackFilename); + SaveThemeID(kDefaultThemeID); +} + +void ThemeService::LoadThemePrefs() { + PrefService* prefs = profile_->GetPrefs(); + + std::string current_id = GetThemeID(); + if (current_id != kDefaultThemeID) { + bool loaded_pack = false; + + // If we don't have a file pack, we're updating from an old version. + FilePath path = prefs->GetFilePath(prefs::kCurrentThemePackFilename); + if (path != FilePath()) { + theme_pack_ = BrowserThemePack::BuildFromDataPack(path, current_id); + loaded_pack = theme_pack_.get() != NULL; + } + + if (loaded_pack) { + UserMetrics::RecordAction(UserMetricsAction("Themes.Loaded"), profile_); + } else { + // TODO(erg): We need to pop up a dialog informing the user that their + // theme is being migrated. + ExtensionService* service = profile_->GetExtensionService(); + if (service) { + const Extension* extension = + service->GetExtensionById(current_id, false); + if (extension) { + DLOG(ERROR) << "Migrating theme"; + BuildFromExtension(extension); + UserMetrics::RecordAction(UserMetricsAction("Themes.Migrated"), + profile_); + } else { + DLOG(ERROR) << "Theme is mysteriously gone."; + ClearAllThemeData(); + UserMetrics::RecordAction(UserMetricsAction("Themes.Gone"), profile_); + } + } + } + } +} + +void ThemeService::NotifyThemeChanged(const Extension* extension) { + VLOG(1) << "Sending BROWSER_THEME_CHANGED"; + // Redraw! + NotificationService* service = NotificationService::current(); + service->Notify(NotificationType::BROWSER_THEME_CHANGED, + Source<ThemeService>(this), + Details<const Extension>(extension)); +#if defined(OS_MACOSX) + NotifyPlatformThemeChanged(); +#endif // OS_MACOSX +} + +#if defined(OS_WIN) +void ThemeService::FreePlatformCaches() { + // Views (Skia) has no platform image cache to clear. +} +#endif + +void ThemeService::SavePackName(const FilePath& pack_path) { + profile_->GetPrefs()->SetFilePath( + prefs::kCurrentThemePackFilename, pack_path); +} + +void ThemeService::SaveThemeID(const std::string& id) { + profile_->GetPrefs()->SetString(prefs::kCurrentThemeID, id); +} + +void ThemeService::BuildFromExtension(const Extension* extension) { + scoped_refptr<BrowserThemePack> pack( + BrowserThemePack::BuildFromExtension(extension)); + if (!pack.get()) { + // TODO(erg): We've failed to install the theme; perhaps we should tell the + // user? http://crbug.com/34780 + LOG(ERROR) << "Could not load theme."; + return; + } + + // Write the packed file to disk. + FilePath pack_path = extension->path().Append(chrome::kThemePackFilename); + BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, + new WritePackToDiskTask(pack, pack_path)); + + SavePackName(pack_path); + theme_pack_ = pack; +} + +void ThemeService::OnInfobarDisplayed() { + number_of_infobars_++; +} + +void ThemeService::OnInfobarDestroyed() { + number_of_infobars_--; + + if (number_of_infobars_ == 0) + RemoveUnusedThemes(); } diff --git a/chrome/browser/themes/theme_service.h b/chrome/browser/themes/theme_service.h index 44abcc2..672bbf0 100644 --- a/chrome/browser/themes/theme_service.h +++ b/chrome/browser/themes/theme_service.h @@ -4,56 +4,285 @@ #ifndef CHROME_BROWSER_THEMES_THEME_SERVICE_H_ #define CHROME_BROWSER_THEMES_THEME_SERVICE_H_ +#pragma once #include <map> +#include <set> +#include <string> -#include "base/singleton.h" -#include "content/common/notification_observer.h" -#include "content/common/notification_registrar.h" +#include "base/ref_counted.h" +#include "base/threading/non_thread_safe.h" +#include "ui/base/theme_provider.h" -class BrowserThemeProvider; +class BrowserThemePack; +class ThemeServiceTest; class Extension; +class FilePath; class Profile; -// Singleton that owns all BrowserThemeProviders and associates them with -// Profiles. Listens for the Profile's destruction notification and cleans up -// the associated BrowserThemeProvider. -class ThemeServiceFactory : public NotificationObserver { +namespace color_utils { +struct HSL; +} + +namespace ui { +class ResourceBundle; +} +using ui::ResourceBundle; + +#ifdef __OBJC__ +@class NSString; +// Sent whenever the browser theme changes. Object => NSValue wrapping the +// ThemeService that changed. +extern "C" NSString* const kBrowserThemeDidChangeNotification; +#endif // __OBJC__ + +class ThemeService : public base::NonThreadSafe, + public ui::ThemeProvider { public: - // Returns the BrowserThemeProvider that provides theming resources for - // |profile|. Note that even if a Profile doesn't have a theme installed, it - // still needs a BrowserThemeProvider to hand back the default theme images. - static BrowserThemeProvider* GetForProfile(Profile* profile); + // Public constants used in ThemeService and its subclasses: + + // Strings used in alignment properties. + static const char* kAlignmentTop; + static const char* kAlignmentBottom; + static const char* kAlignmentLeft; + static const char* kAlignmentRight; + + // Strings used in tiling properties. + static const char* kTilingNoRepeat; + static const char* kTilingRepeatX; + static const char* kTilingRepeatY; + static const char* kTilingRepeat; + + static const char* kDefaultThemeID; + + // Returns true if the image is themeable. Safe to call on any thread. + static bool IsThemeableImage(int resource_id); + + ThemeService(); + virtual ~ThemeService(); + + enum { + COLOR_FRAME, + COLOR_FRAME_INACTIVE, + COLOR_FRAME_INCOGNITO, + COLOR_FRAME_INCOGNITO_INACTIVE, + COLOR_TOOLBAR, + COLOR_TAB_TEXT, + COLOR_BACKGROUND_TAB_TEXT, + COLOR_BOOKMARK_TEXT, + COLOR_NTP_BACKGROUND, + COLOR_NTP_TEXT, + COLOR_NTP_LINK, + COLOR_NTP_LINK_UNDERLINE, + COLOR_NTP_HEADER, + COLOR_NTP_SECTION, + COLOR_NTP_SECTION_TEXT, + COLOR_NTP_SECTION_LINK, + COLOR_NTP_SECTION_LINK_UNDERLINE, + COLOR_CONTROL_BACKGROUND, + COLOR_BUTTON_BACKGROUND, + + // These colors don't have constant default values. They are derived from + // the runtime value of other colors. + COLOR_NTP_SECTION_HEADER_TEXT, + COLOR_NTP_SECTION_HEADER_TEXT_HOVER, + COLOR_NTP_SECTION_HEADER_RULE, + COLOR_NTP_SECTION_HEADER_RULE_LIGHT, + COLOR_NTP_TEXT_LIGHT, + + TINT_BUTTONS, + TINT_FRAME, + TINT_FRAME_INACTIVE, + TINT_FRAME_INCOGNITO, + TINT_FRAME_INCOGNITO_INACTIVE, + TINT_BACKGROUND_TAB, + NTP_BACKGROUND_ALIGNMENT, + NTP_BACKGROUND_TILING, + NTP_LOGO_ALTERNATE +#if defined(OS_MACOSX) + , + COLOR_TOOLBAR_BEZEL = 1000, + COLOR_TOOLBAR_STROKE, + COLOR_TOOLBAR_STROKE_INACTIVE, + COLOR_TOOLBAR_BUTTON_STROKE, + COLOR_TOOLBAR_BUTTON_STROKE_INACTIVE, + GRADIENT_FRAME_INCOGNITO, + GRADIENT_FRAME_INCOGNITO_INACTIVE, + GRADIENT_TOOLBAR, + GRADIENT_TOOLBAR_INACTIVE, + GRADIENT_TOOLBAR_BUTTON, + GRADIENT_TOOLBAR_BUTTON_INACTIVE, + GRADIENT_TOOLBAR_BUTTON_PRESSED, + GRADIENT_TOOLBAR_BUTTON_PRESSED_INACTIVE +#endif // OS_MACOSX + }; + + // A bitfield mask for alignments. + typedef enum { + ALIGN_CENTER = 0x0, + ALIGN_LEFT = 0x1, + ALIGN_TOP = 0x2, + ALIGN_RIGHT = 0x4, + ALIGN_BOTTOM = 0x8, + } AlignmentMasks; + + // Background tiling choices. + typedef enum { + NO_REPEAT = 0, + REPEAT_X = 1, + REPEAT_Y = 2, + REPEAT = 3 + } Tiling; + + // ui::ThemeProvider implementation. + virtual void Init(Profile* profile); + virtual SkBitmap* GetBitmapNamed(int id) const; + virtual SkColor GetColor(int id) const; + virtual bool GetDisplayProperty(int id, int* result) const; + virtual bool ShouldUseNativeFrame() const; + virtual bool HasCustomImage(int id) const; + virtual RefCountedMemory* GetRawData(int id) const; +#if defined(TOOLKIT_USES_GTK) + // GdkPixbufs returned by GetPixbufNamed and GetRTLEnabledPixbufNamed are + // shared instances owned by the theme provider and should not be freed. + virtual GdkPixbuf* GetPixbufNamed(int id) const; + virtual GdkPixbuf* GetRTLEnabledPixbufNamed(int id) const; +#elif defined(OS_MACOSX) + virtual NSImage* GetNSImageNamed(int id, bool allow_default) const; + virtual NSColor* GetNSImageColorNamed(int id, bool allow_default) const; + virtual NSColor* GetNSColor(int id, bool allow_default) const; + virtual NSColor* GetNSColorTint(int id, bool allow_default) const; + virtual NSGradient* GetNSGradient(int id) const; +#endif + + // Set the current theme to the theme defined in |extension|. + virtual void SetTheme(const Extension* extension); + + // Reset the theme to default. + virtual void UseDefaultTheme(); + + // Set the current theme to the native theme. On some platforms, the native + // theme is the default theme. + virtual void SetNativeTheme(); + + // Whether we're using the chrome default theme. Virtual so linux can check + // if we're using the GTK theme. + virtual bool UsingDefaultTheme(); + + // Gets the id of the last installed theme. (The theme may have been further + // locally customized.) + virtual std::string GetThemeID() const; + + // This class needs to keep track of the number of theme infobars so that we + // clean up unused themes. + void OnInfobarDisplayed(); + + // Decrements the number of theme infobars. If the last infobar has been + // destroyed, uninstalls all themes that aren't the currently selected. + void OnInfobarDestroyed(); - // Returns the Extension that implements the theme associated with - // |profile|. Returns NULL if the theme is no longer installed, if there is - // no installed theme, or the theme was cleared. - static const Extension* GetThemeForProfile(Profile* profile); + // Convert a bitfield alignment into a string like "top left". Public so that + // it can be used to generate CSS values. Takes a bitfield of AlignmentMasks. + static std::string AlignmentToString(int alignment); - // Forces an association between |profile| and |provider|. Used in unit tests - // where we need to mock BrowserThemeProvider. - static void ForceAssociationBetween(Profile* profile, - BrowserThemeProvider* provider); + // Parse alignments from something like "top left" into a bitfield of + // AlignmentMasks + static int StringToAlignment(const std::string& alignment); - static ThemeServiceFactory* GetInstance(); + // Convert a tiling value into a string like "no-repeat". Public + // so that it can be used to generate CSS values. Takes a Tiling. + static std::string TilingToString(int tiling); + + // Parse tiling values from something like "no-repeat" into a Tiling value. + static int StringToTiling(const std::string& tiling); + + // Returns the default tint for the given tint |id| TINT_* enum value. + static color_utils::HSL GetDefaultTint(int id); + + // Returns the default color for the given color |id| COLOR_* enum value. + static SkColor GetDefaultColor(int id); + + // Returns true and sets |result| to the requested default property, if |id| + // is valid. + static bool GetDefaultDisplayProperty(int id, int* result); + + // Returns the set of IDR_* resources that should be tinted. + static const std::set<int>& GetTintableToolbarButtons(); + + // Remove preference values for themes that are no longer in use. + void RemoveUnusedThemes(); + + // Save the images to be written to disk, mapping file path to id. + typedef std::map<FilePath, int> ImagesDiskCache; + + protected: + // Get the specified tint - |id| is one of the TINT_* enum values. + color_utils::HSL GetTint(int id) const; + + // Clears all the override fields and saves the dictionary. + virtual void ClearAllThemeData(); + + // Load theme data from preferences. + virtual void LoadThemePrefs(); + + // Let all the browser views know that themes have changed. + // extension is NULL iff the theme is being set to the + // default/system theme. + virtual void NotifyThemeChanged(const Extension* extension); + +#if defined(OS_MACOSX) + // Let all the browser views know that themes have changed in a platform way. + virtual void NotifyPlatformThemeChanged(); +#endif // OS_MACOSX + + // Clears the platform-specific caches. Do not call directly; it's called + // from ClearCaches(). + virtual void FreePlatformCaches(); + + Profile* profile() { return profile_; } private: - friend struct DefaultSingletonTraits<ThemeServiceFactory>; + friend class ThemeServiceTest; + + // Saves the filename of the cached theme pack. + void SavePackName(const FilePath& pack_path); + + // Save the id of the last theme installed. + void SaveThemeID(const std::string& id); + + // Implementation of SetTheme() (and the fallback from LoadThemePrefs() in + // case we don't have a theme pack). + void BuildFromExtension(const Extension* extension); + +#if defined(TOOLKIT_USES_GTK) + // Loads an image and flips it horizontally if |rtl_enabled| is true. + GdkPixbuf* GetPixbufImpl(int id, bool rtl_enabled) const; +#endif + +#if defined(TOOLKIT_USES_GTK) + typedef std::map<int, GdkPixbuf*> GdkPixbufMap; + mutable GdkPixbufMap gdk_pixbufs_; +#elif defined(OS_MACOSX) + typedef std::map<int, NSImage*> NSImageMap; + mutable NSImageMap nsimage_cache_; + + // The bool member of the pair is whether the color is a default color. + typedef std::map<int, std::pair<NSColor*, bool> > NSColorMap; + mutable NSColorMap nscolor_cache_; + + typedef std::map<int, NSGradient*> NSGradientMap; + mutable NSGradientMap nsgradient_cache_; +#endif - ThemeServiceFactory(); - ~ThemeServiceFactory(); + ResourceBundle& rb_; + Profile* profile_; - // Maps |profile| to |provider| and listens for notifications relating to - // either. - void Associate(Profile* profile, BrowserThemeProvider* provider); + scoped_refptr<BrowserThemePack> theme_pack_; - // NotificationObserver: - virtual void Observe(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); + // The number of infobars currently displayed. + int number_of_infobars_; - NotificationRegistrar registrar_; - std::map<Profile*, BrowserThemeProvider*> mapping_; + DISALLOW_COPY_AND_ASSIGN(ThemeService); }; #endif // CHROME_BROWSER_THEMES_THEME_SERVICE_H_ diff --git a/chrome/browser/themes/theme_service_factory.cc b/chrome/browser/themes/theme_service_factory.cc new file mode 100644 index 0000000..f93b838 --- /dev/null +++ b/chrome/browser/themes/theme_service_factory.cc @@ -0,0 +1,109 @@ +// Copyright (c) 2011 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/theme_service_factory.h" + +#include "base/logging.h" +#include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/themes/theme_service.h" +#include "content/common/notification_service.h" + +#if defined(TOOLKIT_USES_GTK) +#include "chrome/browser/ui/gtk/gtk_theme_service.h" +#endif + +// static +ThemeService* ThemeServiceFactory::GetForProfile(Profile* top_profile) { + // We may be asked for the Theme of an incognito profile. Make sure we're + // operating on the real profile. + Profile* profile = top_profile->GetOriginalProfile(); + + ThemeServiceFactory* service = GetInstance(); + + std::map<Profile*, ThemeService*>::const_iterator it = + service->mapping_.find(profile); + if (it != service->mapping_.end()) + return it->second; + + ThemeService* provider = NULL; +#if defined(TOOLKIT_USES_GTK) + provider = new GtkThemeService; +#else + provider = new ThemeService; +#endif + provider->Init(profile); + + service->Associate(profile, provider); + return provider; +} + +const Extension* ThemeServiceFactory::GetThemeForProfile(Profile* profile) { + std::string id = GetForProfile(profile)->GetThemeID(); + if (id == ThemeService::kDefaultThemeID) + return NULL; + + return profile->GetExtensionService()->GetExtensionById(id, false); +} + +void ThemeServiceFactory::ForceAssociationBetween(Profile* top_profile, + ThemeService* provider) { + ThemeServiceFactory* service = GetInstance(); + Profile* profile = top_profile->GetOriginalProfile(); + + service->Associate(profile, provider); +} + +ThemeServiceFactory* ThemeServiceFactory::GetInstance() { + return Singleton<ThemeServiceFactory>::get(); +} + +ThemeServiceFactory::ThemeServiceFactory() {} + +ThemeServiceFactory::~ThemeServiceFactory() { + DCHECK(mapping_.empty()); +} + +void ThemeServiceFactory::Associate(Profile* profile, + ThemeService* provider) { + DCHECK(mapping_.find(profile) == mapping_.end()); + mapping_.insert(std::make_pair(profile, provider)); + + registrar_.Add(this, + NotificationType::PROFILE_DESTROYED, + Source<Profile>(profile)); + registrar_.Add(this, + NotificationType::THEME_INSTALLED, + Source<Profile>(profile)); +} + +void ThemeServiceFactory::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + std::map<Profile*, ThemeService*>::iterator it = + mapping_.find(Source<Profile>(source).ptr()); + DCHECK(it != mapping_.end()); + + if (NotificationType::PROFILE_DESTROYED == type) { + delete it->second; + mapping_.erase(it); + + // Remove ourselves from listening to all notifications because the source + // profile has been deleted. We have to do this because several unit tests + // are set up so a Profile is on the same place on the stack multiple + // times, so while they are different instances, they have the same + // addresses. + registrar_.Remove(this, + NotificationType::PROFILE_DESTROYED, + source); + registrar_.Remove(this, + NotificationType::THEME_INSTALLED, + source); + } else if (NotificationType::THEME_INSTALLED == type) { + const Extension* extension = Details<const Extension>(details).ptr(); + it->second->SetTheme(extension); + } else { + NOTREACHED(); + } +} diff --git a/chrome/browser/themes/theme_service_factory.h b/chrome/browser/themes/theme_service_factory.h new file mode 100644 index 0000000..8211130 --- /dev/null +++ b/chrome/browser/themes/theme_service_factory.h @@ -0,0 +1,59 @@ +// Copyright (c) 2011 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. + +#ifndef CHROME_BROWSER_THEMES_THEME_SERVICE_FACTORY_H_ +#define CHROME_BROWSER_THEMES_THEME_SERVICE_FACTORY_H_ + +#include <map> + +#include "base/singleton.h" +#include "content/common/notification_observer.h" +#include "content/common/notification_registrar.h" + +class ThemeService; +class Extension; +class Profile; + +// Singleton that owns all ThemeServices and associates them with +// Profiles. Listens for the Profile's destruction notification and cleans up +// the associated ThemeService. +class ThemeServiceFactory : public NotificationObserver { + public: + // Returns the ThemeService that provides theming resources for + // |profile|. Note that even if a Profile doesn't have a theme installed, it + // still needs a ThemeService to hand back the default theme images. + static ThemeService* GetForProfile(Profile* profile); + + // Returns the Extension that implements the theme associated with + // |profile|. Returns NULL if the theme is no longer installed, if there is + // no installed theme, or the theme was cleared. + static const Extension* GetThemeForProfile(Profile* profile); + + // Forces an association between |profile| and |provider|. Used in unit tests + // where we need to mock ThemeService. + static void ForceAssociationBetween(Profile* profile, + ThemeService* provider); + + static ThemeServiceFactory* GetInstance(); + + private: + friend struct DefaultSingletonTraits<ThemeServiceFactory>; + + ThemeServiceFactory(); + ~ThemeServiceFactory(); + + // Maps |profile| to |provider| and listens for notifications relating to + // either. + void Associate(Profile* profile, ThemeService* provider); + + // NotificationObserver: + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + NotificationRegistrar registrar_; + std::map<Profile*, ThemeService*> mapping_; +}; + +#endif // CHROME_BROWSER_THEMES_THEME_SERVICE_FACTORY_H_ diff --git a/chrome/browser/themes/browser_theme_provider_gtk.cc b/chrome/browser/themes/theme_service_gtk.cc index 52be010..e9d33bc 100644 --- a/chrome/browser/themes/browser_theme_provider_gtk.cc +++ b/chrome/browser/themes/theme_service_gtk.cc @@ -1,8 +1,8 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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_provider.h" +#include "chrome/browser/themes/theme_service.h" #include <gdk-pixbuf/gdk-pixbuf.h> @@ -11,15 +11,15 @@ #include "third_party/skia/include/core/SkBitmap.h" #include "ui/gfx/gtk_util.h" -GdkPixbuf* BrowserThemeProvider::GetPixbufNamed(int id) const { +GdkPixbuf* ThemeService::GetPixbufNamed(int id) const { return GetPixbufImpl(id, false); } -GdkPixbuf* BrowserThemeProvider::GetRTLEnabledPixbufNamed(int id) const { +GdkPixbuf* ThemeService::GetRTLEnabledPixbufNamed(int id) const { return GetPixbufImpl(id, true); } -GdkPixbuf* BrowserThemeProvider::GetPixbufImpl(int id, bool rtl_enabled) const { +GdkPixbuf* ThemeService::GetPixbufImpl(int id, bool rtl_enabled) const { DCHECK(CalledOnValidThread()); // Use the negative |resource_id| for the key for BIDI-aware images. int key = rtl_enabled ? -id : id; @@ -61,7 +61,7 @@ GdkPixbuf* BrowserThemeProvider::GetPixbufImpl(int id, bool rtl_enabled) const { return empty_bitmap; } -void BrowserThemeProvider::FreePlatformCaches() { +void ThemeService::FreePlatformCaches() { DCHECK(CalledOnValidThread()); // Free GdkPixbufs. diff --git a/chrome/browser/themes/browser_theme_provider_mac.mm b/chrome/browser/themes/theme_service_mac.mm index 887f625..30d359e 100644 --- a/chrome/browser/themes/browser_theme_provider_mac.mm +++ b/chrome/browser/themes/theme_service_mac.mm @@ -1,8 +1,8 @@ -// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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_provider.h" +#include "chrome/browser/themes/theme_service.h" #import <Cocoa/Cocoa.h> @@ -27,10 +27,9 @@ void HSLToHSB(const color_utils::HSL& hsl, CGFloat* h, CGFloat* s, CGFloat* b) { *b = SkScalarToDouble(hsv[2]); } -} +} // namespace -NSImage* BrowserThemeProvider::GetNSImageNamed(int id, - bool allow_default) const { +NSImage* ThemeService::GetNSImageNamed(int id, bool allow_default) const { DCHECK(CalledOnValidThread()); if (!allow_default && !HasCustomImage(id)) @@ -73,8 +72,7 @@ NSImage* BrowserThemeProvider::GetNSImageNamed(int id, return empty_image; } -NSColor* BrowserThemeProvider::GetNSImageColorNamed(int id, - bool allow_default) const { +NSColor* ThemeService::GetNSImageColorNamed(int id, bool allow_default) const { DCHECK(CalledOnValidThread()); // Check to see if we already have the color in the cache. @@ -99,8 +97,7 @@ NSColor* BrowserThemeProvider::GetNSImageColorNamed(int id, return image_color; } -NSColor* BrowserThemeProvider::GetNSColor(int id, - bool allow_default) const { +NSColor* ThemeService::GetNSColor(int id, bool allow_default) const { DCHECK(CalledOnValidThread()); // Check to see if we already have the color in the cache. @@ -136,8 +133,7 @@ NSColor* BrowserThemeProvider::GetNSColor(int id, return color; } -NSColor* BrowserThemeProvider::GetNSColorTint(int id, - bool allow_default) const { +NSColor* ThemeService::GetNSColorTint(int id, bool allow_default) const { DCHECK(CalledOnValidThread()); // Check to see if we already have the color in the cache. @@ -180,7 +176,7 @@ NSColor* BrowserThemeProvider::GetNSColorTint(int id, return tint_color; } -NSGradient* BrowserThemeProvider::GetNSGradient(int id) const { +NSGradient* ThemeService::GetNSGradient(int id) const { DCHECK(CalledOnValidThread()); // Check to see if we already have the gradient in the cache. @@ -285,13 +281,13 @@ NSGradient* BrowserThemeProvider::GetNSGradient(int id) const { } // Let all the browser views know that themes have changed in a platform way. -void BrowserThemeProvider::NotifyPlatformThemeChanged() { +void ThemeService::NotifyPlatformThemeChanged() { NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter]; [defaultCenter postNotificationName:kBrowserThemeDidChangeNotification object:[NSValue valueWithPointer:this]]; } -void BrowserThemeProvider::FreePlatformCaches() { +void ThemeService::FreePlatformCaches() { DCHECK(CalledOnValidThread()); // Free images. diff --git a/chrome/browser/themes/theme_service_unittest.cc b/chrome/browser/themes/theme_service_unittest.cc new file mode 100644 index 0000000..7b39c2e --- /dev/null +++ b/chrome/browser/themes/theme_service_unittest.cc @@ -0,0 +1,51 @@ +// Copyright (c) 2011 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/theme_service.h" + +#include "base/json/json_reader.h" +#include "testing/gtest/include/gtest/gtest.h" + +TEST(ThemeServiceTest, AlignmentConversion) { + // Verify that we get out what we put in. + std::string top_left = "top left"; + int alignment = ThemeService::StringToAlignment(top_left); + EXPECT_EQ(ThemeService::ALIGN_TOP | ThemeService::ALIGN_LEFT, + alignment); + EXPECT_EQ(top_left, ThemeService::AlignmentToString(alignment)); + + alignment = ThemeService::StringToAlignment("top"); + EXPECT_EQ(ThemeService::ALIGN_TOP, alignment); + EXPECT_EQ("top", ThemeService::AlignmentToString(alignment)); + + alignment = ThemeService::StringToAlignment("left"); + EXPECT_EQ(ThemeService::ALIGN_LEFT, alignment); + EXPECT_EQ("left", ThemeService::AlignmentToString(alignment)); + + alignment = ThemeService::StringToAlignment("right"); + EXPECT_EQ(ThemeService::ALIGN_RIGHT, alignment); + EXPECT_EQ("right", ThemeService::AlignmentToString(alignment)); + + alignment = ThemeService::StringToAlignment("righttopbottom"); + EXPECT_EQ(ThemeService::ALIGN_CENTER, alignment); + EXPECT_EQ("", ThemeService::AlignmentToString(alignment)); +} + +TEST(ThemeServiceTest, AlignmentConversionInput) { + // Verify that we output in an expected format. + int alignment = ThemeService::StringToAlignment("right bottom"); + EXPECT_EQ("bottom right", ThemeService::AlignmentToString(alignment)); + + // Verify that bad strings don't cause explosions. + alignment = ThemeService::StringToAlignment("new zealand"); + EXPECT_EQ("", ThemeService::AlignmentToString(alignment)); + + // Verify that bad strings don't cause explosions. + alignment = ThemeService::StringToAlignment("new zealand top"); + EXPECT_EQ("top", ThemeService::AlignmentToString(alignment)); + + // Verify that bad strings don't cause explosions. + alignment = ThemeService::StringToAlignment("new zealandtop"); + EXPECT_EQ("", ThemeService::AlignmentToString(alignment)); +} |