preference_api_prefs_unittest.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
1// Copyright 2013 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 <string> 6 7#include "base/memory/ref_counted.h" 8#include "base/memory/scoped_ptr.h" 9#include "base/prefs/mock_pref_change_callback.h" 10#include "base/values.h" 11#include "chrome/browser/extensions/./extension_prefs_unittest.h" 12#include "chrome/browser/extensions/api/preference/preference_api.h" 13#include "chrome/test/base/testing_profile.h" 14#include "components/user_prefs/pref_registry_syncable.h" 15#include "extensions/browser/extension_prefs.h" 16#include "extensions/common/extension.h" 17#include "testing/gtest/include/gtest/gtest.h" 18 19using base::Value; 20 21namespace extensions { 22 23namespace { 24 25const char kPref1[] = "path1.subpath"; 26const char kPref2[] = "path2"; 27const char kPref3[] = "path3"; 28const char kPref4[] = "path4"; 29 30// Default values in case an extension pref value is not overridden. 31const char kDefaultPref1[] = "default pref 1"; 32const char kDefaultPref2[] = "default pref 2"; 33const char kDefaultPref3[] = "default pref 3"; 34const char kDefaultPref4[] = "default pref 4"; 35 36} // namespace 37 38// An implementation of the PreferenceAPI which returns the ExtensionPrefs and 39// ExtensionPrefValueMap from the TestExtensionPrefs, rather than from a 40// profile (which we don't create in unittests). 41class TestPreferenceAPI : public PreferenceAPIBase { 42 public: 43 explicit TestPreferenceAPI(TestExtensionPrefs* test_extension_prefs) 44 : test_extension_prefs_(test_extension_prefs) { } 45 ~TestPreferenceAPI() { } 46 private: 47 // PreferenceAPIBase implementation. 48 virtual ExtensionPrefs* extension_prefs() OVERRIDE { 49 return test_extension_prefs_->prefs(); 50 } 51 virtual ExtensionPrefValueMap* extension_pref_value_map() OVERRIDE { 52 return test_extension_prefs_->extension_pref_value_map(); 53 } 54 55 TestExtensionPrefs* test_extension_prefs_; 56 57 DISALLOW_COPY_AND_ASSIGN(TestPreferenceAPI); 58}; 59 60class ExtensionControlledPrefsTest : public PrefsPrepopulatedTestBase { 61 public: 62 ExtensionControlledPrefsTest(); 63 virtual ~ExtensionControlledPrefsTest(); 64 65 virtual void RegisterPreferences(user_prefs::PrefRegistrySyncable* registry) 66 OVERRIDE; 67 void InstallExtensionControlledPref(Extension* extension, 68 const std::string& key, 69 base::Value* value); 70 void InstallExtensionControlledPrefIncognito(Extension* extension, 71 const std::string& key, 72 base::Value* value); 73 void InstallExtensionControlledPrefIncognitoSessionOnly( 74 Extension* extension, 75 const std::string& key, 76 base::Value* value); 77 void InstallExtension(Extension* extension); 78 void UninstallExtension(const std::string& extension_id); 79 80 protected: 81 void EnsureExtensionInstalled(Extension* extension); 82 void EnsureExtensionUninstalled(const std::string& extension_id); 83 84 TestPreferenceAPI test_preference_api_; 85}; 86 87ExtensionControlledPrefsTest::ExtensionControlledPrefsTest() 88 : PrefsPrepopulatedTestBase(), 89 test_preference_api_(&prefs_) { 90} 91 92ExtensionControlledPrefsTest::~ExtensionControlledPrefsTest() { 93} 94 95void ExtensionControlledPrefsTest::RegisterPreferences( 96 user_prefs::PrefRegistrySyncable* registry) { 97 registry->RegisterStringPref( 98 kPref1, kDefaultPref1, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 99 registry->RegisterStringPref( 100 kPref2, kDefaultPref2, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 101 registry->RegisterStringPref( 102 kPref3, kDefaultPref3, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 103 registry->RegisterStringPref( 104 kPref4, kDefaultPref4, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 105} 106 107void ExtensionControlledPrefsTest::InstallExtensionControlledPref( 108 Extension* extension, 109 const std::string& key, 110 base::Value* value) { 111 EnsureExtensionInstalled(extension); 112 test_preference_api_.SetExtensionControlledPref( 113 extension->id(), key, kExtensionPrefsScopeRegular, value); 114} 115 116void ExtensionControlledPrefsTest::InstallExtensionControlledPrefIncognito( 117 Extension* extension, 118 const std::string& key, 119 base::Value* value) { 120 EnsureExtensionInstalled(extension); 121 test_preference_api_.SetExtensionControlledPref( 122 extension->id(), key, kExtensionPrefsScopeIncognitoPersistent, value); 123} 124 125void ExtensionControlledPrefsTest:: 126InstallExtensionControlledPrefIncognitoSessionOnly(Extension* extension, 127 const std::string& key, 128 base::Value* value) { 129 EnsureExtensionInstalled(extension); 130 test_preference_api_.SetExtensionControlledPref( 131 extension->id(), key, kExtensionPrefsScopeIncognitoSessionOnly, value); 132} 133 134void ExtensionControlledPrefsTest::InstallExtension(Extension* extension) { 135 EnsureExtensionInstalled(extension); 136} 137 138void ExtensionControlledPrefsTest::UninstallExtension( 139 const std::string& extension_id) { 140 EnsureExtensionUninstalled(extension_id); 141} 142 143void ExtensionControlledPrefsTest::EnsureExtensionInstalled( 144 Extension* extension) { 145 // Install extension the first time a preference is set for it. 146 Extension* extensions[] = { extension1(), 147 extension2(), 148 extension3(), 149 extension4() }; 150 for (size_t i = 0; i < kNumInstalledExtensions; ++i) { 151 if (extension == extensions[i] && !installed_[i]) { 152 prefs()->OnExtensionInstalled(extension, 153 Extension::ENABLED, 154 false, 155 syncer::StringOrdinal()); 156 prefs()->SetIsIncognitoEnabled(extension->id(), true); 157 installed_[i] = true; 158 break; 159 } 160 } 161} 162 163void ExtensionControlledPrefsTest::EnsureExtensionUninstalled( 164 const std::string& extension_id) { 165 Extension* extensions[] = { extension1(), 166 extension2(), 167 extension3(), 168 extension4() }; 169 for (size_t i = 0; i < kNumInstalledExtensions; ++i) { 170 if (extensions[i]->id() == extension_id) { 171 installed_[i] = false; 172 break; 173 } 174 } 175 prefs()->OnExtensionUninstalled(extension_id, Manifest::INTERNAL, false); 176} 177 178class ControlledPrefsInstallOneExtension 179 : public ExtensionControlledPrefsTest { 180 virtual void Initialize() OVERRIDE { 181 InstallExtensionControlledPref(extension1(), 182 kPref1, 183 new base::StringValue("val1")); 184 } 185 virtual void Verify() OVERRIDE { 186 std::string actual = prefs()->pref_service()->GetString(kPref1); 187 EXPECT_EQ("val1", actual); 188 } 189}; 190TEST_F(ControlledPrefsInstallOneExtension, 191 ControlledPrefsInstallOneExtension) { } 192 193// Check that we do not forget persistent incognito values after a reload. 194class ControlledPrefsInstallIncognitoPersistent 195 : public ExtensionControlledPrefsTest { 196 public: 197 virtual void Initialize() OVERRIDE { 198 InstallExtensionControlledPref( 199 extension1(), kPref1, new base::StringValue("val1")); 200 InstallExtensionControlledPrefIncognito( 201 extension1(), kPref1, new base::StringValue("val2")); 202 scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService()); 203 std::string actual = incog_prefs->GetString(kPref1); 204 EXPECT_EQ("val2", actual); 205 } 206 207 virtual void Verify() OVERRIDE { 208 // Main pref service shall see only non-incognito settings. 209 std::string actual = prefs()->pref_service()->GetString(kPref1); 210 EXPECT_EQ("val1", actual); 211 // Incognito pref service shall see incognito values. 212 scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService()); 213 actual = incog_prefs->GetString(kPref1); 214 EXPECT_EQ("val2", actual); 215 } 216}; 217TEST_F(ControlledPrefsInstallIncognitoPersistent, 218 ControlledPrefsInstallIncognitoPersistent) { } 219 220// Check that we forget 'session only' incognito values after a reload. 221class ControlledPrefsInstallIncognitoSessionOnly 222 : public ExtensionControlledPrefsTest { 223 public: 224 ControlledPrefsInstallIncognitoSessionOnly() : iteration_(0) {} 225 226 virtual void Initialize() OVERRIDE { 227 InstallExtensionControlledPref( 228 extension1(), kPref1, new base::StringValue("val1")); 229 InstallExtensionControlledPrefIncognitoSessionOnly( 230 extension1(), kPref1, new base::StringValue("val2")); 231 scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService()); 232 std::string actual = incog_prefs->GetString(kPref1); 233 EXPECT_EQ("val2", actual); 234 } 235 virtual void Verify() OVERRIDE { 236 // Main pref service shall see only non-incognito settings. 237 std::string actual = prefs()->pref_service()->GetString(kPref1); 238 EXPECT_EQ("val1", actual); 239 // Incognito pref service shall see session-only incognito values only 240 // during first run. Once the pref service was reloaded, all values shall be 241 // discarded. 242 scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService()); 243 actual = incog_prefs->GetString(kPref1); 244 if (iteration_ == 0) { 245 EXPECT_EQ("val2", actual); 246 } else { 247 EXPECT_EQ("val1", actual); 248 } 249 ++iteration_; 250 } 251 int iteration_; 252}; 253TEST_F(ControlledPrefsInstallIncognitoSessionOnly, 254 ControlledPrefsInstallIncognitoSessionOnly) { } 255 256class ControlledPrefsUninstallExtension : public ExtensionControlledPrefsTest { 257 virtual void Initialize() OVERRIDE { 258 InstallExtensionControlledPref( 259 extension1(), kPref1, new base::StringValue("val1")); 260 InstallExtensionControlledPref( 261 extension1(), kPref2, new base::StringValue("val2")); 262 ContentSettingsStore* store = prefs()->content_settings_store(); 263 ContentSettingsPattern pattern = 264 ContentSettingsPattern::FromString("http://[*.]example.com"); 265 store->SetExtensionContentSetting(extension1()->id(), 266 pattern, pattern, 267 CONTENT_SETTINGS_TYPE_IMAGES, 268 std::string(), 269 CONTENT_SETTING_BLOCK, 270 kExtensionPrefsScopeRegular); 271 272 UninstallExtension(extension1()->id()); 273 } 274 virtual void Verify() OVERRIDE { 275 EXPECT_FALSE(prefs()->HasPrefForExtension(extension1()->id())); 276 277 std::string actual; 278 actual = prefs()->pref_service()->GetString(kPref1); 279 EXPECT_EQ(kDefaultPref1, actual); 280 actual = prefs()->pref_service()->GetString(kPref2); 281 EXPECT_EQ(kDefaultPref2, actual); 282 } 283}; 284TEST_F(ControlledPrefsUninstallExtension, 285 ControlledPrefsUninstallExtension) { } 286 287// Tests triggering of notifications to registered observers. 288class ControlledPrefsNotifyWhenNeeded : public ExtensionControlledPrefsTest { 289 virtual void Initialize() OVERRIDE { 290 using testing::_; 291 using testing::Mock; 292 using testing::StrEq; 293 294 MockPrefChangeCallback observer(prefs()->pref_service()); 295 PrefChangeRegistrar registrar; 296 registrar.Init(prefs()->pref_service()); 297 registrar.Add(kPref1, observer.GetCallback()); 298 299 MockPrefChangeCallback incognito_observer(prefs()->pref_service()); 300 scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService()); 301 PrefChangeRegistrar incognito_registrar; 302 incognito_registrar.Init(incog_prefs.get()); 303 incognito_registrar.Add(kPref1, incognito_observer.GetCallback()); 304 305 // Write value and check notification. 306 EXPECT_CALL(observer, OnPreferenceChanged(_)); 307 EXPECT_CALL(incognito_observer, OnPreferenceChanged(_)); 308 InstallExtensionControlledPref(extension1(), kPref1, 309 new base::StringValue("https://www.chromium.org")); 310 Mock::VerifyAndClearExpectations(&observer); 311 Mock::VerifyAndClearExpectations(&incognito_observer); 312 313 // Write same value. 314 EXPECT_CALL(observer, OnPreferenceChanged(_)).Times(0); 315 EXPECT_CALL(incognito_observer, OnPreferenceChanged(_)).Times(0); 316 InstallExtensionControlledPref(extension1(), kPref1, 317 new base::StringValue("https://www.chromium.org")); 318 Mock::VerifyAndClearExpectations(&observer); 319 Mock::VerifyAndClearExpectations(&incognito_observer); 320 321 // Change value. 322 EXPECT_CALL(observer, OnPreferenceChanged(_)); 323 EXPECT_CALL(incognito_observer, OnPreferenceChanged(_)); 324 InstallExtensionControlledPref(extension1(), kPref1, 325 new base::StringValue("chrome://newtab")); 326 Mock::VerifyAndClearExpectations(&observer); 327 Mock::VerifyAndClearExpectations(&incognito_observer); 328 // Change only incognito persistent value. 329 EXPECT_CALL(observer, OnPreferenceChanged(_)).Times(0); 330 EXPECT_CALL(incognito_observer, OnPreferenceChanged(_)); 331 InstallExtensionControlledPrefIncognito(extension1(), kPref1, 332 new base::StringValue("chrome://newtab2")); 333 Mock::VerifyAndClearExpectations(&observer); 334 Mock::VerifyAndClearExpectations(&incognito_observer); 335 336 // Change only incognito session-only value. 337 EXPECT_CALL(observer, OnPreferenceChanged(_)).Times(0); 338 EXPECT_CALL(incognito_observer, OnPreferenceChanged(_)); 339 InstallExtensionControlledPrefIncognito(extension1(), kPref1, 340 new base::StringValue("chrome://newtab3")); 341 Mock::VerifyAndClearExpectations(&observer); 342 Mock::VerifyAndClearExpectations(&incognito_observer); 343 344 // Uninstall. 345 EXPECT_CALL(observer, OnPreferenceChanged(_)); 346 EXPECT_CALL(incognito_observer, OnPreferenceChanged(_)); 347 UninstallExtension(extension1()->id()); 348 Mock::VerifyAndClearExpectations(&observer); 349 Mock::VerifyAndClearExpectations(&incognito_observer); 350 351 registrar.Remove(kPref1); 352 incognito_registrar.Remove(kPref1); 353 } 354 virtual void Verify() OVERRIDE { 355 std::string actual = prefs()->pref_service()->GetString(kPref1); 356 EXPECT_EQ(kDefaultPref1, actual); 357 } 358}; 359TEST_F(ControlledPrefsNotifyWhenNeeded, 360 ControlledPrefsNotifyWhenNeeded) { } 361 362// Tests disabling an extension. 363class ControlledPrefsDisableExtension : public ExtensionControlledPrefsTest { 364 virtual void Initialize() OVERRIDE { 365 InstallExtensionControlledPref( 366 extension1(), kPref1, new base::StringValue("val1")); 367 std::string actual = prefs()->pref_service()->GetString(kPref1); 368 EXPECT_EQ("val1", actual); 369 prefs()->SetExtensionState(extension1()->id(), Extension::DISABLED); 370 } 371 virtual void Verify() OVERRIDE { 372 std::string actual = prefs()->pref_service()->GetString(kPref1); 373 EXPECT_EQ(kDefaultPref1, actual); 374 } 375}; 376TEST_F(ControlledPrefsDisableExtension, ControlledPrefsDisableExtension) { } 377 378// Tests disabling and reenabling an extension. 379class ControlledPrefsReenableExtension : public ExtensionControlledPrefsTest { 380 virtual void Initialize() OVERRIDE { 381 InstallExtensionControlledPref( 382 extension1(), kPref1, new base::StringValue("val1")); 383 prefs()->SetExtensionState(extension1()->id(), Extension::DISABLED); 384 prefs()->SetExtensionState(extension1()->id(), Extension::ENABLED); 385 } 386 virtual void Verify() OVERRIDE { 387 std::string actual = prefs()->pref_service()->GetString(kPref1); 388 EXPECT_EQ("val1", actual); 389 } 390}; 391TEST_F(ControlledPrefsDisableExtension, ControlledPrefsReenableExtension) { } 392 393// Mock class to test whether objects are deleted correctly. 394class MockStringValue : public base::StringValue { 395 public: 396 explicit MockStringValue(const std::string& in_value) 397 : base::StringValue(in_value) { 398 } 399 virtual ~MockStringValue() { 400 Die(); 401 } 402 MOCK_METHOD0(Die, void()); 403}; 404 405class ControlledPrefsSetExtensionControlledPref 406 : public ExtensionControlledPrefsTest { 407 public: 408 virtual void Initialize() OVERRIDE { 409 MockStringValue* v1 = new MockStringValue("https://www.chromium.org"); 410 MockStringValue* v2 = new MockStringValue("https://www.chromium.org"); 411 MockStringValue* v1i = new MockStringValue("https://www.chromium.org"); 412 MockStringValue* v2i = new MockStringValue("https://www.chromium.org"); 413 // Ownership is taken, value shall not be deleted. 414 EXPECT_CALL(*v1, Die()).Times(0); 415 EXPECT_CALL(*v1i, Die()).Times(0); 416 InstallExtensionControlledPref(extension1(), kPref1, v1); 417 InstallExtensionControlledPrefIncognito(extension1(), kPref1, v1i); 418 testing::Mock::VerifyAndClearExpectations(v1); 419 testing::Mock::VerifyAndClearExpectations(v1i); 420 // Make sure there is no memory leak and both values are deleted. 421 EXPECT_CALL(*v1, Die()).Times(1); 422 EXPECT_CALL(*v1i, Die()).Times(1); 423 EXPECT_CALL(*v2, Die()).Times(1); 424 EXPECT_CALL(*v2i, Die()).Times(1); 425 InstallExtensionControlledPref(extension1(), kPref1, v2); 426 InstallExtensionControlledPrefIncognito(extension1(), kPref1, v2i); 427 prefs_.RecreateExtensionPrefs(); 428 testing::Mock::VerifyAndClearExpectations(v1); 429 testing::Mock::VerifyAndClearExpectations(v1i); 430 testing::Mock::VerifyAndClearExpectations(v2); 431 testing::Mock::VerifyAndClearExpectations(v2i); 432 } 433 434 virtual void Verify() OVERRIDE { 435 } 436}; 437TEST_F(ControlledPrefsSetExtensionControlledPref, 438 ControlledPrefsSetExtensionControlledPref) { } 439 440// Tests that the switches::kDisableExtensions command-line flag prevents 441// extension controlled preferences from being enacted. 442class ControlledPrefsDisableExtensions : public ExtensionControlledPrefsTest { 443 public: 444 ControlledPrefsDisableExtensions() 445 : iteration_(0) {} 446 virtual ~ControlledPrefsDisableExtensions() {} 447 virtual void Initialize() OVERRIDE { 448 InstallExtensionControlledPref( 449 extension1(), kPref1, new base::StringValue("val1")); 450 // This becomes only active in the second verification phase. 451 prefs_.set_extensions_disabled(true); 452 } 453 virtual void Verify() OVERRIDE { 454 std::string actual = prefs()->pref_service()->GetString(kPref1); 455 if (iteration_ == 0) { 456 EXPECT_EQ("val1", actual); 457 ++iteration_; 458 } else { 459 EXPECT_EQ(kDefaultPref1, actual); 460 } 461 } 462 463 private: 464 int iteration_; 465}; 466TEST_F(ControlledPrefsDisableExtensions, ControlledPrefsDisableExtensions) { } 467 468} // namespace extensions 469