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
3 // found in the LICENSE file.
5 #include "chrome/browser/themes/theme_service.h"
7 #include "base/files/file_util.h"
8 #include "base/path_service.h"
9 #include "chrome/browser/chrome_notification_types.h"
10 #include "chrome/browser/extensions/extension_service.h"
11 #include "chrome/browser/extensions/extension_service_test_base.h"
12 #include "chrome/browser/extensions/unpacked_installer.h"
13 #include "chrome/browser/themes/custom_theme_supplier.h"
14 #include "chrome/browser/themes/theme_service_factory.h"
15 #include "chrome/common/chrome_paths.h"
16 #include "chrome/common/pref_names.h"
17 #include "chrome/test/base/testing_browser_process.h"
18 #include "chrome/test/base/testing_profile.h"
19 #include "chrome/test/base/testing_profile_manager.h"
20 #include "content/public/test/test_utils.h"
21 #include "extensions/browser/extension_registry.h"
22 #include "extensions/browser/test_extension_registry_observer.h"
23 #include "extensions/browser/uninstall_reason.h"
24 #include "extensions/common/extension.h"
25 #include "testing/gtest/include/gtest/gtest.h"
27 #if defined(ENABLE_SUPERVISED_USERS)
28 #include "chrome/browser/supervised_user/supervised_user_service.h"
29 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
32 using extensions::ExtensionRegistry
;
34 namespace theme_service_internal
{
36 class ThemeServiceTest
: public extensions::ExtensionServiceTestBase
{
38 ThemeServiceTest() : is_supervised_(false),
40 ~ThemeServiceTest() override
{}
42 // Moves a minimal theme to |temp_dir_path| and unpacks it from that
44 std::string
LoadUnpackedThemeAt(const base::FilePath
& temp_dir
) {
45 base::FilePath dst_manifest_path
= temp_dir
.AppendASCII("manifest.json");
46 base::FilePath test_data_dir
;
47 EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA
, &test_data_dir
));
48 base::FilePath src_manifest_path
=
49 test_data_dir
.AppendASCII("extensions/theme_minimal/manifest.json");
50 EXPECT_TRUE(base::CopyFile(src_manifest_path
, dst_manifest_path
));
52 scoped_refptr
<extensions::UnpackedInstaller
> installer(
53 extensions::UnpackedInstaller::Create(service_
));
54 extensions::TestExtensionRegistryObserver
observer(
55 ExtensionRegistry::Get(profile()));
56 installer
->Load(temp_dir
);
57 std::string extension_id
= observer
.WaitForExtensionLoaded()->id();
59 // Let the ThemeService finish creating the theme pack.
60 base::MessageLoop::current()->RunUntilIdle();
65 // Update the theme with |extension_id|.
66 void UpdateUnpackedTheme(const std::string
& extension_id
) {
67 const base::FilePath
& path
=
68 service_
->GetInstalledExtension(extension_id
)->path();
70 scoped_refptr
<extensions::UnpackedInstaller
> installer(
71 extensions::UnpackedInstaller::Create(service_
));
72 if (service_
->IsExtensionEnabled(extension_id
)) {
73 extensions::TestExtensionRegistryObserver
observer(
74 ExtensionRegistry::Get(profile()));
75 installer
->Load(path
);
76 observer
.WaitForExtensionLoaded();
78 content::WindowedNotificationObserver
observer(
79 extensions::NOTIFICATION_EXTENSION_UPDATE_DISABLED
,
80 content::Source
<Profile
>(profile_
.get()));
81 installer
->Load(path
);
85 // Let the ThemeService finish creating the theme pack.
86 base::MessageLoop::current()->RunUntilIdle();
89 void SetUp() override
{
90 extensions::ExtensionServiceTestBase::SetUp();
91 extensions::ExtensionServiceTestBase::ExtensionServiceInitParams params
=
92 CreateDefaultInitParams();
93 params
.profile_is_supervised
= is_supervised_
;
94 InitializeExtensionService(params
);
96 registry_
= ExtensionRegistry::Get(profile_
.get());
97 ASSERT_TRUE(registry_
);
100 const CustomThemeSupplier
* get_theme_supplier(ThemeService
* theme_service
) {
101 return theme_service
->get_theme_supplier();
106 ExtensionRegistry
* registry_
;
110 // Installs then uninstalls a theme and makes sure that the ThemeService
111 // reverts to the default theme after the uninstall.
112 TEST_F(ThemeServiceTest
, ThemeInstallUninstall
) {
113 ThemeService
* theme_service
=
114 ThemeServiceFactory::GetForProfile(profile_
.get());
115 theme_service
->UseDefaultTheme();
116 // Let the ThemeService uninstall unused themes.
117 base::MessageLoop::current()->RunUntilIdle();
119 base::ScopedTempDir temp_dir
;
120 ASSERT_TRUE(temp_dir
.CreateUniqueTempDir());
121 const std::string
& extension_id
= LoadUnpackedThemeAt(temp_dir
.path());
122 EXPECT_FALSE(theme_service
->UsingDefaultTheme());
123 EXPECT_EQ(extension_id
, theme_service
->GetThemeID());
125 // Now uninstall the extension, should revert to the default theme.
126 service_
->UninstallExtension(extension_id
,
127 extensions::UNINSTALL_REASON_FOR_TESTING
,
128 base::Bind(&base::DoNothing
),
130 EXPECT_TRUE(theme_service
->UsingDefaultTheme());
133 // Test that a theme extension is disabled when not in use. A theme may be
134 // installed but not in use if it there is an infobar to revert to the previous
136 TEST_F(ThemeServiceTest
, DisableUnusedTheme
) {
137 ThemeService
* theme_service
=
138 ThemeServiceFactory::GetForProfile(profile_
.get());
139 theme_service
->UseDefaultTheme();
140 // Let the ThemeService uninstall unused themes.
141 base::MessageLoop::current()->RunUntilIdle();
143 base::ScopedTempDir temp_dir1
;
144 ASSERT_TRUE(temp_dir1
.CreateUniqueTempDir());
145 base::ScopedTempDir temp_dir2
;
146 ASSERT_TRUE(temp_dir2
.CreateUniqueTempDir());
148 // 1) Installing a theme should disable the previously active theme.
149 const std::string
& extension1_id
= LoadUnpackedThemeAt(temp_dir1
.path());
150 EXPECT_FALSE(theme_service
->UsingDefaultTheme());
151 EXPECT_EQ(extension1_id
, theme_service
->GetThemeID());
152 EXPECT_TRUE(service_
->IsExtensionEnabled(extension1_id
));
154 // Show an infobar to prevent the current theme from being uninstalled.
155 theme_service
->OnInfobarDisplayed();
157 const std::string
& extension2_id
= LoadUnpackedThemeAt(temp_dir2
.path());
158 EXPECT_EQ(extension2_id
, theme_service
->GetThemeID());
159 EXPECT_TRUE(service_
->IsExtensionEnabled(extension2_id
));
160 EXPECT_TRUE(registry_
->GetExtensionById(extension1_id
,
161 ExtensionRegistry::DISABLED
));
163 // 2) Enabling a disabled theme extension should swap the current theme.
164 service_
->EnableExtension(extension1_id
);
165 base::MessageLoop::current()->RunUntilIdle();
166 EXPECT_EQ(extension1_id
, theme_service
->GetThemeID());
167 EXPECT_TRUE(service_
->IsExtensionEnabled(extension1_id
));
168 EXPECT_TRUE(registry_
->GetExtensionById(extension2_id
,
169 ExtensionRegistry::DISABLED
));
171 // 3) Using SetTheme() with a disabled theme should enable and set the
172 // theme. This is the case when the user reverts to the previous theme
174 const extensions::Extension
* extension2
=
175 service_
->GetInstalledExtension(extension2_id
);
176 theme_service
->SetTheme(extension2
);
177 base::MessageLoop::current()->RunUntilIdle();
178 EXPECT_EQ(extension2_id
, theme_service
->GetThemeID());
179 EXPECT_TRUE(service_
->IsExtensionEnabled(extension2_id
));
180 EXPECT_TRUE(registry_
->GetExtensionById(extension1_id
,
181 ExtensionRegistry::DISABLED
));
183 // 4) Disabling the current theme extension should revert to the default theme
184 // and uninstall any installed theme extensions.
185 theme_service
->OnInfobarDestroyed();
186 EXPECT_FALSE(theme_service
->UsingDefaultTheme());
187 service_
->DisableExtension(extension2_id
,
188 extensions::Extension::DISABLE_USER_ACTION
);
189 base::MessageLoop::current()->RunUntilIdle();
190 EXPECT_TRUE(theme_service
->UsingDefaultTheme());
191 EXPECT_FALSE(service_
->GetInstalledExtension(extension1_id
));
192 EXPECT_FALSE(service_
->GetInstalledExtension(extension2_id
));
195 // Test the ThemeService's behavior when a theme is upgraded.
196 TEST_F(ThemeServiceTest
, ThemeUpgrade
) {
198 ThemeService
* theme_service
=
199 ThemeServiceFactory::GetForProfile(profile_
.get());
200 theme_service
->UseDefaultTheme();
201 // Let the ThemeService uninstall unused themes.
202 base::MessageLoop::current()->RunUntilIdle();
204 theme_service
->OnInfobarDisplayed();
206 base::ScopedTempDir temp_dir1
;
207 ASSERT_TRUE(temp_dir1
.CreateUniqueTempDir());
208 base::ScopedTempDir temp_dir2
;
209 ASSERT_TRUE(temp_dir2
.CreateUniqueTempDir());
211 const std::string
& extension1_id
= LoadUnpackedThemeAt(temp_dir1
.path());
212 const std::string
& extension2_id
= LoadUnpackedThemeAt(temp_dir2
.path());
214 // Test the initial state.
215 EXPECT_TRUE(registry_
->GetExtensionById(extension1_id
,
216 ExtensionRegistry::DISABLED
));
217 EXPECT_EQ(extension2_id
, theme_service
->GetThemeID());
219 // 1) Upgrading the current theme should not revert to the default theme.
220 content::WindowedNotificationObserver
theme_change_observer(
221 chrome::NOTIFICATION_BROWSER_THEME_CHANGED
,
222 content::Source
<ThemeService
>(theme_service
));
223 UpdateUnpackedTheme(extension2_id
);
225 // The ThemeService should have sent an theme change notification even though
226 // the id of the current theme did not change.
227 theme_change_observer
.Wait();
229 EXPECT_EQ(extension2_id
, theme_service
->GetThemeID());
230 EXPECT_TRUE(registry_
->GetExtensionById(extension1_id
,
231 ExtensionRegistry::DISABLED
));
233 // 2) Upgrading a disabled theme should not change the current theme.
234 UpdateUnpackedTheme(extension1_id
);
235 EXPECT_EQ(extension2_id
, theme_service
->GetThemeID());
236 EXPECT_TRUE(registry_
->GetExtensionById(extension1_id
,
237 ExtensionRegistry::DISABLED
));
240 #if defined(ENABLE_SUPERVISED_USERS)
241 class ThemeServiceSupervisedUserTest
: public ThemeServiceTest
{
243 ThemeServiceSupervisedUserTest() {}
244 ~ThemeServiceSupervisedUserTest() override
{}
246 void SetUp() override
{
247 is_supervised_
= true;
248 ThemeServiceTest::SetUp();
252 // Checks that supervised users have their own default theme.
253 TEST_F(ThemeServiceSupervisedUserTest
,
254 SupervisedUserThemeReplacesDefaultTheme
) {
255 ThemeService
* theme_service
=
256 ThemeServiceFactory::GetForProfile(profile_
.get());
257 theme_service
->UseDefaultTheme();
258 EXPECT_TRUE(theme_service
->UsingDefaultTheme());
259 EXPECT_TRUE(get_theme_supplier(theme_service
));
260 EXPECT_EQ(get_theme_supplier(theme_service
)->get_theme_type(),
261 CustomThemeSupplier::SUPERVISED_USER_THEME
);
264 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
265 // Checks that supervised users don't use the system theme even if it is the
266 // default. The system theme is only available on Linux.
267 TEST_F(ThemeServiceSupervisedUserTest
, SupervisedUserThemeReplacesNativeTheme
) {
268 profile_
->GetPrefs()->SetBoolean(prefs::kUsesSystemTheme
, true);
269 ThemeService
* theme_service
=
270 ThemeServiceFactory::GetForProfile(profile_
.get());
271 theme_service
->UseDefaultTheme();
272 EXPECT_TRUE(theme_service
->UsingDefaultTheme());
273 EXPECT_TRUE(get_theme_supplier(theme_service
));
274 EXPECT_EQ(get_theme_supplier(theme_service
)->get_theme_type(),
275 CustomThemeSupplier::SUPERVISED_USER_THEME
);
277 #endif // defined(OS_LINUX) && !defined(OS_CHROMEOS)
278 #endif // defined(ENABLE_SUPERVISED_USERS)
280 }; // namespace theme_service_internal