Refactor WebsiteSettings to operate on a SecurityInfo
[chromium-blink-merge.git] / chrome / browser / themes / theme_service_unittest.cc
blob4ea081cef6846114feee6b3fa20293a3dc737f29
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/browser/notification_observer.h"
21 #include "content/public/browser/notification_registrar.h"
22 #include "content/public/test/test_utils.h"
23 #include "extensions/browser/extension_registry.h"
24 #include "extensions/browser/test_extension_registry_observer.h"
25 #include "extensions/browser/uninstall_reason.h"
26 #include "extensions/common/extension.h"
27 #include "testing/gtest/include/gtest/gtest.h"
29 #if defined(ENABLE_SUPERVISED_USERS)
30 #include "chrome/browser/supervised_user/supervised_user_service.h"
31 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
32 #endif
34 using extensions::ExtensionRegistry;
36 namespace theme_service_internal {
38 class ThemeServiceTest : public extensions::ExtensionServiceTestBase {
39 public:
40 ThemeServiceTest() : is_supervised_(false),
41 registry_(NULL) {}
42 ~ThemeServiceTest() override {}
44 // Moves a minimal theme to |temp_dir_path| and unpacks it from that
45 // directory.
46 std::string LoadUnpackedThemeAt(const base::FilePath& temp_dir) {
47 base::FilePath dst_manifest_path = temp_dir.AppendASCII("manifest.json");
48 base::FilePath test_data_dir;
49 EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir));
50 base::FilePath src_manifest_path =
51 test_data_dir.AppendASCII("extensions/theme_minimal/manifest.json");
52 EXPECT_TRUE(base::CopyFile(src_manifest_path, dst_manifest_path));
54 scoped_refptr<extensions::UnpackedInstaller> installer(
55 extensions::UnpackedInstaller::Create(service_));
56 extensions::TestExtensionRegistryObserver observer(
57 ExtensionRegistry::Get(profile()));
58 installer->Load(temp_dir);
59 std::string extension_id = observer.WaitForExtensionLoaded()->id();
61 // Let the ThemeService finish creating the theme pack.
62 base::MessageLoop::current()->RunUntilIdle();
64 return extension_id;
67 // Update the theme with |extension_id|.
68 void UpdateUnpackedTheme(const std::string& extension_id) {
69 const base::FilePath& path =
70 service_->GetInstalledExtension(extension_id)->path();
72 scoped_refptr<extensions::UnpackedInstaller> installer(
73 extensions::UnpackedInstaller::Create(service_));
74 if (service_->IsExtensionEnabled(extension_id)) {
75 extensions::TestExtensionRegistryObserver observer(
76 ExtensionRegistry::Get(profile()));
77 installer->Load(path);
78 observer.WaitForExtensionLoaded();
79 } else {
80 content::WindowedNotificationObserver observer(
81 extensions::NOTIFICATION_EXTENSION_UPDATE_DISABLED,
82 content::Source<Profile>(profile_.get()));
83 installer->Load(path);
84 observer.Wait();
87 // Let the ThemeService finish creating the theme pack.
88 base::MessageLoop::current()->RunUntilIdle();
91 void SetUp() override {
92 extensions::ExtensionServiceTestBase::SetUp();
93 extensions::ExtensionServiceTestBase::ExtensionServiceInitParams params =
94 CreateDefaultInitParams();
95 params.profile_is_supervised = is_supervised_;
96 InitializeExtensionService(params);
97 service_->Init();
98 registry_ = ExtensionRegistry::Get(profile_.get());
99 ASSERT_TRUE(registry_);
102 const CustomThemeSupplier* get_theme_supplier(ThemeService* theme_service) {
103 return theme_service->get_theme_supplier();
106 protected:
107 bool is_supervised_;
108 ExtensionRegistry* registry_;
112 // Installs then uninstalls a theme and makes sure that the ThemeService
113 // reverts to the default theme after the uninstall.
114 TEST_F(ThemeServiceTest, ThemeInstallUninstall) {
115 ThemeService* theme_service =
116 ThemeServiceFactory::GetForProfile(profile_.get());
117 theme_service->UseDefaultTheme();
118 // Let the ThemeService uninstall unused themes.
119 base::MessageLoop::current()->RunUntilIdle();
121 base::ScopedTempDir temp_dir;
122 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
123 const std::string& extension_id = LoadUnpackedThemeAt(temp_dir.path());
124 EXPECT_FALSE(theme_service->UsingDefaultTheme());
125 EXPECT_EQ(extension_id, theme_service->GetThemeID());
127 // Now uninstall the extension, should revert to the default theme.
128 service_->UninstallExtension(extension_id,
129 extensions::UNINSTALL_REASON_FOR_TESTING,
130 base::Bind(&base::DoNothing),
131 NULL);
132 EXPECT_TRUE(theme_service->UsingDefaultTheme());
135 // Test that a theme extension is disabled when not in use. A theme may be
136 // installed but not in use if it there is an infobar to revert to the previous
137 // theme.
138 TEST_F(ThemeServiceTest, DisableUnusedTheme) {
139 ThemeService* theme_service =
140 ThemeServiceFactory::GetForProfile(profile_.get());
141 theme_service->UseDefaultTheme();
142 // Let the ThemeService uninstall unused themes.
143 base::MessageLoop::current()->RunUntilIdle();
145 base::ScopedTempDir temp_dir1;
146 ASSERT_TRUE(temp_dir1.CreateUniqueTempDir());
147 base::ScopedTempDir temp_dir2;
148 ASSERT_TRUE(temp_dir2.CreateUniqueTempDir());
150 // 1) Installing a theme should disable the previously active theme.
151 const std::string& extension1_id = LoadUnpackedThemeAt(temp_dir1.path());
152 EXPECT_FALSE(theme_service->UsingDefaultTheme());
153 EXPECT_EQ(extension1_id, theme_service->GetThemeID());
154 EXPECT_TRUE(service_->IsExtensionEnabled(extension1_id));
156 // Show an infobar to prevent the current theme from being uninstalled.
157 theme_service->OnInfobarDisplayed();
159 const std::string& extension2_id = LoadUnpackedThemeAt(temp_dir2.path());
160 EXPECT_EQ(extension2_id, theme_service->GetThemeID());
161 EXPECT_TRUE(service_->IsExtensionEnabled(extension2_id));
162 EXPECT_TRUE(registry_->GetExtensionById(extension1_id,
163 ExtensionRegistry::DISABLED));
165 // 2) Enabling a disabled theme extension should swap the current theme.
166 service_->EnableExtension(extension1_id);
167 base::MessageLoop::current()->RunUntilIdle();
168 EXPECT_EQ(extension1_id, theme_service->GetThemeID());
169 EXPECT_TRUE(service_->IsExtensionEnabled(extension1_id));
170 EXPECT_TRUE(registry_->GetExtensionById(extension2_id,
171 ExtensionRegistry::DISABLED));
173 // 3) Using SetTheme() with a disabled theme should enable and set the
174 // theme. This is the case when the user reverts to the previous theme
175 // via an infobar.
176 const extensions::Extension* extension2 =
177 service_->GetInstalledExtension(extension2_id);
178 theme_service->SetTheme(extension2);
179 base::MessageLoop::current()->RunUntilIdle();
180 EXPECT_EQ(extension2_id, theme_service->GetThemeID());
181 EXPECT_TRUE(service_->IsExtensionEnabled(extension2_id));
182 EXPECT_TRUE(registry_->GetExtensionById(extension1_id,
183 ExtensionRegistry::DISABLED));
185 // 4) Disabling the current theme extension should revert to the default theme
186 // and uninstall any installed theme extensions.
187 theme_service->OnInfobarDestroyed();
188 EXPECT_FALSE(theme_service->UsingDefaultTheme());
189 service_->DisableExtension(extension2_id,
190 extensions::Extension::DISABLE_USER_ACTION);
191 base::MessageLoop::current()->RunUntilIdle();
192 EXPECT_TRUE(theme_service->UsingDefaultTheme());
193 EXPECT_FALSE(service_->GetInstalledExtension(extension1_id));
194 EXPECT_FALSE(service_->GetInstalledExtension(extension2_id));
197 // Test the ThemeService's behavior when a theme is upgraded.
198 TEST_F(ThemeServiceTest, ThemeUpgrade) {
199 // Setup.
200 ThemeService* theme_service =
201 ThemeServiceFactory::GetForProfile(profile_.get());
202 theme_service->UseDefaultTheme();
203 // Let the ThemeService uninstall unused themes.
204 base::MessageLoop::current()->RunUntilIdle();
206 theme_service->OnInfobarDisplayed();
208 base::ScopedTempDir temp_dir1;
209 ASSERT_TRUE(temp_dir1.CreateUniqueTempDir());
210 base::ScopedTempDir temp_dir2;
211 ASSERT_TRUE(temp_dir2.CreateUniqueTempDir());
213 const std::string& extension1_id = LoadUnpackedThemeAt(temp_dir1.path());
214 const std::string& extension2_id = LoadUnpackedThemeAt(temp_dir2.path());
216 // Test the initial state.
217 EXPECT_TRUE(registry_->GetExtensionById(extension1_id,
218 ExtensionRegistry::DISABLED));
219 EXPECT_EQ(extension2_id, theme_service->GetThemeID());
221 // 1) Upgrading the current theme should not revert to the default theme.
222 content::WindowedNotificationObserver theme_change_observer(
223 chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
224 content::Source<ThemeService>(theme_service));
225 UpdateUnpackedTheme(extension2_id);
227 // The ThemeService should have sent an theme change notification even though
228 // the id of the current theme did not change.
229 theme_change_observer.Wait();
231 EXPECT_EQ(extension2_id, theme_service->GetThemeID());
232 EXPECT_TRUE(registry_->GetExtensionById(extension1_id,
233 ExtensionRegistry::DISABLED));
235 // 2) Upgrading a disabled theme should not change the current theme.
236 UpdateUnpackedTheme(extension1_id);
237 EXPECT_EQ(extension2_id, theme_service->GetThemeID());
238 EXPECT_TRUE(registry_->GetExtensionById(extension1_id,
239 ExtensionRegistry::DISABLED));
242 namespace {
244 // NotificationObserver which emulates an infobar getting destroyed when the
245 // theme changes.
246 class InfobarDestroyerOnThemeChange : public content::NotificationObserver {
247 public:
248 InfobarDestroyerOnThemeChange(Profile* profile)
249 : theme_service_(ThemeServiceFactory::GetForProfile(profile)) {
250 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
251 content::Source<ThemeService>(theme_service_));
254 ~InfobarDestroyerOnThemeChange() override {}
256 private:
257 void Observe(int type,
258 const content::NotificationSource& source,
259 const content::NotificationDetails& details) override {
260 theme_service_->OnInfobarDestroyed();
263 // Not owned.
264 ThemeService* theme_service_;
266 content::NotificationRegistrar registrar_;
268 DISALLOW_COPY_AND_ASSIGN(InfobarDestroyerOnThemeChange);
271 } // namespace
273 // crbug.com/468280
274 TEST_F(ThemeServiceTest, UninstallThemeOnThemeChangeNotification) {
275 // Setup.
276 ThemeService* theme_service =
277 ThemeServiceFactory::GetForProfile(profile_.get());
278 theme_service->UseDefaultTheme();
279 // Let the ThemeService uninstall unused themes.
280 base::MessageLoop::current()->RunUntilIdle();
282 base::ScopedTempDir temp_dir1;
283 ASSERT_TRUE(temp_dir1.CreateUniqueTempDir());
284 base::ScopedTempDir temp_dir2;
285 ASSERT_TRUE(temp_dir2.CreateUniqueTempDir());
287 const std::string& extension1_id = LoadUnpackedThemeAt(temp_dir1.path());
288 ASSERT_EQ(extension1_id, theme_service->GetThemeID());
290 // Show an infobar.
291 theme_service->OnInfobarDisplayed();
293 // Install another theme. Emulate the infobar destroying itself (and
294 // causing unused themes to be uninstalled) as a result of the
295 // NOTIFICATION_BROWSER_THEME_CHANGED notification.
297 InfobarDestroyerOnThemeChange destroyer(profile_.get());
298 const std::string& extension2_id = LoadUnpackedThemeAt(temp_dir2.path());
299 ASSERT_EQ(extension2_id, theme_service->GetThemeID());
300 ASSERT_FALSE(service_->GetInstalledExtension(extension1_id));
303 // Check that it is possible to reinstall extension1.
304 ASSERT_EQ(extension1_id, LoadUnpackedThemeAt(temp_dir1.path()));
305 EXPECT_EQ(extension1_id, theme_service->GetThemeID());
308 #if defined(ENABLE_SUPERVISED_USERS)
309 class ThemeServiceSupervisedUserTest : public ThemeServiceTest {
310 public:
311 ThemeServiceSupervisedUserTest() {}
312 ~ThemeServiceSupervisedUserTest() override {}
314 void SetUp() override {
315 is_supervised_ = true;
316 ThemeServiceTest::SetUp();
320 // Checks that supervised users have their own default theme.
321 TEST_F(ThemeServiceSupervisedUserTest,
322 SupervisedUserThemeReplacesDefaultTheme) {
323 ThemeService* theme_service =
324 ThemeServiceFactory::GetForProfile(profile_.get());
325 theme_service->UseDefaultTheme();
326 EXPECT_TRUE(theme_service->UsingDefaultTheme());
327 EXPECT_TRUE(get_theme_supplier(theme_service));
328 EXPECT_EQ(get_theme_supplier(theme_service)->get_theme_type(),
329 CustomThemeSupplier::SUPERVISED_USER_THEME);
332 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
333 // Checks that supervised users don't use the system theme even if it is the
334 // default. The system theme is only available on Linux.
335 TEST_F(ThemeServiceSupervisedUserTest, SupervisedUserThemeReplacesNativeTheme) {
336 profile_->GetPrefs()->SetBoolean(prefs::kUsesSystemTheme, true);
337 ThemeService* theme_service =
338 ThemeServiceFactory::GetForProfile(profile_.get());
339 theme_service->UseDefaultTheme();
340 EXPECT_TRUE(theme_service->UsingDefaultTheme());
341 EXPECT_TRUE(get_theme_supplier(theme_service));
342 EXPECT_EQ(get_theme_supplier(theme_service)->get_theme_type(),
343 CustomThemeSupplier::SUPERVISED_USER_THEME);
345 #endif // defined(OS_LINUX) && !defined(OS_CHROMEOS)
346 #endif // defined(ENABLE_SUPERVISED_USERS)
348 }; // namespace theme_service_internal