| 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 <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 | 10 |
| 11 #include "base/bind.h" | 11 #include "base/bind.h" |
| 12 #include "base/files/file_util.h" | 12 #include "base/files/file_util.h" |
| 13 #include "base/location.h" | 13 #include "base/location.h" |
| 14 #include "base/memory/ref_counted_memory.h" | 14 #include "base/memory/ref_counted_memory.h" |
| 15 #include "base/metrics/user_metrics.h" | 15 #include "base/metrics/user_metrics.h" |
| 16 #include "base/sequenced_task_runner.h" | 16 #include "base/sequenced_task_runner.h" |
| 17 #include "base/single_thread_task_runner.h" | 17 #include "base/single_thread_task_runner.h" |
| 18 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
| 19 #include "base/strings/utf_string_conversions.h" | 19 #include "base/strings/utf_string_conversions.h" |
| 20 #include "base/task_scheduler/post_task.h" |
| 20 #include "base/threading/thread_task_runner_handle.h" | 21 #include "base/threading/thread_task_runner_handle.h" |
| 21 #include "build/build_config.h" | 22 #include "build/build_config.h" |
| 22 #include "chrome/browser/chrome_notification_types.h" | 23 #include "chrome/browser/chrome_notification_types.h" |
| 23 #include "chrome/browser/extensions/extension_service.h" | 24 #include "chrome/browser/extensions/extension_service.h" |
| 25 #include "chrome/browser/extensions/theme_installed_infobar_delegate.h" |
| 24 #include "chrome/browser/profiles/profile.h" | 26 #include "chrome/browser/profiles/profile.h" |
| 25 #include "chrome/browser/themes/browser_theme_pack.h" | 27 #include "chrome/browser/themes/browser_theme_pack.h" |
| 26 #include "chrome/browser/themes/custom_theme_supplier.h" | 28 #include "chrome/browser/themes/custom_theme_supplier.h" |
| 27 #include "chrome/browser/themes/theme_properties.h" | 29 #include "chrome/browser/themes/theme_properties.h" |
| 28 #include "chrome/browser/themes/theme_service_factory.h" | 30 #include "chrome/browser/themes/theme_service_factory.h" |
| 29 #include "chrome/browser/themes/theme_syncable_service.h" | 31 #include "chrome/browser/themes/theme_syncable_service.h" |
| 30 #include "chrome/common/chrome_constants.h" | 32 #include "chrome/common/chrome_constants.h" |
| 31 #include "chrome/common/features.h" | 33 #include "chrome/common/features.h" |
| 32 #include "chrome/common/pref_names.h" | 34 #include "chrome/common/pref_names.h" |
| 33 #include "chrome/grit/theme_resources.h" | 35 #include "chrome/grit/theme_resources.h" |
| (...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 255 switch (type) { | 257 switch (type) { |
| 256 case extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED: | 258 case extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED: |
| 257 registrar_.Remove(this, | 259 registrar_.Remove(this, |
| 258 extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED, | 260 extensions::NOTIFICATION_EXTENSIONS_READY_DEPRECATED, |
| 259 content::Source<Profile>(profile_)); | 261 content::Source<Profile>(profile_)); |
| 260 OnExtensionServiceReady(); | 262 OnExtensionServiceReady(); |
| 261 break; | 263 break; |
| 262 case extensions::NOTIFICATION_EXTENSION_ENABLED: { | 264 case extensions::NOTIFICATION_EXTENSION_ENABLED: { |
| 263 const Extension* extension = Details<const Extension>(details).ptr(); | 265 const Extension* extension = Details<const Extension>(details).ptr(); |
| 264 if (extension->is_theme()) | 266 if (extension->is_theme()) |
| 265 SetTheme(extension); | 267 DoSetTheme(extension, true); |
| 266 break; | 268 break; |
| 267 } | 269 } |
| 268 default: | 270 default: |
| 269 NOTREACHED(); | 271 NOTREACHED(); |
| 270 } | 272 } |
| 271 } | 273 } |
| 272 | 274 |
| 273 void ThemeService::SetTheme(const Extension* extension) { | 275 void ThemeService::SetTheme(const Extension* extension) { |
| 276 DoSetTheme(extension, false); |
| 277 } |
| 278 |
| 279 void ThemeService::RevertToTheme(const Extension* extension) { |
| 274 DCHECK(extension->is_theme()); | 280 DCHECK(extension->is_theme()); |
| 275 ExtensionService* service = | 281 ExtensionService* service = |
| 276 extensions::ExtensionSystem::Get(profile_)->extension_service(); | 282 extensions::ExtensionSystem::Get(profile_)->extension_service(); |
| 277 if (!service->IsExtensionEnabled(extension->id())) { | 283 DCHECK(!service->IsExtensionEnabled(extension->id())); |
| 278 // |extension| is disabled when reverting to the previous theme via an | 284 // |extension| is disabled when reverting to the previous theme via an |
| 279 // infobar. | 285 // infobar. |
| 280 service->EnableExtension(extension->id()); | 286 service->EnableExtension(extension->id()); |
| 281 // Enabling the extension will call back to SetTheme(). | 287 // Enabling the extension will call back to SetTheme(). |
| 282 return; | |
| 283 } | |
| 284 | |
| 285 std::string previous_theme_id = GetThemeID(); | |
| 286 | |
| 287 // Clear our image cache. | |
| 288 FreePlatformCaches(); | |
| 289 | |
| 290 BuildFromExtension(extension); | |
| 291 SaveThemeID(extension->id()); | |
| 292 | |
| 293 NotifyThemeChanged(); | |
| 294 base::RecordAction(UserMetricsAction("Themes_Installed")); | |
| 295 | |
| 296 if (previous_theme_id != kDefaultThemeID && | |
| 297 previous_theme_id != extension->id() && | |
| 298 service->GetInstalledExtension(previous_theme_id)) { | |
| 299 // Do not disable the previous theme if it is already uninstalled. Sending | |
| 300 // NOTIFICATION_BROWSER_THEME_CHANGED causes the previous theme to be | |
| 301 // uninstalled when the notification causes the remaining infobar to close | |
| 302 // and does not open any new infobars. See crbug.com/468280. | |
| 303 | |
| 304 // Disable the old theme. | |
| 305 service->DisableExtension(previous_theme_id, | |
| 306 extensions::Extension::DISABLE_USER_ACTION); | |
| 307 } | |
| 308 } | 288 } |
| 309 | 289 |
| 310 void ThemeService::UseDefaultTheme() { | 290 void ThemeService::UseDefaultTheme() { |
| 311 if (ready_) | 291 if (ready_) |
| 312 base::RecordAction(UserMetricsAction("Themes_Reset")); | 292 base::RecordAction(UserMetricsAction("Themes_Reset")); |
| 313 #if BUILDFLAG(ENABLE_SUPERVISED_USERS) | 293 #if BUILDFLAG(ENABLE_SUPERVISED_USERS) |
| 314 if (IsSupervisedUser()) { | 294 if (IsSupervisedUser()) { |
| 315 SetSupervisedUserTheme(); | 295 SetSupervisedUserTheme(); |
| 316 return; | 296 return; |
| 317 } | 297 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 342 return profile_->GetPrefs()->GetString(prefs::kCurrentThemeID); | 322 return profile_->GetPrefs()->GetString(prefs::kCurrentThemeID); |
| 343 } | 323 } |
| 344 | 324 |
| 345 void ThemeService::OnInfobarDisplayed() { | 325 void ThemeService::OnInfobarDisplayed() { |
| 346 number_of_infobars_++; | 326 number_of_infobars_++; |
| 347 } | 327 } |
| 348 | 328 |
| 349 void ThemeService::OnInfobarDestroyed() { | 329 void ThemeService::OnInfobarDestroyed() { |
| 350 number_of_infobars_--; | 330 number_of_infobars_--; |
| 351 | 331 |
| 352 if (number_of_infobars_ == 0) | 332 if (number_of_infobars_ == 0 && |
| 333 !build_extension_task_tracker_.HasTrackedTasks()) { |
| 353 RemoveUnusedThemes(false); | 334 RemoveUnusedThemes(false); |
| 335 } |
| 354 } | 336 } |
| 355 | 337 |
| 356 void ThemeService::RemoveUnusedThemes(bool ignore_infobars) { | 338 void ThemeService::RemoveUnusedThemes(bool ignore_infobars) { |
| 357 // We do not want to garbage collect themes on startup (|ready_| is false). | 339 // We do not want to garbage collect themes on startup (|ready_| is false). |
| 358 // Themes will get garbage collected after |kRemoveUnusedThemesStartupDelay|. | 340 // Themes will get garbage collected after |kRemoveUnusedThemesStartupDelay|. |
| 359 if (!profile_ || !ready_) | 341 if (!profile_ || !ready_) |
| 360 return; | 342 return; |
| 361 if (!ignore_infobars && number_of_infobars_ != 0) | 343 if (!ignore_infobars && number_of_infobars_ != 0) |
| 362 return; | 344 return; |
| 363 | 345 |
| 364 ExtensionService* service = | 346 ExtensionService* service = |
| 365 extensions::ExtensionSystem::Get(profile_)->extension_service(); | 347 extensions::ExtensionSystem::Get(profile_)->extension_service(); |
| 366 if (!service) | 348 if (!service) |
| 367 return; | 349 return; |
| 368 | 350 |
| 369 std::string current_theme = GetThemeID(); | 351 std::string current_theme = GetThemeID(); |
| 370 std::vector<std::string> remove_list; | 352 std::vector<std::string> remove_list; |
| 371 std::unique_ptr<const extensions::ExtensionSet> extensions( | 353 std::unique_ptr<const extensions::ExtensionSet> extensions( |
| 372 extensions::ExtensionRegistry::Get(profile_) | 354 extensions::ExtensionRegistry::Get(profile_) |
| 373 ->GenerateInstalledExtensionsSet()); | 355 ->GenerateInstalledExtensionsSet()); |
| 374 extensions::ExtensionPrefs* prefs = extensions::ExtensionPrefs::Get(profile_); | 356 extensions::ExtensionPrefs* prefs = extensions::ExtensionPrefs::Get(profile_); |
| 375 for (extensions::ExtensionSet::const_iterator it = extensions->begin(); | 357 for (extensions::ExtensionSet::const_iterator it = extensions->begin(); |
| 376 it != extensions->end(); ++it) { | 358 it != extensions->end(); ++it) { |
| 377 const extensions::Extension* extension = it->get(); | 359 const extensions::Extension* extension = it->get(); |
| 378 if (extension->is_theme() && | 360 if (extension->is_theme() && extension->id() != current_theme && |
| 379 extension->id() != current_theme) { | 361 extension->id() != building_extension_id_) { |
| 380 // Only uninstall themes which are not disabled or are disabled with | 362 // Only uninstall themes which are not disabled or are disabled with |
| 381 // reason DISABLE_USER_ACTION. We cannot blanket uninstall all disabled | 363 // reason DISABLE_USER_ACTION. We cannot blanket uninstall all disabled |
| 382 // themes because externally installed themes are initially disabled. | 364 // themes because externally installed themes are initially disabled. |
| 383 int disable_reason = prefs->GetDisableReasons(extension->id()); | 365 int disable_reason = prefs->GetDisableReasons(extension->id()); |
| 384 if (!prefs->IsExtensionDisabled(extension->id()) || | 366 if (!prefs->IsExtensionDisabled(extension->id()) || |
| 385 disable_reason == Extension::DISABLE_USER_ACTION) { | 367 disable_reason == Extension::DISABLE_USER_ACTION) { |
| 386 remove_list.push_back((*it)->id()); | 368 remove_list.push_back((*it)->id()); |
| 387 } | 369 } |
| 388 } | 370 } |
| 389 } | 371 } |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 571 else | 553 else |
| 572 UseDefaultTheme(); | 554 UseDefaultTheme(); |
| 573 set_ready(); | 555 set_ready(); |
| 574 return; | 556 return; |
| 575 } | 557 } |
| 576 | 558 |
| 577 bool loaded_pack = false; | 559 bool loaded_pack = false; |
| 578 | 560 |
| 579 // If we don't have a file pack, we're updating from an old version. | 561 // If we don't have a file pack, we're updating from an old version. |
| 580 base::FilePath path = prefs->GetFilePath(prefs::kCurrentThemePackFilename); | 562 base::FilePath path = prefs->GetFilePath(prefs::kCurrentThemePackFilename); |
| 581 if (path != base::FilePath()) { | 563 if (!path.empty()) { |
| 582 path = path.Append(chrome::kThemePackFilename); | 564 path = path.Append(chrome::kThemePackFilename); |
| 583 SwapThemeSupplier(BrowserThemePack::BuildFromDataPack(path, current_id)); | 565 SwapThemeSupplier(BrowserThemePack::BuildFromDataPack(path, current_id)); |
| 584 if (theme_supplier_) | 566 if (theme_supplier_) |
| 585 loaded_pack = true; | 567 loaded_pack = true; |
| 586 } | 568 } |
| 587 | 569 |
| 588 if (loaded_pack) { | 570 if (loaded_pack) { |
| 589 base::RecordAction(UserMetricsAction("Themes.Loaded")); | 571 base::RecordAction(UserMetricsAction("Themes.Loaded")); |
| 590 set_ready(); | 572 set_ready(); |
| 591 } | 573 } |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 678 for (int delta = lighten ? 64 : -64; delta != 0; delta /= 2) { | 660 for (int delta = lighten ? 64 : -64; delta != 0; delta /= 2) { |
| 679 const double luminance = color_utils::GetRelativeLuminance( | 661 const double luminance = color_utils::GetRelativeLuminance( |
| 680 color_utils::AlphaBlend(separator_color, frame_color, alpha)); | 662 color_utils::AlphaBlend(separator_color, frame_color, alpha)); |
| 681 if (luminance == target_luminance) | 663 if (luminance == target_luminance) |
| 682 break; | 664 break; |
| 683 alpha += (luminance < target_luminance) ? -delta : delta; | 665 alpha += (luminance < target_luminance) ? -delta : delta; |
| 684 } | 666 } |
| 685 return SkColorSetA(separator_color, alpha); | 667 return SkColorSetA(separator_color, alpha); |
| 686 } | 668 } |
| 687 | 669 |
| 670 void ThemeService::DoSetTheme(const Extension* extension, |
| 671 bool suppress_infobar) { |
| 672 DCHECK(extension->is_theme()); |
| 673 DCHECK(extensions::ExtensionSystem::Get(profile_) |
| 674 ->extension_service() |
| 675 ->IsExtensionEnabled(extension->id())); |
| 676 BuildFromExtension(extension, suppress_infobar); |
| 677 } |
| 678 |
| 688 gfx::ImageSkia* ThemeService::GetImageSkiaNamed(int id, bool incognito) const { | 679 gfx::ImageSkia* ThemeService::GetImageSkiaNamed(int id, bool incognito) const { |
| 689 gfx::Image image = GetImageNamed(id, incognito); | 680 gfx::Image image = GetImageNamed(id, incognito); |
| 690 if (image.IsEmpty()) | 681 if (image.IsEmpty()) |
| 691 return nullptr; | 682 return nullptr; |
| 692 // TODO(pkotwicz): Remove this const cast. The gfx::Image interface returns | 683 // TODO(pkotwicz): Remove this const cast. The gfx::Image interface returns |
| 693 // its images const. GetImageSkiaNamed() also should but has many callsites. | 684 // its images const. GetImageSkiaNamed() also should but has many callsites. |
| 694 return const_cast<gfx::ImageSkia*>(image.ToImageSkia()); | 685 return const_cast<gfx::ImageSkia*>(image.ToImageSkia()); |
| 695 } | 686 } |
| 696 | 687 |
| 697 SkColor ThemeService::GetColor(int id, bool incognito) const { | 688 SkColor ThemeService::GetColor(int id, bool incognito) const { |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 778 | 769 |
| 779 return image; | 770 return image; |
| 780 } | 771 } |
| 781 | 772 |
| 782 void ThemeService::OnExtensionServiceReady() { | 773 void ThemeService::OnExtensionServiceReady() { |
| 783 if (!ready_) { | 774 if (!ready_) { |
| 784 // If the ThemeService is not ready yet, the custom theme data pack needs to | 775 // If the ThemeService is not ready yet, the custom theme data pack needs to |
| 785 // be recreated from the extension. | 776 // be recreated from the extension. |
| 786 MigrateTheme(); | 777 MigrateTheme(); |
| 787 set_ready(); | 778 set_ready(); |
| 788 | |
| 789 // Send notification in case anyone requested data and cached it when the | |
| 790 // theme service was not ready yet. | |
| 791 NotifyThemeChanged(); | |
| 792 } | 779 } |
| 793 | 780 |
| 794 #if BUILDFLAG(ENABLE_EXTENSIONS) | 781 #if BUILDFLAG(ENABLE_EXTENSIONS) |
| 795 theme_observer_.reset(new ThemeObserver(this)); | 782 theme_observer_.reset(new ThemeObserver(this)); |
| 796 #endif | 783 #endif |
| 797 | 784 |
| 798 registrar_.Add(this, | 785 registrar_.Add(this, |
| 799 extensions::NOTIFICATION_EXTENSION_ENABLED, | 786 extensions::NOTIFICATION_EXTENSION_ENABLED, |
| 800 content::Source<Profile>(profile_)); | 787 content::Source<Profile>(profile_)); |
| 801 | 788 |
| 802 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | 789 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 803 FROM_HERE, base::Bind(&ThemeService::RemoveUnusedThemes, | 790 FROM_HERE, base::Bind(&ThemeService::RemoveUnusedThemes, |
| 804 weak_ptr_factory_.GetWeakPtr(), false), | 791 weak_ptr_factory_.GetWeakPtr(), false), |
| 805 base::TimeDelta::FromSeconds(kRemoveUnusedThemesStartupDelay)); | 792 base::TimeDelta::FromSeconds(kRemoveUnusedThemesStartupDelay)); |
| 806 } | 793 } |
| 807 | 794 |
| 808 void ThemeService::MigrateTheme() { | 795 void ThemeService::MigrateTheme() { |
| 809 // TODO(erg): We need to pop up a dialog informing the user that their | |
| 810 // theme is being migrated. | |
| 811 ExtensionService* service = | 796 ExtensionService* service = |
| 812 extensions::ExtensionSystem::Get(profile_)->extension_service(); | 797 extensions::ExtensionSystem::Get(profile_)->extension_service(); |
| 813 const Extension* extension = | 798 const Extension* extension = |
| 814 service ? service->GetExtensionById(GetThemeID(), false) : nullptr; | 799 service ? service->GetExtensionById(GetThemeID(), false) : nullptr; |
| 815 if (extension) { | 800 if (extension) { |
| 816 DLOG(ERROR) << "Migrating theme"; | 801 DLOG(ERROR) << "Migrating theme"; |
| 817 BuildFromExtension(extension); | 802 // Theme migration is done on the UI thread. Blocking the UI from appearing |
| 803 // until it's ready is deemed better than showing a blip of the default |
| 804 // theme. |
| 805 scoped_refptr<BrowserThemePack> pack(new BrowserThemePack); |
| 806 BrowserThemePack::BuildFromExtension(extension, pack); |
| 807 OnThemeBuiltFromExtension(extension->id(), pack, true); |
| 818 base::RecordAction(UserMetricsAction("Themes.Migrated")); | 808 base::RecordAction(UserMetricsAction("Themes.Migrated")); |
| 819 } else { | 809 } else { |
| 820 DLOG(ERROR) << "Theme is mysteriously gone."; | 810 DLOG(ERROR) << "Theme is mysteriously gone."; |
| 821 ClearAllThemeData(); | 811 ClearAllThemeData(); |
| 822 base::RecordAction(UserMetricsAction("Themes.Gone")); | 812 base::RecordAction(UserMetricsAction("Themes.Gone")); |
| 823 } | 813 } |
| 824 } | 814 } |
| 825 | 815 |
| 826 void ThemeService::SwapThemeSupplier( | 816 void ThemeService::SwapThemeSupplier( |
| 827 scoped_refptr<CustomThemeSupplier> theme_supplier) { | 817 scoped_refptr<CustomThemeSupplier> theme_supplier) { |
| 828 if (theme_supplier_) | 818 if (theme_supplier_) |
| 829 theme_supplier_->StopUsingTheme(); | 819 theme_supplier_->StopUsingTheme(); |
| 830 theme_supplier_ = theme_supplier; | 820 theme_supplier_ = theme_supplier; |
| 831 if (theme_supplier_) | 821 if (theme_supplier_) |
| 832 theme_supplier_->StartUsingTheme(); | 822 theme_supplier_->StartUsingTheme(); |
| 833 } | 823 } |
| 834 | 824 |
| 835 void ThemeService::SavePackName(const base::FilePath& pack_path) { | 825 void ThemeService::SavePackName(const base::FilePath& pack_path) { |
| 836 profile_->GetPrefs()->SetFilePath( | 826 profile_->GetPrefs()->SetFilePath( |
| 837 prefs::kCurrentThemePackFilename, pack_path); | 827 prefs::kCurrentThemePackFilename, pack_path); |
| 838 } | 828 } |
| 839 | 829 |
| 840 void ThemeService::SaveThemeID(const std::string& id) { | 830 void ThemeService::SaveThemeID(const std::string& id) { |
| 841 profile_->GetPrefs()->SetString(prefs::kCurrentThemeID, id); | 831 profile_->GetPrefs()->SetString(prefs::kCurrentThemeID, id); |
| 842 } | 832 } |
| 843 | 833 |
| 844 void ThemeService::BuildFromExtension(const Extension* extension) { | 834 void ThemeService::BuildFromExtension(const Extension* extension, |
| 845 scoped_refptr<BrowserThemePack> pack( | 835 bool suppress_infobar) { |
| 846 BrowserThemePack::BuildFromExtension(extension)); | 836 build_extension_task_tracker_.TryCancelAll(); |
| 847 if (!pack.get()) { | 837 building_extension_id_ = extension->id(); |
| 838 scoped_refptr<BrowserThemePack> pack(new BrowserThemePack); |
| 839 auto task_runner = base::CreateTaskRunnerWithTraits( |
| 840 {base::MayBlock(), base::TaskPriority::USER_BLOCKING}); |
| 841 build_extension_task_tracker_.PostTaskAndReply( |
| 842 task_runner.get(), FROM_HERE, |
| 843 base::Bind(&BrowserThemePack::BuildFromExtension, extension, pack), |
| 844 base::Bind(&ThemeService::OnThemeBuiltFromExtension, |
| 845 weak_ptr_factory_.GetWeakPtr(), extension->id(), pack, |
| 846 suppress_infobar)); |
| 847 } |
| 848 |
| 849 void ThemeService::OnThemeBuiltFromExtension( |
| 850 const extensions::ExtensionId& extension_id, |
| 851 scoped_refptr<BrowserThemePack> pack, |
| 852 bool suppress_infobar) { |
| 853 if (!pack->is_valid()) { |
| 848 // TODO(erg): We've failed to install the theme; perhaps we should tell the | 854 // TODO(erg): We've failed to install the theme; perhaps we should tell the |
| 849 // user? http://crbug.com/34780 | 855 // user? http://crbug.com/34780 |
| 850 LOG(ERROR) << "Could not load theme."; | 856 LOG(ERROR) << "Could not load theme."; |
| 851 return; | 857 return; |
| 852 } | 858 } |
| 853 | 859 |
| 854 ExtensionService* service = | 860 ExtensionService* service = |
| 855 extensions::ExtensionSystem::Get(profile_)->extension_service(); | 861 extensions::ExtensionSystem::Get(profile_)->extension_service(); |
| 856 if (!service) | 862 if (!service) |
| 857 return; | 863 return; |
| 864 const Extension* extension = extensions::ExtensionRegistry::Get(profile_) |
| 865 ->enabled_extensions() |
| 866 .GetByID(extension_id); |
| 867 if (!extension) |
| 868 return; |
| 858 | 869 |
| 859 // Write the packed file to disk. | 870 // Write the packed file to disk. |
| 860 service->GetFileTaskRunner()->PostTask( | 871 service->GetFileTaskRunner()->PostTask( |
| 861 FROM_HERE, base::Bind(&WritePackToDiskCallback, base::RetainedRef(pack), | 872 FROM_HERE, base::Bind(&WritePackToDiskCallback, base::RetainedRef(pack), |
| 862 extension->path())); | 873 extension->path())); |
| 863 | 874 |
| 864 // Save only the extension path. The packed file will be loaded via | 875 // Save only the extension path. The packed file will be loaded via |
| 865 // LoadThemePrefs(). | 876 // LoadThemePrefs(). |
| 866 SavePackName(extension->path()); | 877 SavePackName(extension->path()); |
| 867 SwapThemeSupplier(pack); | 878 SwapThemeSupplier(pack); |
| 879 |
| 880 const std::string previous_theme_id = GetThemeID(); |
| 881 const bool previous_using_system_theme = UsingSystemTheme(); |
| 882 |
| 883 // Clear our image cache. |
| 884 FreePlatformCaches(); |
| 885 SaveThemeID(extension->id()); |
| 886 NotifyThemeChanged(); |
| 887 |
| 888 // Same old theme, but the theme has changed (migrated) or auto-updated. |
| 889 if (previous_theme_id == extension->id()) |
| 890 return; |
| 891 |
| 892 base::RecordAction(UserMetricsAction("Themes_Installed")); |
| 893 |
| 894 bool can_revert_theme = |
| 895 previous_theme_id == kDefaultThemeID || previous_using_system_theme; |
| 896 if (previous_theme_id != kDefaultThemeID && |
| 897 service->GetInstalledExtension(previous_theme_id)) { |
| 898 // Do not disable the previous theme if it is already uninstalled. Sending |
| 899 // NOTIFICATION_BROWSER_THEME_CHANGED causes the previous theme to be |
| 900 // uninstalled when the notification causes the remaining infobar to close |
| 901 // and does not open any new infobars. See crbug.com/468280. |
| 902 |
| 903 // Disable the old theme. |
| 904 service->DisableExtension(previous_theme_id, |
| 905 extensions::Extension::DISABLE_USER_ACTION); |
| 906 |
| 907 can_revert_theme = true; |
| 908 } |
| 909 |
| 910 // Offer to revert to the old theme. |
| 911 if (can_revert_theme && !suppress_infobar) { |
| 912 ThemeInstalledInfoBarDelegate::Create( |
| 913 extension, profile_, previous_theme_id, previous_using_system_theme); |
| 914 } |
| 915 building_extension_id_.clear(); |
| 868 } | 916 } |
| 869 | 917 |
| 870 #if BUILDFLAG(ENABLE_SUPERVISED_USERS) | 918 #if BUILDFLAG(ENABLE_SUPERVISED_USERS) |
| 871 bool ThemeService::IsSupervisedUser() const { | 919 bool ThemeService::IsSupervisedUser() const { |
| 872 return profile_->IsSupervised(); | 920 return profile_->IsSupervised(); |
| 873 } | 921 } |
| 874 | 922 |
| 875 void ThemeService::SetSupervisedUserTheme() { | 923 void ThemeService::SetSupervisedUserTheme() { |
| 876 SetCustomDefaultTheme(new SupervisedUserTheme); | 924 SetCustomDefaultTheme(new SupervisedUserTheme); |
| 877 } | 925 } |
| 878 #endif | 926 #endif |
| OLD | NEW |