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