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 |
| 875 const std::string previous_theme_id = GetThemeID(); |
| 876 const bool previous_using_system_theme = UsingSystemTheme(); |
| 877 |
864 // Save only the extension path. The packed file will be loaded via | 878 // Save only the extension path. The packed file will be loaded via |
865 // LoadThemePrefs(). | 879 // LoadThemePrefs(). |
866 SavePackName(extension->path()); | 880 SavePackName(extension->path()); |
867 SwapThemeSupplier(pack); | 881 SwapThemeSupplier(pack); |
| 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 = previous_theme_id == kDefaultThemeID; |
| 895 if (previous_theme_id != kDefaultThemeID && |
| 896 service->GetInstalledExtension(previous_theme_id)) { |
| 897 // Do not disable the previous theme if it is already uninstalled. Sending |
| 898 // NOTIFICATION_BROWSER_THEME_CHANGED causes the previous theme to be |
| 899 // uninstalled when the notification causes the remaining infobar to close |
| 900 // and does not open any new infobars. See crbug.com/468280. |
| 901 |
| 902 // Disable the old theme. |
| 903 service->DisableExtension(previous_theme_id, |
| 904 extensions::Extension::DISABLE_USER_ACTION); |
| 905 |
| 906 can_revert_theme = true; |
| 907 } |
| 908 |
| 909 // Offer to revert to the old theme. |
| 910 if (can_revert_theme && !suppress_infobar) { |
| 911 ThemeInstalledInfoBarDelegate::Create( |
| 912 extension, profile_, previous_theme_id, previous_using_system_theme); |
| 913 } |
| 914 building_extension_id_.clear(); |
868 } | 915 } |
869 | 916 |
870 #if BUILDFLAG(ENABLE_SUPERVISED_USERS) | 917 #if BUILDFLAG(ENABLE_SUPERVISED_USERS) |
871 bool ThemeService::IsSupervisedUser() const { | 918 bool ThemeService::IsSupervisedUser() const { |
872 return profile_->IsSupervised(); | 919 return profile_->IsSupervised(); |
873 } | 920 } |
874 | 921 |
875 void ThemeService::SetSupervisedUserTheme() { | 922 void ThemeService::SetSupervisedUserTheme() { |
876 SetCustomDefaultTheme(new SupervisedUserTheme); | 923 SetCustomDefaultTheme(new SupervisedUserTheme); |
877 } | 924 } |
878 #endif | 925 #endif |
OLD | NEW |