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