Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / themes / theme_service_unittest.cc
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.
4
5 #include "chrome/browser/themes/theme_service.h"
6
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/supervised_user/supervised_user_service.h"
14 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
15 #include "chrome/browser/themes/custom_theme_supplier.h"
16 #include "chrome/browser/themes/theme_service_factory.h"
17 #include "chrome/common/chrome_paths.h"
18 #include "chrome/common/pref_names.h"
19 #include "chrome/test/base/testing_browser_process.h"
20 #include "chrome/test/base/testing_profile.h"
21 #include "chrome/test/base/testing_profile_manager.h"
22 #include "content/public/test/test_utils.h"
23 #include "extensions/browser/extension_registry.h"
24 #include "extensions/browser/uninstall_reason.h"
25 #include "extensions/common/extension.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27
28 using extensions::ExtensionRegistry;
29
30 namespace theme_service_internal {
31
32 class ThemeServiceTest : public extensions::ExtensionServiceTestBase {
33  public:
34   ThemeServiceTest() : is_supervised_(false),
35                        registry_(NULL) {}
36   virtual ~ThemeServiceTest() {}
37
38   // Moves a minimal theme to |temp_dir_path| and unpacks it from that
39   // directory.
40   std::string LoadUnpackedThemeAt(const base::FilePath& temp_dir) {
41     base::FilePath dst_manifest_path = temp_dir.AppendASCII("manifest.json");
42     base::FilePath test_data_dir;
43     EXPECT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir));
44     base::FilePath src_manifest_path =
45         test_data_dir.AppendASCII("extensions/theme_minimal/manifest.json");
46     EXPECT_TRUE(base::CopyFile(src_manifest_path, dst_manifest_path));
47
48     scoped_refptr<extensions::UnpackedInstaller> installer(
49         extensions::UnpackedInstaller::Create(service_));
50     content::WindowedNotificationObserver observer(
51         extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
52         content::Source<Profile>(profile_.get()));
53     installer->Load(temp_dir);
54     observer.Wait();
55
56     std::string extension_id =
57         content::Details<extensions::Extension>(observer.details())->id();
58
59     // Let the ThemeService finish creating the theme pack.
60     base::MessageLoop::current()->RunUntilIdle();
61
62     return extension_id;
63   }
64
65   // Update the theme with |extension_id|.
66   void UpdateUnpackedTheme(const std::string& extension_id) {
67     int updated_notification =
68         service_->IsExtensionEnabled(extension_id)
69             ? extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED
70             : extensions::NOTIFICATION_EXTENSION_UPDATE_DISABLED;
71
72     const base::FilePath& path =
73         service_->GetInstalledExtension(extension_id)->path();
74
75     scoped_refptr<extensions::UnpackedInstaller> installer(
76         extensions::UnpackedInstaller::Create(service_));
77     content::WindowedNotificationObserver observer(updated_notification,
78         content::Source<Profile>(profile_.get()));
79     installer->Load(path);
80     observer.Wait();
81
82     // Let the ThemeService finish creating the theme pack.
83     base::MessageLoop::current()->RunUntilIdle();
84   }
85
86   virtual void SetUp() {
87     extensions::ExtensionServiceTestBase::SetUp();
88     extensions::ExtensionServiceTestBase::ExtensionServiceInitParams params =
89         CreateDefaultInitParams();
90     params.profile_is_supervised = is_supervised_;
91     InitializeExtensionService(params);
92     service_->Init();
93     registry_ = ExtensionRegistry::Get(profile_.get());
94     ASSERT_TRUE(registry_);
95   }
96
97   const CustomThemeSupplier* get_theme_supplier(ThemeService* theme_service) {
98     return theme_service->get_theme_supplier();
99   }
100
101  protected:
102   bool is_supervised_;
103   ExtensionRegistry* registry_;
104
105 };
106
107 // Installs then uninstalls a theme and makes sure that the ThemeService
108 // reverts to the default theme after the uninstall.
109 TEST_F(ThemeServiceTest, ThemeInstallUninstall) {
110   ThemeService* theme_service =
111       ThemeServiceFactory::GetForProfile(profile_.get());
112   theme_service->UseDefaultTheme();
113   // Let the ThemeService uninstall unused themes.
114   base::MessageLoop::current()->RunUntilIdle();
115
116   base::ScopedTempDir temp_dir;
117   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
118   const std::string& extension_id = LoadUnpackedThemeAt(temp_dir.path());
119   EXPECT_FALSE(theme_service->UsingDefaultTheme());
120   EXPECT_EQ(extension_id, theme_service->GetThemeID());
121
122   // Now uninstall the extension, should revert to the default theme.
123   service_->UninstallExtension(extension_id,
124                                extensions::UNINSTALL_REASON_FOR_TESTING,
125                                base::Bind(&base::DoNothing),
126                                NULL);
127   EXPECT_TRUE(theme_service->UsingDefaultTheme());
128 }
129
130 // Test that a theme extension is disabled when not in use. A theme may be
131 // installed but not in use if it there is an infobar to revert to the previous
132 // theme.
133 TEST_F(ThemeServiceTest, DisableUnusedTheme) {
134   ThemeService* theme_service =
135       ThemeServiceFactory::GetForProfile(profile_.get());
136   theme_service->UseDefaultTheme();
137   // Let the ThemeService uninstall unused themes.
138   base::MessageLoop::current()->RunUntilIdle();
139
140   base::ScopedTempDir temp_dir1;
141   ASSERT_TRUE(temp_dir1.CreateUniqueTempDir());
142   base::ScopedTempDir temp_dir2;
143   ASSERT_TRUE(temp_dir2.CreateUniqueTempDir());
144
145   // 1) Installing a theme should disable the previously active theme.
146   const std::string& extension1_id = LoadUnpackedThemeAt(temp_dir1.path());
147   EXPECT_FALSE(theme_service->UsingDefaultTheme());
148   EXPECT_EQ(extension1_id, theme_service->GetThemeID());
149   EXPECT_TRUE(service_->IsExtensionEnabled(extension1_id));
150
151   // Show an infobar to prevent the current theme from being uninstalled.
152   theme_service->OnInfobarDisplayed();
153
154   const std::string& extension2_id = LoadUnpackedThemeAt(temp_dir2.path());
155   EXPECT_EQ(extension2_id, theme_service->GetThemeID());
156   EXPECT_TRUE(service_->IsExtensionEnabled(extension2_id));
157   EXPECT_TRUE(registry_->GetExtensionById(extension1_id,
158                                           ExtensionRegistry::DISABLED));
159
160   // 2) Enabling a disabled theme extension should swap the current theme.
161   service_->EnableExtension(extension1_id);
162   base::MessageLoop::current()->RunUntilIdle();
163   EXPECT_EQ(extension1_id, theme_service->GetThemeID());
164   EXPECT_TRUE(service_->IsExtensionEnabled(extension1_id));
165   EXPECT_TRUE(registry_->GetExtensionById(extension2_id,
166                                           ExtensionRegistry::DISABLED));
167
168   // 3) Using SetTheme() with a disabled theme should enable and set the
169   // theme. This is the case when the user reverts to the previous theme
170   // via an infobar.
171   const extensions::Extension* extension2 =
172       service_->GetInstalledExtension(extension2_id);
173   theme_service->SetTheme(extension2);
174   base::MessageLoop::current()->RunUntilIdle();
175   EXPECT_EQ(extension2_id, theme_service->GetThemeID());
176   EXPECT_TRUE(service_->IsExtensionEnabled(extension2_id));
177   EXPECT_TRUE(registry_->GetExtensionById(extension1_id,
178                                           ExtensionRegistry::DISABLED));
179
180   // 4) Disabling the current theme extension should revert to the default theme
181   // and uninstall any installed theme extensions.
182   theme_service->OnInfobarDestroyed();
183   EXPECT_FALSE(theme_service->UsingDefaultTheme());
184   service_->DisableExtension(extension2_id,
185       extensions::Extension::DISABLE_USER_ACTION);
186   base::MessageLoop::current()->RunUntilIdle();
187   EXPECT_TRUE(theme_service->UsingDefaultTheme());
188   EXPECT_FALSE(service_->GetInstalledExtension(extension1_id));
189   EXPECT_FALSE(service_->GetInstalledExtension(extension2_id));
190 }
191
192 // Test the ThemeService's behavior when a theme is upgraded.
193 TEST_F(ThemeServiceTest, ThemeUpgrade) {
194   // Setup.
195   ThemeService* theme_service =
196       ThemeServiceFactory::GetForProfile(profile_.get());
197   theme_service->UseDefaultTheme();
198   // Let the ThemeService uninstall unused themes.
199   base::MessageLoop::current()->RunUntilIdle();
200
201   theme_service->OnInfobarDisplayed();
202
203   base::ScopedTempDir temp_dir1;
204   ASSERT_TRUE(temp_dir1.CreateUniqueTempDir());
205   base::ScopedTempDir temp_dir2;
206   ASSERT_TRUE(temp_dir2.CreateUniqueTempDir());
207
208   const std::string& extension1_id = LoadUnpackedThemeAt(temp_dir1.path());
209   const std::string& extension2_id = LoadUnpackedThemeAt(temp_dir2.path());
210
211   // Test the initial state.
212   EXPECT_TRUE(registry_->GetExtensionById(extension1_id,
213                                           ExtensionRegistry::DISABLED));
214   EXPECT_EQ(extension2_id, theme_service->GetThemeID());
215
216   // 1) Upgrading the current theme should not revert to the default theme.
217   content::WindowedNotificationObserver theme_change_observer(
218       chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
219       content::Source<ThemeService>(theme_service));
220   UpdateUnpackedTheme(extension2_id);
221
222   // The ThemeService should have sent an theme change notification even though
223   // the id of the current theme did not change.
224   theme_change_observer.Wait();
225
226   EXPECT_EQ(extension2_id, theme_service->GetThemeID());
227   EXPECT_TRUE(registry_->GetExtensionById(extension1_id,
228                                           ExtensionRegistry::DISABLED));
229
230   // 2) Upgrading a disabled theme should not change the current theme.
231   UpdateUnpackedTheme(extension1_id);
232   EXPECT_EQ(extension2_id, theme_service->GetThemeID());
233   EXPECT_TRUE(registry_->GetExtensionById(extension1_id,
234                                           ExtensionRegistry::DISABLED));
235 }
236
237 class ThemeServiceSupervisedUserTest : public ThemeServiceTest {
238  public:
239   ThemeServiceSupervisedUserTest() {}
240   virtual ~ThemeServiceSupervisedUserTest() {}
241
242   virtual void SetUp() OVERRIDE {
243     is_supervised_ = true;
244     ThemeServiceTest::SetUp();
245   }
246 };
247
248 // Checks that supervised users have their own default theme.
249 TEST_F(ThemeServiceSupervisedUserTest,
250        SupervisedUserThemeReplacesDefaultTheme) {
251   ThemeService* theme_service =
252       ThemeServiceFactory::GetForProfile(profile_.get());
253   theme_service->UseDefaultTheme();
254   EXPECT_TRUE(theme_service->UsingDefaultTheme());
255   EXPECT_TRUE(get_theme_supplier(theme_service));
256   EXPECT_EQ(get_theme_supplier(theme_service)->get_theme_type(),
257             CustomThemeSupplier::SUPERVISED_USER_THEME);
258 }
259
260 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
261 // Checks that supervised users don't use the system theme even if it is the
262 // default. The system theme is only available on Linux.
263 TEST_F(ThemeServiceSupervisedUserTest, SupervisedUserThemeReplacesNativeTheme) {
264   profile_->GetPrefs()->SetBoolean(prefs::kUsesSystemTheme, true);
265   ThemeService* theme_service =
266       ThemeServiceFactory::GetForProfile(profile_.get());
267   theme_service->UseDefaultTheme();
268   EXPECT_TRUE(theme_service->UsingDefaultTheme());
269   EXPECT_TRUE(get_theme_supplier(theme_service));
270   EXPECT_EQ(get_theme_supplier(theme_service)->get_theme_type(),
271             CustomThemeSupplier::SUPERVISED_USER_THEME);
272 }
273 #endif
274
275 }; // namespace theme_service_internal