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/json/json_reader.h" | 7 #include "base/file_util.h" |
| 8 #include "base/path_service.h" |
| 9 #include "chrome/browser/chrome_notification_types.h" |
8 #include "chrome/browser/extensions/extension_service_unittest.h" | 10 #include "chrome/browser/extensions/extension_service_unittest.h" |
| 11 #include "chrome/browser/extensions/unpacked_installer.h" |
9 #include "chrome/browser/themes/custom_theme_supplier.h" | 12 #include "chrome/browser/themes/custom_theme_supplier.h" |
10 #include "chrome/browser/themes/theme_service_factory.h" | 13 #include "chrome/browser/themes/theme_service_factory.h" |
| 14 #include "chrome/common/chrome_paths.h" |
11 #include "chrome/common/extensions/extension.h" | 15 #include "chrome/common/extensions/extension.h" |
12 #include "chrome/common/extensions/extension_manifest_constants.h" | 16 #include "chrome/common/extensions/extension_manifest_constants.h" |
13 #include "chrome/common/pref_names.h" | 17 #include "chrome/common/pref_names.h" |
14 #include "chrome/test/base/testing_profile.h" | 18 #include "chrome/test/base/testing_profile.h" |
| 19 #include "content/public/test/test_utils.h" |
15 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
16 | 21 |
17 namespace theme_service_internal { | 22 namespace theme_service_internal { |
18 | 23 |
19 class ThemeServiceTest : public ExtensionServiceTestBase { | 24 class ThemeServiceTest : public ExtensionServiceTestBase { |
20 public: | 25 public: |
21 ThemeServiceTest() {} | 26 ThemeServiceTest() {} |
22 virtual ~ThemeServiceTest() {} | 27 virtual ~ThemeServiceTest() {} |
23 | 28 |
24 scoped_refptr<extensions::Extension> MakeThemeExtension(base::FilePath path) { | 29 // Moves a minimal theme to |temp_dir_path| and unpacks it from that |
25 DictionaryValue source; | 30 // directory. |
26 source.SetString(extension_manifest_keys::kName, "theme"); | 31 std::string LoadUnpackedThemeAt(const base::FilePath& temp_dir) { |
27 source.Set(extension_manifest_keys::kTheme, new DictionaryValue()); | 32 base::FilePath dst_manifest_path = temp_dir.AppendASCII("manifest.json"); |
28 source.SetString(extension_manifest_keys::kUpdateURL, "http://foo.com"); | 33 base::FilePath test_data_dir; |
29 source.SetString(extension_manifest_keys::kVersion, "0.0.0.0"); | 34 EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir)); |
30 std::string error; | 35 base::FilePath src_manifest_path = |
31 scoped_refptr<extensions::Extension> extension = | 36 test_data_dir.AppendASCII("extensions/theme_minimal/manifest.json"); |
32 extensions::Extension::Create( | 37 EXPECT_TRUE(base::CopyFile(src_manifest_path, dst_manifest_path)); |
33 path, extensions::Manifest::EXTERNAL_PREF_DOWNLOAD, | 38 |
34 source, extensions::Extension::NO_FLAGS, &error); | 39 scoped_refptr<extensions::UnpackedInstaller> installer( |
35 EXPECT_TRUE(extension.get()); | 40 extensions::UnpackedInstaller::Create(service_)); |
36 EXPECT_EQ("", error); | 41 content::WindowedNotificationObserver observer( |
37 return extension; | 42 chrome::NOTIFICATION_EXTENSION_LOADED, |
| 43 content::Source<Profile>(profile_.get())); |
| 44 installer->Load(temp_dir); |
| 45 observer.Wait(); |
| 46 |
| 47 std::string extension_id = |
| 48 content::Details<extensions::Extension>(observer.details())->id(); |
| 49 |
| 50 // Let the ThemeService finish creating the theme pack. |
| 51 base::MessageLoop::current()->RunUntilIdle(); |
| 52 |
| 53 return extension_id; |
| 54 } |
| 55 |
| 56 // Update the theme with |extension_id|. |
| 57 void UpdateUnpackedTheme(const std::string& extension_id) { |
| 58 int updated_notification = service_->IsExtensionEnabled(extension_id) ? |
| 59 chrome::NOTIFICATION_EXTENSION_LOADED : |
| 60 chrome::NOTIFICATION_EXTENSION_UPDATE_DISABLED; |
| 61 |
| 62 const base::FilePath& path = |
| 63 service_->GetInstalledExtension(extension_id)->path(); |
| 64 |
| 65 scoped_refptr<extensions::UnpackedInstaller> installer( |
| 66 extensions::UnpackedInstaller::Create(service_)); |
| 67 content::WindowedNotificationObserver observer(updated_notification, |
| 68 content::Source<Profile>(profile_.get())); |
| 69 installer->Load(path); |
| 70 observer.Wait(); |
| 71 |
| 72 // Let the ThemeService finish creating the theme pack. |
| 73 base::MessageLoop::current()->RunUntilIdle(); |
38 } | 74 } |
39 | 75 |
40 virtual void SetUp() { | 76 virtual void SetUp() { |
41 ExtensionServiceTestBase::SetUp(); | 77 ExtensionServiceTestBase::SetUp(); |
42 InitializeEmptyExtensionService(); | 78 InitializeEmptyExtensionService(); |
| 79 service_->Init(); |
43 } | 80 } |
44 | 81 |
45 const CustomThemeSupplier* get_theme_supplier(ThemeService* theme_service) { | 82 const CustomThemeSupplier* get_theme_supplier(ThemeService* theme_service) { |
46 return theme_service->get_theme_supplier(); | 83 return theme_service->get_theme_supplier(); |
47 } | 84 } |
48 }; | 85 }; |
49 | 86 |
50 // Installs then uninstalls a theme and makes sure that the ThemeService | 87 // Installs then uninstalls a theme and makes sure that the ThemeService |
51 // reverts to the default theme after the uninstall. | 88 // reverts to the default theme after the uninstall. |
52 TEST_F(ThemeServiceTest, ThemeInstallUninstall) { | 89 TEST_F(ThemeServiceTest, ThemeInstallUninstall) { |
53 base::ScopedTempDir temp_dir; | |
54 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | |
55 ThemeService* theme_service = | 90 ThemeService* theme_service = |
56 ThemeServiceFactory::GetForProfile(profile_.get()); | 91 ThemeServiceFactory::GetForProfile(profile_.get()); |
57 theme_service->UseDefaultTheme(); | 92 theme_service->UseDefaultTheme(); |
58 scoped_refptr<extensions::Extension> extension = | 93 // Let the ThemeService uninstall unused themes. |
59 MakeThemeExtension(temp_dir.path()); | |
60 service_->FinishInstallationForTest(extension.get()); | |
61 // Let ThemeService finish creating the theme pack. | |
62 base::MessageLoop::current()->RunUntilIdle(); | 94 base::MessageLoop::current()->RunUntilIdle(); |
| 95 |
| 96 base::ScopedTempDir temp_dir; |
| 97 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
| 98 const std::string& extension_id = LoadUnpackedThemeAt(temp_dir.path()); |
63 EXPECT_FALSE(theme_service->UsingDefaultTheme()); | 99 EXPECT_FALSE(theme_service->UsingDefaultTheme()); |
64 EXPECT_EQ(extension->id(), theme_service->GetThemeID()); | 100 EXPECT_EQ(extension_id, theme_service->GetThemeID()); |
65 | 101 |
66 // Now unload the extension, should revert to the default theme. | 102 // Now uninstall the extension, should revert to the default theme. |
67 service_->UnloadExtension(extension->id(), | 103 service_->UninstallExtension(extension_id, false, NULL); |
68 extension_misc::UNLOAD_REASON_UNINSTALL); | |
69 EXPECT_TRUE(theme_service->UsingDefaultTheme()); | 104 EXPECT_TRUE(theme_service->UsingDefaultTheme()); |
70 } | 105 } |
71 | 106 |
72 // Upgrades a theme and ensures that the ThemeService does not revert to the | 107 // Test that a theme extension is disabled when not in use. A theme may be |
73 // default theme. | 108 // installed but not in use if it there is an infobar to revert to the previous |
74 TEST_F(ThemeServiceTest, ThemeUpgrade) { | 109 // theme. |
75 base::ScopedTempDir temp_dir; | 110 TEST_F(ThemeServiceTest, DisableUnusedTheme) { |
76 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | |
77 ThemeService* theme_service = | 111 ThemeService* theme_service = |
78 ThemeServiceFactory::GetForProfile(profile_.get()); | 112 ThemeServiceFactory::GetForProfile(profile_.get()); |
79 theme_service->UseDefaultTheme(); | 113 theme_service->UseDefaultTheme(); |
80 scoped_refptr<extensions::Extension> extension = | 114 // Let the ThemeService uninstall unused themes. |
81 MakeThemeExtension(temp_dir.path()); | |
82 service_->FinishInstallationForTest(extension.get()); | |
83 // Let ThemeService finish creating the theme pack. | |
84 base::MessageLoop::current()->RunUntilIdle(); | 115 base::MessageLoop::current()->RunUntilIdle(); |
| 116 |
| 117 base::ScopedTempDir temp_dir1; |
| 118 ASSERT_TRUE(temp_dir1.CreateUniqueTempDir()); |
| 119 base::ScopedTempDir temp_dir2; |
| 120 ASSERT_TRUE(temp_dir2.CreateUniqueTempDir()); |
| 121 |
| 122 // 1) Installing a theme should disable the previously active theme. |
| 123 const std::string& extension1_id = LoadUnpackedThemeAt(temp_dir1.path()); |
85 EXPECT_FALSE(theme_service->UsingDefaultTheme()); | 124 EXPECT_FALSE(theme_service->UsingDefaultTheme()); |
86 EXPECT_EQ(extension->id(), theme_service->GetThemeID()); | 125 EXPECT_EQ(extension1_id, theme_service->GetThemeID()); |
| 126 EXPECT_TRUE(service_->IsExtensionEnabled(extension1_id)); |
87 | 127 |
88 // Now unload the extension, should revert to the default theme. | 128 // Show an infobar to prevent the current theme from being uninstalled. |
89 service_->UnloadExtension(extension->id(), | 129 theme_service->OnInfobarDisplayed(); |
90 extension_misc::UNLOAD_REASON_UPDATE); | 130 |
| 131 const std::string& extension2_id = LoadUnpackedThemeAt(temp_dir2.path()); |
| 132 EXPECT_EQ(extension2_id, theme_service->GetThemeID()); |
| 133 EXPECT_TRUE(service_->IsExtensionEnabled(extension2_id)); |
| 134 EXPECT_TRUE(service_->GetExtensionById(extension1_id, |
| 135 ExtensionService::INCLUDE_DISABLED)); |
| 136 |
| 137 // 2) Enabling a disabled theme extension should swap the current theme. |
| 138 service_->EnableExtension(extension1_id); |
| 139 base::MessageLoop::current()->RunUntilIdle(); |
| 140 EXPECT_EQ(extension1_id, theme_service->GetThemeID()); |
| 141 EXPECT_TRUE(service_->IsExtensionEnabled(extension1_id)); |
| 142 EXPECT_TRUE(service_->GetExtensionById(extension2_id, |
| 143 ExtensionService::INCLUDE_DISABLED)); |
| 144 |
| 145 // 3) Using SetTheme() with a disabled theme should enable and set the |
| 146 // theme. This is the case when the user reverts to the previous theme |
| 147 // via an infobar. |
| 148 const extensions::Extension* extension2 = |
| 149 service_->GetInstalledExtension(extension2_id); |
| 150 theme_service->SetTheme(extension2); |
| 151 base::MessageLoop::current()->RunUntilIdle(); |
| 152 EXPECT_EQ(extension2_id, theme_service->GetThemeID()); |
| 153 EXPECT_TRUE(service_->IsExtensionEnabled(extension2_id)); |
| 154 EXPECT_TRUE(service_->GetExtensionById(extension1_id, |
| 155 ExtensionService::INCLUDE_DISABLED)); |
| 156 |
| 157 // 4) Disabling the current theme extension should revert to the default theme |
| 158 // and uninstall any installed theme extensions. |
| 159 theme_service->OnInfobarDestroyed(); |
91 EXPECT_FALSE(theme_service->UsingDefaultTheme()); | 160 EXPECT_FALSE(theme_service->UsingDefaultTheme()); |
| 161 service_->DisableExtension(extension2_id, |
| 162 extensions::Extension::DISABLE_USER_ACTION); |
| 163 base::MessageLoop::current()->RunUntilIdle(); |
| 164 EXPECT_TRUE(theme_service->UsingDefaultTheme()); |
| 165 EXPECT_FALSE(service_->GetInstalledExtension(extension1_id)); |
| 166 EXPECT_FALSE(service_->GetInstalledExtension(extension2_id)); |
| 167 } |
| 168 |
| 169 // Test the ThemeService's behavior when a theme is upgraded. |
| 170 TEST_F(ThemeServiceTest, ThemeUpgrade) { |
| 171 // Setup. |
| 172 ThemeService* theme_service = |
| 173 ThemeServiceFactory::GetForProfile(profile_.get()); |
| 174 theme_service->UseDefaultTheme(); |
| 175 // Let the ThemeService uninstall unused themes. |
| 176 base::MessageLoop::current()->RunUntilIdle(); |
| 177 |
| 178 theme_service->OnInfobarDisplayed(); |
| 179 |
| 180 base::ScopedTempDir temp_dir1; |
| 181 ASSERT_TRUE(temp_dir1.CreateUniqueTempDir()); |
| 182 base::ScopedTempDir temp_dir2; |
| 183 ASSERT_TRUE(temp_dir2.CreateUniqueTempDir()); |
| 184 |
| 185 const std::string& extension1_id = LoadUnpackedThemeAt(temp_dir1.path()); |
| 186 const std::string& extension2_id = LoadUnpackedThemeAt(temp_dir2.path()); |
| 187 |
| 188 // Test the initial state. |
| 189 EXPECT_TRUE(service_->GetExtensionById(extension1_id, |
| 190 ExtensionService::INCLUDE_DISABLED)); |
| 191 EXPECT_EQ(extension2_id, theme_service->GetThemeID()); |
| 192 |
| 193 // 1) Upgrading the current theme should not revert to the default theme. |
| 194 content::WindowedNotificationObserver theme_change_observer( |
| 195 chrome::NOTIFICATION_BROWSER_THEME_CHANGED, |
| 196 content::Source<ThemeService>(theme_service)); |
| 197 UpdateUnpackedTheme(extension2_id); |
| 198 |
| 199 // The ThemeService should have sent an theme change notification even though |
| 200 // the id of the current theme did not change. |
| 201 theme_change_observer.Wait(); |
| 202 |
| 203 EXPECT_EQ(extension2_id, theme_service->GetThemeID()); |
| 204 EXPECT_TRUE(service_->GetExtensionById(extension1_id, |
| 205 ExtensionService::INCLUDE_DISABLED)); |
| 206 |
| 207 // 2) Upgrading a disabled theme should not change the current theme. |
| 208 UpdateUnpackedTheme(extension1_id); |
| 209 EXPECT_EQ(extension2_id, theme_service->GetThemeID()); |
| 210 EXPECT_TRUE(service_->GetExtensionById(extension1_id, |
| 211 ExtensionService::INCLUDE_DISABLED)); |
92 } | 212 } |
93 | 213 |
94 // Checks that managed users have their own default theme. | 214 // Checks that managed users have their own default theme. |
95 TEST_F(ThemeServiceTest, ManagedUserThemeReplacesDefaultTheme) { | 215 TEST_F(ThemeServiceTest, ManagedUserThemeReplacesDefaultTheme) { |
96 profile_->GetPrefs()->SetBoolean(prefs::kProfileIsManaged, true); | 216 profile_->GetPrefs()->SetBoolean(prefs::kProfileIsManaged, true); |
97 ThemeService* theme_service = | 217 ThemeService* theme_service = |
98 ThemeServiceFactory::GetForProfile(profile_.get()); | 218 ThemeServiceFactory::GetForProfile(profile_.get()); |
99 theme_service->UseDefaultTheme(); | 219 theme_service->UseDefaultTheme(); |
100 EXPECT_TRUE(theme_service->UsingDefaultTheme()); | 220 EXPECT_TRUE(theme_service->UsingDefaultTheme()); |
101 EXPECT_TRUE(get_theme_supplier(theme_service)); | 221 EXPECT_TRUE(get_theme_supplier(theme_service)); |
(...skipping 11 matching lines...) Expand all Loading... |
113 ThemeServiceFactory::GetForProfile(profile_.get()); | 233 ThemeServiceFactory::GetForProfile(profile_.get()); |
114 theme_service->UseDefaultTheme(); | 234 theme_service->UseDefaultTheme(); |
115 EXPECT_TRUE(theme_service->UsingDefaultTheme()); | 235 EXPECT_TRUE(theme_service->UsingDefaultTheme()); |
116 EXPECT_TRUE(get_theme_supplier(theme_service)); | 236 EXPECT_TRUE(get_theme_supplier(theme_service)); |
117 EXPECT_EQ(get_theme_supplier(theme_service)->get_theme_type(), | 237 EXPECT_EQ(get_theme_supplier(theme_service)->get_theme_type(), |
118 CustomThemeSupplier::MANAGED_USER_THEME); | 238 CustomThemeSupplier::MANAGED_USER_THEME); |
119 } | 239 } |
120 #endif | 240 #endif |
121 | 241 |
122 }; // namespace theme_service_internal | 242 }; // namespace theme_service_internal |
OLD | NEW |