summaryrefslogtreecommitdiffstats
path: root/chrome/browser/themes/browser_theme_provider.cc
diff options
context:
space:
mode:
authorevan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-25 20:28:03 +0000
committerevan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-08-25 20:28:03 +0000
commitb071b6c6801bc5a0d2cdb174a200a85f201ce7c0 (patch)
tree7a6e2df9cd89f3b490a540d35118555675946b99 /chrome/browser/themes/browser_theme_provider.cc
parent5e3e622c221b530be9a9902f9060656848a2a7b0 (diff)
downloadchromium_src-b071b6c6801bc5a0d2cdb174a200a85f201ce7c0.zip
chromium_src-b071b6c6801bc5a0d2cdb174a200a85f201ce7c0.tar.gz
chromium_src-b071b6c6801bc5a0d2cdb174a200a85f201ce7c0.tar.bz2
Move theme files in chrome/browser/ into a themes/ subdir.
Rename (and resort) every #include. BUG=50548 TEST=compiles Review URL: http://codereview.chromium.org/3173043 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@57375 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/themes/browser_theme_provider.cc')
-rw-r--r--chrome/browser/themes/browser_theme_provider.cc609
1 files changed, 609 insertions, 0 deletions
diff --git a/chrome/browser/themes/browser_theme_provider.cc b/chrome/browser/themes/browser_theme_provider.cc
new file mode 100644
index 0000000..74bddfa
--- /dev/null
+++ b/chrome/browser/themes/browser_theme_provider.cc
@@ -0,0 +1,609 @@
+// Copyright (c) 2010 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 "app/resource_bundle.h"
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/extensions/extensions_service.h"
+#include "chrome/browser/metrics/user_metrics.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/themes/browser_theme_pack.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_type.h"
+#include "chrome/common/pref_names.h"
+#include "grit/app_resources.h"
+#include "grit/theme_resources.h"
+
+#if defined(OS_WIN)
+#include "app/win_util.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";
+
+// Saved default values.
+const char* BrowserThemeProvider::kDefaultThemeID = "";
+
+namespace {
+
+SkColor TintForUnderline(SkColor input) {
+ return SkColorSetA(input, SkColorGetA(input) / 3);
+}
+
+// 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(75, 140, 220);
+const SkColor kDefaultColorNTPSection = SkColorSetRGB(229, 239, 254);
+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();
+
+ RemoveUnusedThemes();
+}
+
+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;
+
+ 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 win_util::ShouldUseVistaFrame();
+#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(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;
+ ExtensionsService* service = profile_->GetExtensionsService();
+ 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_);
+}
+
+bool BrowserThemeProvider::UsingDefaultTheme() {
+ return GetThemeID() == BrowserThemeProvider::kDefaultThemeID;
+}
+
+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;
+ 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.
+ ExtensionsService* service = profile_->GetExtensionsService();
+ if (service) {
+ 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(Extension* extension) {
+ LOG(INFO) << "Sending BROWSER_THEME_CHANGED";
+ // Redraw!
+ NotificationService* service = NotificationService::current();
+ service->Notify(NotificationType::BROWSER_THEME_CHANGED,
+ Source<BrowserThemeProvider>(this),
+ Details<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(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);
+ ChromeThread::PostTask(ChromeThread::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();
+}