Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "chrome/browser/themes/theme_service.h" |
| 6 | |
| 7 | #include "base/bind.h" |
| 8 | #include "base/memory/ref_counted_memory.h" |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 9 | #include "base/prefs/pref_service.h" |
| 10 | #include "base/sequenced_task_runner.h" |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 11 | #include "base/strings/string_util.h" |
| 12 | #include "base/strings/utf_string_conversions.h" |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 13 | #include "chrome/browser/chrome_notification_types.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 14 | #include "chrome/browser/extensions/extension_service.h" |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 15 | #include "chrome/browser/extensions/extension_system.h" |
Ben Murdoch | 2385ea3 | 2013-08-06 11:01:04 +0100 | [diff] [blame] | 16 | #include "chrome/browser/managed_mode/managed_user_theme.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 17 | #include "chrome/browser/profiles/profile.h" |
| 18 | #include "chrome/browser/themes/browser_theme_pack.h" |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 19 | #include "chrome/browser/themes/custom_theme_supplier.h" |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 20 | #include "chrome/browser/themes/theme_properties.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 21 | #include "chrome/browser/themes/theme_syncable_service.h" |
| 22 | #include "chrome/common/chrome_constants.h" |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 23 | #include "chrome/common/extensions/extension_manifest_constants.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 24 | #include "chrome/common/pref_names.h" |
| 25 | #include "content/public/browser/notification_service.h" |
| 26 | #include "content/public/browser/user_metrics.h" |
| 27 | #include "grit/theme_resources.h" |
| 28 | #include "grit/ui_resources.h" |
| 29 | #include "ui/base/layout.h" |
| 30 | #include "ui/base/resource/resource_bundle.h" |
| 31 | #include "ui/gfx/image/image_skia.h" |
| 32 | |
| 33 | #if defined(OS_WIN) |
| 34 | #include "ui/base/win/shell.h" |
| 35 | #endif |
| 36 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 37 | using content::BrowserThread; |
| 38 | using content::UserMetricsAction; |
| 39 | using extensions::Extension; |
| 40 | using ui::ResourceBundle; |
| 41 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 42 | typedef ThemeProperties Properties; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 43 | |
| 44 | // The default theme if we haven't installed a theme yet or if we've clicked |
| 45 | // the "Use Classic" button. |
| 46 | const char* ThemeService::kDefaultThemeID = ""; |
| 47 | |
| 48 | namespace { |
| 49 | |
| 50 | // The default theme if we've gone to the theme gallery and installed the |
| 51 | // "Default" theme. We have to detect this case specifically. (By the time we |
| 52 | // realize we've installed the default theme, we already have an extension |
| 53 | // unpacked on the filesystem.) |
| 54 | const char* kDefaultThemeGalleryID = "hkacjpbfdknhflllbcmjibkdeoafencn"; |
| 55 | |
| 56 | SkColor TintForUnderline(SkColor input) { |
| 57 | return SkColorSetA(input, SkColorGetA(input) / 3); |
| 58 | } |
| 59 | |
| 60 | SkColor IncreaseLightness(SkColor color, double percent) { |
| 61 | color_utils::HSL result; |
| 62 | color_utils::SkColorToHSL(color, &result); |
| 63 | result.l += (1 - result.l) * percent; |
| 64 | return color_utils::HSLToSkColor(result, SkColorGetA(color)); |
| 65 | } |
| 66 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 67 | // Writes the theme pack to disk on a separate thread. |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 68 | void WritePackToDiskCallback(BrowserThemePack* pack, |
| 69 | const base::FilePath& path) { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 70 | if (!pack->WriteToDisk(path)) |
| 71 | NOTREACHED() << "Could not write theme pack to disk"; |
| 72 | } |
| 73 | |
| 74 | } // namespace |
| 75 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 76 | ThemeService::ThemeService() |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 77 | : ready_(false), |
| 78 | rb_(ResourceBundle::GetSharedInstance()), |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 79 | profile_(NULL), |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 80 | number_of_infobars_(0) { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 81 | } |
| 82 | |
| 83 | ThemeService::~ThemeService() { |
| 84 | FreePlatformCaches(); |
| 85 | } |
| 86 | |
| 87 | void ThemeService::Init(Profile* profile) { |
| 88 | DCHECK(CalledOnValidThread()); |
| 89 | profile_ = profile; |
| 90 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 91 | LoadThemePrefs(); |
| 92 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 93 | if (!ready_) { |
| 94 | registrar_.Add(this, |
| 95 | chrome::NOTIFICATION_EXTENSIONS_READY, |
| 96 | content::Source<Profile>(profile_)); |
| 97 | } |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 98 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 99 | theme_syncable_service_.reset(new ThemeSyncableService(profile_, this)); |
| 100 | } |
| 101 | |
| 102 | gfx::Image ThemeService::GetImageNamed(int id) const { |
| 103 | DCHECK(CalledOnValidThread()); |
| 104 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 105 | gfx::Image image; |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 106 | if (theme_supplier_.get()) |
| 107 | image = theme_supplier_->GetImageNamed(id); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 108 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 109 | if (image.IsEmpty()) |
| 110 | image = rb_.GetNativeImageNamed(id); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 111 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 112 | return image; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 113 | } |
| 114 | |
| 115 | gfx::ImageSkia* ThemeService::GetImageSkiaNamed(int id) const { |
| 116 | gfx::Image image = GetImageNamed(id); |
| 117 | if (image.IsEmpty()) |
| 118 | return NULL; |
| 119 | // TODO(pkotwicz): Remove this const cast. The gfx::Image interface returns |
| 120 | // its images const. GetImageSkiaNamed() also should but has many callsites. |
| 121 | return const_cast<gfx::ImageSkia*>(image.ToImageSkia()); |
| 122 | } |
| 123 | |
| 124 | SkColor ThemeService::GetColor(int id) const { |
| 125 | DCHECK(CalledOnValidThread()); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 126 | SkColor color; |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 127 | if (theme_supplier_.get() && theme_supplier_->GetColor(id, &color)) |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 128 | return color; |
| 129 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 130 | // For backward compat with older themes, some newer colors are generated from |
| 131 | // older ones if they are missing. |
| 132 | switch (id) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 133 | case Properties::COLOR_NTP_SECTION_HEADER_TEXT: |
| 134 | return IncreaseLightness(GetColor(Properties::COLOR_NTP_TEXT), 0.30); |
| 135 | case Properties::COLOR_NTP_SECTION_HEADER_TEXT_HOVER: |
| 136 | return GetColor(Properties::COLOR_NTP_TEXT); |
| 137 | case Properties::COLOR_NTP_SECTION_HEADER_RULE: |
| 138 | return IncreaseLightness(GetColor(Properties::COLOR_NTP_TEXT), 0.70); |
| 139 | case Properties::COLOR_NTP_SECTION_HEADER_RULE_LIGHT: |
| 140 | return IncreaseLightness(GetColor(Properties::COLOR_NTP_TEXT), 0.86); |
| 141 | case Properties::COLOR_NTP_TEXT_LIGHT: |
| 142 | return IncreaseLightness(GetColor(Properties::COLOR_NTP_TEXT), 0.40); |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 143 | case Properties::COLOR_MANAGED_USER_LABEL: |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 144 | return color_utils::GetReadableColor( |
| 145 | SK_ColorWHITE, |
| 146 | GetColor(Properties::COLOR_MANAGED_USER_LABEL_BACKGROUND)); |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 147 | case Properties::COLOR_MANAGED_USER_LABEL_BACKGROUND: |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 148 | return color_utils::BlendTowardOppositeLuminance( |
| 149 | GetColor(Properties::COLOR_FRAME), 0x80); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 150 | } |
| 151 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 152 | return Properties::GetDefaultColor(id); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 153 | } |
| 154 | |
| 155 | bool ThemeService::GetDisplayProperty(int id, int* result) const { |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 156 | if (theme_supplier_.get()) |
| 157 | return theme_supplier_->GetDisplayProperty(id, result); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 158 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 159 | return Properties::GetDefaultDisplayProperty(id, result); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 160 | } |
| 161 | |
| 162 | bool ThemeService::ShouldUseNativeFrame() const { |
| 163 | if (HasCustomImage(IDR_THEME_FRAME)) |
| 164 | return false; |
| 165 | #if defined(OS_WIN) |
| 166 | return ui::win::IsAeroGlassEnabled(); |
| 167 | #else |
| 168 | return false; |
| 169 | #endif |
| 170 | } |
| 171 | |
| 172 | bool ThemeService::HasCustomImage(int id) const { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 173 | if (!Properties::IsThemeableImage(id)) |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 174 | return false; |
| 175 | |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 176 | if (theme_supplier_.get()) |
| 177 | return theme_supplier_->HasCustomImage(id); |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 178 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 179 | return false; |
| 180 | } |
| 181 | |
| 182 | base::RefCountedMemory* ThemeService::GetRawData( |
| 183 | int id, |
| 184 | ui::ScaleFactor scale_factor) const { |
| 185 | // Check to see whether we should substitute some images. |
| 186 | int ntp_alternate; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 187 | GetDisplayProperty(Properties::NTP_LOGO_ALTERNATE, &ntp_alternate); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 188 | if (id == IDR_PRODUCT_LOGO && ntp_alternate != 0) |
| 189 | id = IDR_PRODUCT_LOGO_WHITE; |
| 190 | |
| 191 | base::RefCountedMemory* data = NULL; |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 192 | if (theme_supplier_.get()) |
| 193 | data = theme_supplier_->GetRawData(id, scale_factor); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 194 | if (!data) |
| 195 | data = rb_.LoadDataResourceBytesForScale(id, ui::SCALE_FACTOR_100P); |
| 196 | |
| 197 | return data; |
| 198 | } |
| 199 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 200 | void ThemeService::Observe(int type, |
| 201 | const content::NotificationSource& source, |
| 202 | const content::NotificationDetails& details) { |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 203 | DCHECK(type == chrome::NOTIFICATION_EXTENSIONS_READY); |
| 204 | registrar_.Remove(this, chrome::NOTIFICATION_EXTENSIONS_READY, |
| 205 | content::Source<Profile>(profile_)); |
| 206 | |
| 207 | MigrateTheme(); |
| 208 | set_ready(); |
| 209 | |
| 210 | // Send notification in case anyone requested data and cached it when the |
| 211 | // theme service was not ready yet. |
| 212 | NotifyThemeChanged(); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 213 | } |
| 214 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 215 | void ThemeService::SetTheme(const Extension* extension) { |
| 216 | // Clear our image cache. |
| 217 | FreePlatformCaches(); |
| 218 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 219 | DCHECK(extension); |
| 220 | DCHECK(extension->is_theme()); |
| 221 | if (DCHECK_IS_ON()) { |
| 222 | ExtensionService* service = |
| 223 | extensions::ExtensionSystem::Get(profile_)->extension_service(); |
| 224 | DCHECK(service); |
| 225 | DCHECK(service->GetExtensionById(extension->id(), false)); |
| 226 | } |
| 227 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 228 | BuildFromExtension(extension); |
| 229 | SaveThemeID(extension->id()); |
| 230 | |
| 231 | NotifyThemeChanged(); |
| 232 | content::RecordAction(UserMetricsAction("Themes_Installed")); |
| 233 | } |
| 234 | |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 235 | void ThemeService::SetCustomDefaultTheme( |
| 236 | scoped_refptr<CustomThemeSupplier> theme_supplier) { |
| 237 | ClearAllThemeData(); |
| 238 | SwapThemeSupplier(theme_supplier); |
| 239 | NotifyThemeChanged(); |
| 240 | } |
| 241 | |
| 242 | bool ThemeService::ShouldInitWithNativeTheme() const { |
| 243 | return false; |
| 244 | } |
| 245 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 246 | void ThemeService::RemoveUnusedThemes() { |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 247 | // We do not want to garbage collect themes on startup (|ready_| is false). |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 248 | // Themes will get garbage collected once |
| 249 | // ExtensionService::GarbageCollectExtensions() runs. |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 250 | if (!profile_ || !ready_) |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 251 | return; |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 252 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 253 | ExtensionService* service = profile_->GetExtensionService(); |
| 254 | if (!service) |
| 255 | return; |
| 256 | std::string current_theme = GetThemeID(); |
| 257 | std::vector<std::string> remove_list; |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 258 | const ExtensionSet* extensions = service->extensions(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 259 | for (ExtensionSet::const_iterator it = extensions->begin(); |
| 260 | it != extensions->end(); ++it) { |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 261 | if ((*it)->is_theme() && (*it)->id() != current_theme) { |
| 262 | remove_list.push_back((*it)->id()); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 263 | } |
| 264 | } |
| 265 | for (size_t i = 0; i < remove_list.size(); ++i) |
| 266 | service->UninstallExtension(remove_list[i], false, NULL); |
| 267 | } |
| 268 | |
| 269 | void ThemeService::UseDefaultTheme() { |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 270 | if (ready_) |
| 271 | content::RecordAction(UserMetricsAction("Themes_Reset")); |
| 272 | if (IsManagedUser()) { |
| 273 | SetManagedUserTheme(); |
| 274 | return; |
| 275 | } |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 276 | ClearAllThemeData(); |
| 277 | NotifyThemeChanged(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 278 | } |
| 279 | |
| 280 | void ThemeService::SetNativeTheme() { |
| 281 | UseDefaultTheme(); |
| 282 | } |
| 283 | |
| 284 | bool ThemeService::UsingDefaultTheme() const { |
| 285 | std::string id = GetThemeID(); |
| 286 | return id == ThemeService::kDefaultThemeID || |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 287 | (id == kDefaultThemeGalleryID && !IsManagedUser()); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 288 | } |
| 289 | |
| 290 | bool ThemeService::UsingNativeTheme() const { |
| 291 | return UsingDefaultTheme(); |
| 292 | } |
| 293 | |
| 294 | std::string ThemeService::GetThemeID() const { |
| 295 | return profile_->GetPrefs()->GetString(prefs::kCurrentThemeID); |
| 296 | } |
| 297 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 298 | color_utils::HSL ThemeService::GetTint(int id) const { |
| 299 | DCHECK(CalledOnValidThread()); |
| 300 | |
| 301 | color_utils::HSL hsl; |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 302 | if (theme_supplier_.get() && theme_supplier_->GetTint(id, &hsl)) |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 303 | return hsl; |
| 304 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 305 | return ThemeProperties::GetDefaultTint(id); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 306 | } |
| 307 | |
| 308 | void ThemeService::ClearAllThemeData() { |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 309 | if (!ready_) |
| 310 | return; |
| 311 | |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 312 | SwapThemeSupplier(NULL); |
| 313 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 314 | // Clear our image cache. |
| 315 | FreePlatformCaches(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 316 | |
| 317 | profile_->GetPrefs()->ClearPref(prefs::kCurrentThemePackFilename); |
| 318 | SaveThemeID(kDefaultThemeID); |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 319 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 320 | RemoveUnusedThemes(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 321 | } |
| 322 | |
| 323 | void ThemeService::LoadThemePrefs() { |
| 324 | PrefService* prefs = profile_->GetPrefs(); |
| 325 | |
| 326 | std::string current_id = GetThemeID(); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 327 | if (current_id == kDefaultThemeID) { |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 328 | // Managed users have a different default theme. |
| 329 | if (IsManagedUser()) |
| 330 | SetManagedUserTheme(); |
| 331 | else if (ShouldInitWithNativeTheme()) |
| 332 | SetNativeTheme(); |
| 333 | else |
| 334 | UseDefaultTheme(); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 335 | set_ready(); |
| 336 | return; |
| 337 | } |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 338 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 339 | bool loaded_pack = false; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 340 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 341 | // If we don't have a file pack, we're updating from an old version. |
| 342 | base::FilePath path = prefs->GetFilePath(prefs::kCurrentThemePackFilename); |
| 343 | if (path != base::FilePath()) { |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 344 | SwapThemeSupplier(BrowserThemePack::BuildFromDataPack(path, current_id)); |
| 345 | loaded_pack = theme_supplier_.get() != NULL; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 346 | } |
| 347 | |
| 348 | if (loaded_pack) { |
| 349 | content::RecordAction(UserMetricsAction("Themes.Loaded")); |
| 350 | set_ready(); |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 351 | } else { |
| 352 | // TODO(erg): We need to pop up a dialog informing the user that their |
| 353 | // theme is being migrated. |
| 354 | ExtensionService* service = |
| 355 | extensions::ExtensionSystem::Get(profile_)->extension_service(); |
| 356 | if (service && service->is_ready()) { |
| 357 | MigrateTheme(); |
| 358 | set_ready(); |
| 359 | } |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 360 | } |
| 361 | } |
| 362 | |
| 363 | void ThemeService::NotifyThemeChanged() { |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 364 | if (!ready_) |
| 365 | return; |
| 366 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 367 | DVLOG(1) << "Sending BROWSER_THEME_CHANGED"; |
| 368 | // Redraw! |
| 369 | content::NotificationService* service = |
| 370 | content::NotificationService::current(); |
| 371 | service->Notify(chrome::NOTIFICATION_BROWSER_THEME_CHANGED, |
| 372 | content::Source<ThemeService>(this), |
| 373 | content::NotificationService::NoDetails()); |
| 374 | #if defined(OS_MACOSX) |
| 375 | NotifyPlatformThemeChanged(); |
| 376 | #endif // OS_MACOSX |
| 377 | |
| 378 | // Notify sync that theme has changed. |
| 379 | if (theme_syncable_service_.get()) { |
| 380 | theme_syncable_service_->OnThemeChange(); |
| 381 | } |
| 382 | } |
| 383 | |
| 384 | #if defined(OS_WIN) || defined(USE_AURA) |
| 385 | void ThemeService::FreePlatformCaches() { |
| 386 | // Views (Skia) has no platform image cache to clear. |
| 387 | } |
| 388 | #endif |
| 389 | |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 390 | void ThemeService::SwapThemeSupplier( |
| 391 | scoped_refptr<CustomThemeSupplier> theme_supplier) { |
| 392 | if (theme_supplier_.get()) |
| 393 | theme_supplier_->StopUsingTheme(); |
| 394 | theme_supplier_ = theme_supplier; |
| 395 | if (theme_supplier_.get()) |
| 396 | theme_supplier_->StartUsingTheme(); |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 397 | } |
| 398 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 399 | void ThemeService::MigrateTheme() { |
| 400 | ExtensionService* service = |
| 401 | extensions::ExtensionSystem::Get(profile_)->extension_service(); |
| 402 | const Extension* extension = service ? |
| 403 | service->GetExtensionById(GetThemeID(), false) : NULL; |
| 404 | if (extension) { |
| 405 | DLOG(ERROR) << "Migrating theme"; |
| 406 | BuildFromExtension(extension); |
| 407 | content::RecordAction(UserMetricsAction("Themes.Migrated")); |
| 408 | } else { |
| 409 | DLOG(ERROR) << "Theme is mysteriously gone."; |
| 410 | ClearAllThemeData(); |
| 411 | content::RecordAction(UserMetricsAction("Themes.Gone")); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 412 | } |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 413 | } |
| 414 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 415 | void ThemeService::SavePackName(const base::FilePath& pack_path) { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 416 | profile_->GetPrefs()->SetFilePath( |
| 417 | prefs::kCurrentThemePackFilename, pack_path); |
| 418 | } |
| 419 | |
| 420 | void ThemeService::SaveThemeID(const std::string& id) { |
| 421 | profile_->GetPrefs()->SetString(prefs::kCurrentThemeID, id); |
| 422 | } |
| 423 | |
| 424 | void ThemeService::BuildFromExtension(const Extension* extension) { |
| 425 | scoped_refptr<BrowserThemePack> pack( |
| 426 | BrowserThemePack::BuildFromExtension(extension)); |
| 427 | if (!pack.get()) { |
| 428 | // TODO(erg): We've failed to install the theme; perhaps we should tell the |
| 429 | // user? http://crbug.com/34780 |
| 430 | LOG(ERROR) << "Could not load theme."; |
| 431 | return; |
| 432 | } |
| 433 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 434 | ExtensionService* service = |
| 435 | extensions::ExtensionSystem::Get(profile_)->extension_service(); |
| 436 | if (!service) |
| 437 | return; |
| 438 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 439 | // Write the packed file to disk. |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 440 | base::FilePath pack_path = |
| 441 | extension->path().Append(chrome::kThemePackFilename); |
| 442 | service->GetFileTaskRunner()->PostTask( |
| 443 | FROM_HERE, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 444 | base::Bind(&WritePackToDiskCallback, pack, pack_path)); |
| 445 | |
| 446 | SavePackName(pack_path); |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 447 | SwapThemeSupplier(pack); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 448 | } |
| 449 | |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 450 | bool ThemeService::IsManagedUser() const { |
Torne (Richard Coles) | a36e592 | 2013-08-05 13:57:33 +0100 | [diff] [blame] | 451 | return profile_->IsManaged(); |
Ben Murdoch | eb525c5 | 2013-07-10 11:40:50 +0100 | [diff] [blame] | 452 | } |
| 453 | |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 454 | void ThemeService::SetManagedUserTheme() { |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 455 | SetCustomDefaultTheme(new ManagedUserTheme); |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 456 | } |
| 457 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 458 | void ThemeService::OnInfobarDisplayed() { |
| 459 | number_of_infobars_++; |
| 460 | } |
| 461 | |
| 462 | void ThemeService::OnInfobarDestroyed() { |
| 463 | number_of_infobars_--; |
| 464 | |
| 465 | if (number_of_infobars_ == 0) |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 466 | RemoveUnusedThemes(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 467 | } |
| 468 | |
| 469 | ThemeSyncableService* ThemeService::GetThemeSyncableService() const { |
| 470 | return theme_syncable_service_.get(); |
| 471 | } |