OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/themes/theme_service.h" | 5 #include "chrome/browser/themes/theme_service.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/memory/ref_counted_memory.h" | 8 #include "base/memory/ref_counted_memory.h" |
| 9 #include "base/message_loop/message_loop.h" |
9 #include "base/prefs/pref_service.h" | 10 #include "base/prefs/pref_service.h" |
10 #include "base/sequenced_task_runner.h" | 11 #include "base/sequenced_task_runner.h" |
11 #include "base/strings/string_util.h" | 12 #include "base/strings/string_util.h" |
12 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
13 #include "chrome/browser/chrome_notification_types.h" | 14 #include "chrome/browser/chrome_notification_types.h" |
14 #include "chrome/browser/extensions/extension_service.h" | 15 #include "chrome/browser/extensions/extension_service.h" |
15 #include "chrome/browser/extensions/extension_system.h" | 16 #include "chrome/browser/extensions/extension_system.h" |
16 #include "chrome/browser/managed_mode/managed_user_service.h" | 17 #include "chrome/browser/managed_mode/managed_user_service.h" |
17 #include "chrome/browser/managed_mode/managed_user_service_factory.h" | 18 #include "chrome/browser/managed_mode/managed_user_service_factory.h" |
18 #include "chrome/browser/managed_mode/managed_user_theme.h" | 19 #include "chrome/browser/managed_mode/managed_user_theme.h" |
(...skipping 29 matching lines...) Expand all Loading... |
48 const char* ThemeService::kDefaultThemeID = ""; | 49 const char* ThemeService::kDefaultThemeID = ""; |
49 | 50 |
50 namespace { | 51 namespace { |
51 | 52 |
52 // The default theme if we've gone to the theme gallery and installed the | 53 // The default theme if we've gone to the theme gallery and installed the |
53 // "Default" theme. We have to detect this case specifically. (By the time we | 54 // "Default" theme. We have to detect this case specifically. (By the time we |
54 // realize we've installed the default theme, we already have an extension | 55 // realize we've installed the default theme, we already have an extension |
55 // unpacked on the filesystem.) | 56 // unpacked on the filesystem.) |
56 const char* kDefaultThemeGalleryID = "hkacjpbfdknhflllbcmjibkdeoafencn"; | 57 const char* kDefaultThemeGalleryID = "hkacjpbfdknhflllbcmjibkdeoafencn"; |
57 | 58 |
| 59 // Wait this many seconds after startup to garbage collect unused themes. |
| 60 // Removing unused themes is done after a delay because there is no |
| 61 // reason to do it at startup. |
| 62 // ExtensionService::GarbageCollectExtensions() does something similar. |
| 63 const int kRemoveUnusedThemesStartupDelay = 30; |
| 64 |
58 SkColor TintForUnderline(SkColor input) { | 65 SkColor TintForUnderline(SkColor input) { |
59 return SkColorSetA(input, SkColorGetA(input) / 3); | 66 return SkColorSetA(input, SkColorGetA(input) / 3); |
60 } | 67 } |
61 | 68 |
62 SkColor IncreaseLightness(SkColor color, double percent) { | 69 SkColor IncreaseLightness(SkColor color, double percent) { |
63 color_utils::HSL result; | 70 color_utils::HSL result; |
64 color_utils::SkColorToHSL(color, &result); | 71 color_utils::SkColorToHSL(color, &result); |
65 result.l += (1 - result.l) * percent; | 72 result.l += (1 - result.l) * percent; |
66 return color_utils::HSLToSkColor(result, SkColorGetA(color)); | 73 return color_utils::HSLToSkColor(result, SkColorGetA(color)); |
67 } | 74 } |
68 | 75 |
69 // Writes the theme pack to disk on a separate thread. | 76 // Writes the theme pack to disk on a separate thread. |
70 void WritePackToDiskCallback(BrowserThemePack* pack, | 77 void WritePackToDiskCallback(BrowserThemePack* pack, |
71 const base::FilePath& path) { | 78 const base::FilePath& path) { |
72 if (!pack->WriteToDisk(path)) | 79 if (!pack->WriteToDisk(path)) |
73 NOTREACHED() << "Could not write theme pack to disk"; | 80 NOTREACHED() << "Could not write theme pack to disk"; |
74 } | 81 } |
75 | 82 |
76 } // namespace | 83 } // namespace |
77 | 84 |
78 ThemeService::ThemeService() | 85 ThemeService::ThemeService() |
79 : ready_(false), | 86 : ready_(false), |
80 rb_(ResourceBundle::GetSharedInstance()), | 87 rb_(ResourceBundle::GetSharedInstance()), |
81 profile_(NULL), | 88 profile_(NULL), |
| 89 installed_pending_load_id_(kDefaultThemeID), |
82 number_of_infobars_(0), | 90 number_of_infobars_(0), |
83 weak_ptr_factory_(this) { | 91 weak_ptr_factory_(this) { |
84 } | 92 } |
85 | 93 |
86 ThemeService::~ThemeService() { | 94 ThemeService::~ThemeService() { |
87 FreePlatformCaches(); | 95 FreePlatformCaches(); |
88 } | 96 } |
89 | 97 |
90 void ThemeService::Init(Profile* profile) { | 98 void ThemeService::Init(Profile* profile) { |
91 DCHECK(CalledOnValidThread()); | 99 DCHECK(CalledOnValidThread()); |
92 profile_ = profile; | 100 profile_ = profile; |
93 | 101 |
94 ManagedUserServiceFactory::GetForProfile(profile)->AddInitCallback(base::Bind( | 102 ManagedUserServiceFactory::GetForProfile(profile)->AddInitCallback(base::Bind( |
95 &ThemeService::OnManagedUserInitialized, weak_ptr_factory_.GetWeakPtr())); | 103 &ThemeService::OnManagedUserInitialized, weak_ptr_factory_.GetWeakPtr())); |
96 | 104 |
97 LoadThemePrefs(); | 105 LoadThemePrefs(); |
98 | 106 |
99 if (!ready_) { | 107 registrar_.Add(this, |
100 registrar_.Add(this, | 108 chrome::NOTIFICATION_EXTENSIONS_READY, |
101 chrome::NOTIFICATION_EXTENSIONS_READY, | 109 content::Source<Profile>(profile_)); |
102 content::Source<Profile>(profile_)); | |
103 } | |
104 | 110 |
105 theme_syncable_service_.reset(new ThemeSyncableService(profile_, this)); | 111 theme_syncable_service_.reset(new ThemeSyncableService(profile_, this)); |
106 } | 112 } |
107 | 113 |
108 gfx::Image ThemeService::GetImageNamed(int id) const { | 114 gfx::Image ThemeService::GetImageNamed(int id) const { |
109 DCHECK(CalledOnValidThread()); | 115 DCHECK(CalledOnValidThread()); |
110 | 116 |
111 gfx::Image image; | 117 gfx::Image image; |
112 if (theme_supplier_.get()) | 118 if (theme_supplier_.get()) |
113 image = theme_supplier_->GetImageNamed(id); | 119 image = theme_supplier_->GetImageNamed(id); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 data = theme_supplier_->GetRawData(id, scale_factor); | 210 data = theme_supplier_->GetRawData(id, scale_factor); |
205 if (!data) | 211 if (!data) |
206 data = rb_.LoadDataResourceBytesForScale(id, ui::SCALE_FACTOR_100P); | 212 data = rb_.LoadDataResourceBytesForScale(id, ui::SCALE_FACTOR_100P); |
207 | 213 |
208 return data; | 214 return data; |
209 } | 215 } |
210 | 216 |
211 void ThemeService::Observe(int type, | 217 void ThemeService::Observe(int type, |
212 const content::NotificationSource& source, | 218 const content::NotificationSource& source, |
213 const content::NotificationDetails& details) { | 219 const content::NotificationDetails& details) { |
214 DCHECK(type == chrome::NOTIFICATION_EXTENSIONS_READY); | 220 using content::Details; |
215 registrar_.Remove(this, chrome::NOTIFICATION_EXTENSIONS_READY, | 221 switch (type) { |
216 content::Source<Profile>(profile_)); | 222 case chrome::NOTIFICATION_EXTENSIONS_READY: |
217 | 223 registrar_.Remove(this, chrome::NOTIFICATION_EXTENSIONS_READY, |
218 MigrateTheme(); | 224 content::Source<Profile>(profile_)); |
219 set_ready(); | 225 OnExtensionServiceReady(); |
220 | 226 break; |
221 // Send notification in case anyone requested data and cached it when the | 227 case chrome::NOTIFICATION_EXTENSION_INSTALLED: |
222 // theme service was not ready yet. | 228 { |
223 NotifyThemeChanged(); | 229 // The theme may be initially disabled. Wait till it is loaded (if ever). |
| 230 Details<const extensions::InstalledExtensionInfo> installed_details( |
| 231 details); |
| 232 if (installed_details->extension->is_theme()) |
| 233 installed_pending_load_id_ = installed_details->extension->id(); |
| 234 break; |
| 235 } |
| 236 case chrome::NOTIFICATION_EXTENSION_LOADED: |
| 237 { |
| 238 const Extension* extension = Details<const Extension>(details).ptr(); |
| 239 if (extension->is_theme() && |
| 240 installed_pending_load_id_ != kDefaultThemeID && |
| 241 installed_pending_load_id_ == extension->id()) { |
| 242 SetTheme(extension); |
| 243 } |
| 244 installed_pending_load_id_ = kDefaultThemeID; |
| 245 break; |
| 246 } |
| 247 case chrome::NOTIFICATION_EXTENSION_ENABLED: |
| 248 { |
| 249 const Extension* extension = Details<const Extension>(details).ptr(); |
| 250 if (extension->is_theme()) |
| 251 SetTheme(extension); |
| 252 break; |
| 253 } |
| 254 case chrome::NOTIFICATION_EXTENSION_UNLOADED: |
| 255 { |
| 256 Details<const extensions::UnloadedExtensionInfo> unloaded_details( |
| 257 details); |
| 258 if (unloaded_details->reason != extension_misc::UNLOAD_REASON_UPDATE && |
| 259 unloaded_details->extension->is_theme() && |
| 260 unloaded_details->extension->id() == GetThemeID()) { |
| 261 UseDefaultTheme(); |
| 262 } |
| 263 break; |
| 264 } |
| 265 } |
224 } | 266 } |
225 | 267 |
226 void ThemeService::SetTheme(const Extension* extension) { | 268 void ThemeService::SetTheme(const Extension* extension) { |
| 269 DCHECK(extension->is_theme()); |
| 270 ExtensionService* service = |
| 271 extensions::ExtensionSystem::Get(profile_)->extension_service(); |
| 272 if (!service->IsExtensionEnabled(extension->id())) { |
| 273 // |extension| is disabled when reverting to the previous theme via an |
| 274 // infobar. |
| 275 service->EnableExtension(extension->id()); |
| 276 // Enabling the extension will call back to SetTheme(). |
| 277 return; |
| 278 } |
| 279 |
| 280 std::string previous_theme_id = GetThemeID(); |
| 281 |
227 // Clear our image cache. | 282 // Clear our image cache. |
228 FreePlatformCaches(); | 283 FreePlatformCaches(); |
229 | 284 |
230 DCHECK(extension); | |
231 DCHECK(extension->is_theme()); | |
232 if (DCHECK_IS_ON()) { | |
233 ExtensionService* service = | |
234 extensions::ExtensionSystem::Get(profile_)->extension_service(); | |
235 DCHECK(service); | |
236 DCHECK(service->GetExtensionById(extension->id(), false)); | |
237 } | |
238 | |
239 BuildFromExtension(extension); | 285 BuildFromExtension(extension); |
240 SaveThemeID(extension->id()); | 286 SaveThemeID(extension->id()); |
241 | 287 |
242 NotifyThemeChanged(); | 288 NotifyThemeChanged(); |
243 content::RecordAction(UserMetricsAction("Themes_Installed")); | 289 content::RecordAction(UserMetricsAction("Themes_Installed")); |
| 290 |
| 291 if (previous_theme_id != kDefaultThemeID && |
| 292 previous_theme_id != extension->id()) { |
| 293 // Disable the old theme. |
| 294 service->DisableExtension(previous_theme_id, |
| 295 extensions::Extension::DISABLE_USER_ACTION); |
| 296 } |
244 } | 297 } |
245 | 298 |
246 void ThemeService::SetCustomDefaultTheme( | 299 void ThemeService::SetCustomDefaultTheme( |
247 scoped_refptr<CustomThemeSupplier> theme_supplier) { | 300 scoped_refptr<CustomThemeSupplier> theme_supplier) { |
248 ClearAllThemeData(); | 301 ClearAllThemeData(); |
249 SwapThemeSupplier(theme_supplier); | 302 SwapThemeSupplier(theme_supplier); |
250 NotifyThemeChanged(); | 303 NotifyThemeChanged(); |
251 } | 304 } |
252 | 305 |
253 bool ThemeService::ShouldInitWithNativeTheme() const { | 306 bool ThemeService::ShouldInitWithNativeTheme() const { |
254 return false; | 307 return false; |
255 } | 308 } |
256 | 309 |
257 void ThemeService::RemoveUnusedThemes() { | 310 void ThemeService::RemoveUnusedThemes(bool ignore_infobars) { |
258 // We do not want to garbage collect themes on startup (|ready_| is false). | 311 // We do not want to garbage collect themes on startup (|ready_| is false). |
259 // Themes will get garbage collected once | 312 // Themes will get garbage collected after |kRemoveUnusedThemesStartupDelay|. |
260 // ExtensionService::GarbageCollectExtensions() runs. | |
261 if (!profile_ || !ready_) | 313 if (!profile_ || !ready_) |
262 return; | 314 return; |
| 315 if (!ignore_infobars && number_of_infobars_ != 0) |
| 316 return; |
263 | 317 |
264 ExtensionService* service = profile_->GetExtensionService(); | 318 ExtensionService* service = profile_->GetExtensionService(); |
265 if (!service) | 319 if (!service) |
266 return; | 320 return; |
267 std::string current_theme = GetThemeID(); | 321 std::string current_theme = GetThemeID(); |
268 std::vector<std::string> remove_list; | 322 std::vector<std::string> remove_list; |
269 const ExtensionSet* extensions = service->extensions(); | 323 scoped_ptr<const ExtensionSet> extensions( |
| 324 service->GenerateInstalledExtensionsSet()); |
| 325 extensions::ExtensionPrefs* prefs = service->extension_prefs(); |
270 for (ExtensionSet::const_iterator it = extensions->begin(); | 326 for (ExtensionSet::const_iterator it = extensions->begin(); |
271 it != extensions->end(); ++it) { | 327 it != extensions->end(); ++it) { |
272 if ((*it)->is_theme() && (*it)->id() != current_theme) { | 328 const extensions::Extension* extension = *it; |
273 remove_list.push_back((*it)->id()); | 329 if (extension->is_theme() && |
| 330 extension->id() != current_theme) { |
| 331 // Only uninstall themes which are not disabled or are disabled with |
| 332 // reason DISABLE_USER_ACTION. We cannot blanket uninstall all disabled |
| 333 // themes because externally installed themes are initially disabled. |
| 334 int disable_reason = prefs->GetDisableReasons(extension->id()); |
| 335 if (!prefs->IsExtensionDisabled(extension->id()) || |
| 336 disable_reason == Extension::DISABLE_USER_ACTION) { |
| 337 remove_list.push_back((*it)->id()); |
| 338 } |
274 } | 339 } |
275 } | 340 } |
| 341 // TODO: Garbage collect all unused themes. This method misses themes which |
| 342 // are installed but not loaded because they are blacklisted by a management |
| 343 // policy provider. |
| 344 |
276 for (size_t i = 0; i < remove_list.size(); ++i) | 345 for (size_t i = 0; i < remove_list.size(); ++i) |
277 service->UninstallExtension(remove_list[i], false, NULL); | 346 service->UninstallExtension(remove_list[i], false, NULL); |
278 } | 347 } |
279 | 348 |
280 void ThemeService::UseDefaultTheme() { | 349 void ThemeService::UseDefaultTheme() { |
281 if (ready_) | 350 if (ready_) |
282 content::RecordAction(UserMetricsAction("Themes_Reset")); | 351 content::RecordAction(UserMetricsAction("Themes_Reset")); |
283 if (IsManagedUser()) { | 352 if (IsManagedUser()) { |
284 SetManagedUserTheme(); | 353 SetManagedUserTheme(); |
285 return; | 354 return; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
321 return; | 390 return; |
322 | 391 |
323 SwapThemeSupplier(NULL); | 392 SwapThemeSupplier(NULL); |
324 | 393 |
325 // Clear our image cache. | 394 // Clear our image cache. |
326 FreePlatformCaches(); | 395 FreePlatformCaches(); |
327 | 396 |
328 profile_->GetPrefs()->ClearPref(prefs::kCurrentThemePackFilename); | 397 profile_->GetPrefs()->ClearPref(prefs::kCurrentThemePackFilename); |
329 SaveThemeID(kDefaultThemeID); | 398 SaveThemeID(kDefaultThemeID); |
330 | 399 |
331 RemoveUnusedThemes(); | 400 // There should be no more infobars. This may not be the case because of |
| 401 // http://crbug.com/62154 |
| 402 // RemoveUnusedThemes is called on a task because ClearAllThemeData() may |
| 403 // be called as a result of NOTIFICATION_EXTENSION_UNLOADED. |
| 404 base::MessageLoop::current()->PostTask(FROM_HERE, |
| 405 base::Bind(&ThemeService::RemoveUnusedThemes, |
| 406 weak_ptr_factory_.GetWeakPtr(), |
| 407 true)); |
332 } | 408 } |
333 | 409 |
334 void ThemeService::LoadThemePrefs() { | 410 void ThemeService::LoadThemePrefs() { |
335 PrefService* prefs = profile_->GetPrefs(); | 411 PrefService* prefs = profile_->GetPrefs(); |
336 | 412 |
337 std::string current_id = GetThemeID(); | 413 std::string current_id = GetThemeID(); |
338 if (current_id == kDefaultThemeID) { | 414 if (current_id == kDefaultThemeID) { |
339 // Managed users have a different default theme. | 415 // Managed users have a different default theme. |
340 if (IsManagedUser()) | 416 if (IsManagedUser()) |
341 SetManagedUserTheme(); | 417 SetManagedUserTheme(); |
(...skipping 10 matching lines...) Expand all Loading... |
352 // If we don't have a file pack, we're updating from an old version. | 428 // If we don't have a file pack, we're updating from an old version. |
353 base::FilePath path = prefs->GetFilePath(prefs::kCurrentThemePackFilename); | 429 base::FilePath path = prefs->GetFilePath(prefs::kCurrentThemePackFilename); |
354 if (path != base::FilePath()) { | 430 if (path != base::FilePath()) { |
355 SwapThemeSupplier(BrowserThemePack::BuildFromDataPack(path, current_id)); | 431 SwapThemeSupplier(BrowserThemePack::BuildFromDataPack(path, current_id)); |
356 loaded_pack = theme_supplier_.get() != NULL; | 432 loaded_pack = theme_supplier_.get() != NULL; |
357 } | 433 } |
358 | 434 |
359 if (loaded_pack) { | 435 if (loaded_pack) { |
360 content::RecordAction(UserMetricsAction("Themes.Loaded")); | 436 content::RecordAction(UserMetricsAction("Themes.Loaded")); |
361 set_ready(); | 437 set_ready(); |
362 } else { | |
363 // TODO(erg): We need to pop up a dialog informing the user that their | |
364 // theme is being migrated. | |
365 ExtensionService* service = | |
366 extensions::ExtensionSystem::Get(profile_)->extension_service(); | |
367 if (service && service->is_ready()) { | |
368 MigrateTheme(); | |
369 set_ready(); | |
370 } | |
371 } | 438 } |
| 439 // Else: wait for the extension service to be ready so that the theme pack |
| 440 // can be recreated from the extension. |
372 } | 441 } |
373 | 442 |
374 void ThemeService::NotifyThemeChanged() { | 443 void ThemeService::NotifyThemeChanged() { |
375 if (!ready_) | 444 if (!ready_) |
376 return; | 445 return; |
377 | 446 |
378 DVLOG(1) << "Sending BROWSER_THEME_CHANGED"; | 447 DVLOG(1) << "Sending BROWSER_THEME_CHANGED"; |
379 // Redraw! | 448 // Redraw! |
380 content::NotificationService* service = | 449 content::NotificationService* service = |
381 content::NotificationService::current(); | 450 content::NotificationService::current(); |
382 service->Notify(chrome::NOTIFICATION_BROWSER_THEME_CHANGED, | 451 service->Notify(chrome::NOTIFICATION_BROWSER_THEME_CHANGED, |
383 content::Source<ThemeService>(this), | 452 content::Source<ThemeService>(this), |
384 content::NotificationService::NoDetails()); | 453 content::NotificationService::NoDetails()); |
385 #if defined(OS_MACOSX) | 454 #if defined(OS_MACOSX) |
386 NotifyPlatformThemeChanged(); | 455 NotifyPlatformThemeChanged(); |
387 #endif // OS_MACOSX | 456 #endif // OS_MACOSX |
388 | 457 |
389 // Notify sync that theme has changed. | 458 // Notify sync that theme has changed. |
390 if (theme_syncable_service_.get()) { | 459 if (theme_syncable_service_.get()) { |
391 theme_syncable_service_->OnThemeChange(); | 460 theme_syncable_service_->OnThemeChange(); |
392 } | 461 } |
393 } | 462 } |
394 | 463 |
395 #if defined(OS_WIN) || defined(USE_AURA) | 464 #if defined(OS_WIN) || defined(USE_AURA) |
396 void ThemeService::FreePlatformCaches() { | 465 void ThemeService::FreePlatformCaches() { |
397 // Views (Skia) has no platform image cache to clear. | 466 // Views (Skia) has no platform image cache to clear. |
398 } | 467 } |
399 #endif | 468 #endif |
400 | 469 |
401 void ThemeService::SwapThemeSupplier( | 470 void ThemeService::OnExtensionServiceReady() { |
402 scoped_refptr<CustomThemeSupplier> theme_supplier) { | 471 if (!ready_) { |
403 if (theme_supplier_.get()) | 472 // If the ThemeService is not ready yet, the custom theme data pack needs to |
404 theme_supplier_->StopUsingTheme(); | 473 // be recreated from the extension. |
405 theme_supplier_ = theme_supplier; | 474 MigrateTheme(); |
406 if (theme_supplier_.get()) | 475 set_ready(); |
407 theme_supplier_->StartUsingTheme(); | 476 |
| 477 // Send notification in case anyone requested data and cached it when the |
| 478 // theme service was not ready yet. |
| 479 NotifyThemeChanged(); |
| 480 } |
| 481 |
| 482 registrar_.Add(this, |
| 483 chrome::NOTIFICATION_EXTENSION_INSTALLED, |
| 484 content::Source<Profile>(profile_)); |
| 485 registrar_.Add(this, |
| 486 chrome::NOTIFICATION_EXTENSION_LOADED, |
| 487 content::Source<Profile>(profile_)); |
| 488 registrar_.Add(this, |
| 489 chrome::NOTIFICATION_EXTENSION_ENABLED, |
| 490 content::Source<Profile>(profile_)); |
| 491 registrar_.Add(this, |
| 492 chrome::NOTIFICATION_EXTENSION_UNLOADED, |
| 493 content::Source<Profile>(profile_)); |
| 494 |
| 495 base::MessageLoop::current()->PostDelayedTask(FROM_HERE, |
| 496 base::Bind(&ThemeService::RemoveUnusedThemes, |
| 497 weak_ptr_factory_.GetWeakPtr(), |
| 498 false), |
| 499 base::TimeDelta::FromSeconds(kRemoveUnusedThemesStartupDelay)); |
408 } | 500 } |
409 | 501 |
410 void ThemeService::MigrateTheme() { | 502 void ThemeService::MigrateTheme() { |
| 503 // TODO(erg): We need to pop up a dialog informing the user that their |
| 504 // theme is being migrated. |
411 ExtensionService* service = | 505 ExtensionService* service = |
412 extensions::ExtensionSystem::Get(profile_)->extension_service(); | 506 extensions::ExtensionSystem::Get(profile_)->extension_service(); |
413 const Extension* extension = service ? | 507 const Extension* extension = service ? |
414 service->GetExtensionById(GetThemeID(), false) : NULL; | 508 service->GetExtensionById(GetThemeID(), false) : NULL; |
415 if (extension) { | 509 if (extension) { |
416 DLOG(ERROR) << "Migrating theme"; | 510 DLOG(ERROR) << "Migrating theme"; |
417 BuildFromExtension(extension); | 511 BuildFromExtension(extension); |
418 content::RecordAction(UserMetricsAction("Themes.Migrated")); | 512 content::RecordAction(UserMetricsAction("Themes.Migrated")); |
419 } else { | 513 } else { |
420 DLOG(ERROR) << "Theme is mysteriously gone."; | 514 DLOG(ERROR) << "Theme is mysteriously gone."; |
421 ClearAllThemeData(); | 515 ClearAllThemeData(); |
422 content::RecordAction(UserMetricsAction("Themes.Gone")); | 516 content::RecordAction(UserMetricsAction("Themes.Gone")); |
423 } | 517 } |
424 } | 518 } |
425 | 519 |
| 520 void ThemeService::SwapThemeSupplier( |
| 521 scoped_refptr<CustomThemeSupplier> theme_supplier) { |
| 522 if (theme_supplier_.get()) |
| 523 theme_supplier_->StopUsingTheme(); |
| 524 theme_supplier_ = theme_supplier; |
| 525 if (theme_supplier_.get()) |
| 526 theme_supplier_->StartUsingTheme(); |
| 527 } |
| 528 |
426 void ThemeService::SavePackName(const base::FilePath& pack_path) { | 529 void ThemeService::SavePackName(const base::FilePath& pack_path) { |
427 profile_->GetPrefs()->SetFilePath( | 530 profile_->GetPrefs()->SetFilePath( |
428 prefs::kCurrentThemePackFilename, pack_path); | 531 prefs::kCurrentThemePackFilename, pack_path); |
429 } | 532 } |
430 | 533 |
431 void ThemeService::SaveThemeID(const std::string& id) { | 534 void ThemeService::SaveThemeID(const std::string& id) { |
432 profile_->GetPrefs()->SetString(prefs::kCurrentThemeID, id); | 535 profile_->GetPrefs()->SetString(prefs::kCurrentThemeID, id); |
433 } | 536 } |
434 | 537 |
435 void ThemeService::BuildFromExtension(const Extension* extension) { | 538 void ThemeService::BuildFromExtension(const Extension* extension) { |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
486 } | 589 } |
487 | 590 |
488 void ThemeService::OnInfobarDisplayed() { | 591 void ThemeService::OnInfobarDisplayed() { |
489 number_of_infobars_++; | 592 number_of_infobars_++; |
490 } | 593 } |
491 | 594 |
492 void ThemeService::OnInfobarDestroyed() { | 595 void ThemeService::OnInfobarDestroyed() { |
493 number_of_infobars_--; | 596 number_of_infobars_--; |
494 | 597 |
495 if (number_of_infobars_ == 0) | 598 if (number_of_infobars_ == 0) |
496 RemoveUnusedThemes(); | 599 RemoveUnusedThemes(false); |
497 } | 600 } |
498 | 601 |
499 ThemeSyncableService* ThemeService::GetThemeSyncableService() const { | 602 ThemeSyncableService* ThemeService::GetThemeSyncableService() const { |
500 return theme_syncable_service_.get(); | 603 return theme_syncable_service_.get(); |
501 } | 604 } |
OLD | NEW |