preference_api_prefs_unittest.cc revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
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/api/preference/preference_api.h" 12#include "chrome/browser/extensions/extension_prefs.h" 13#include "chrome/browser/extensions/extension_prefs_unittest.h" 14#include "chrome/common/extensions/extension.h" 15#include "chrome/common/extensions/extension_manifest_constants.h" 16#include "chrome/test/base/testing_profile.h" 17#include "components/user_prefs/pref_registry_syncable.h" 18#include "testing/gtest/include/gtest/gtest.h" 19 20using base::Value; 21 22namespace keys = extension_manifest_keys; 23 24namespace extensions { 25 26namespace { 27 28const char kPref1[] = "path1.subpath"; 29const char kPref2[] = "path2"; 30const char kPref3[] = "path3"; 31const char kPref4[] = "path4"; 32 33// Default values in case an extension pref value is not overridden. 34const char kDefaultPref1[] = "default pref 1"; 35const char kDefaultPref2[] = "default pref 2"; 36const char kDefaultPref3[] = "default pref 3"; 37const char kDefaultPref4[] = "default pref 4"; 38 39} // namespace 40 41// An implementation of the PreferenceAPI which returns the ExtensionPrefs and 42// ExtensionPrefValueMap from the TestExtensionPrefs, rather than from a 43// profile (which we don't create in unittests). 44class TestPreferenceAPI : public PreferenceAPIBase { 45 public: 46 explicit TestPreferenceAPI(TestExtensionPrefs* test_extension_prefs) 47 : test_extension_prefs_(test_extension_prefs) { } 48 ~TestPreferenceAPI() { } 49 private: 50 // PreferenceAPIBase implementation. 51 virtual ExtensionPrefs* extension_prefs() OVERRIDE { 52 return test_extension_prefs_->prefs(); 53 } 54 virtual ExtensionPrefValueMap* extension_pref_value_map() OVERRIDE { 55 return test_extension_prefs_->extension_pref_value_map(); 56 } 57 58 TestExtensionPrefs* test_extension_prefs_; 59 60 DISALLOW_COPY_AND_ASSIGN(TestPreferenceAPI); 61}; 62 63class ExtensionControlledPrefsTest : public PrefsPrepopulatedTestBase { 64 public: 65 ExtensionControlledPrefsTest(); 66 virtual ~ExtensionControlledPrefsTest(); 67 68 virtual void RegisterPreferences(user_prefs::PrefRegistrySyncable* registry) 69 OVERRIDE; 70 void InstallExtensionControlledPref(Extension* extension, 71 const std::string& key, 72 base::Value* value); 73 void InstallExtensionControlledPrefIncognito(Extension* extension, 74 const std::string& key, 75 base::Value* value); 76 void InstallExtensionControlledPrefIncognitoSessionOnly( 77 Extension* extension, 78 const std::string& key, 79 base::Value* value); 80 void InstallExtension(Extension* extension); 81 void UninstallExtension(const std::string& extension_id); 82 83 protected: 84 void EnsureExtensionInstalled(Extension* extension); 85 void EnsureExtensionUninstalled(const std::string& extension_id); 86 87 TestPreferenceAPI test_preference_api_; 88}; 89 90ExtensionControlledPrefsTest::ExtensionControlledPrefsTest() 91 : PrefsPrepopulatedTestBase(), 92 test_preference_api_(&prefs_) { 93} 94 95ExtensionControlledPrefsTest::~ExtensionControlledPrefsTest() { 96} 97 98void ExtensionControlledPrefsTest::RegisterPreferences( 99 user_prefs::PrefRegistrySyncable* registry) { 100 registry->RegisterStringPref( 101 kPref1, kDefaultPref1, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 102 registry->RegisterStringPref( 103 kPref2, kDefaultPref2, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 104 registry->RegisterStringPref( 105 kPref3, kDefaultPref3, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 106 registry->RegisterStringPref( 107 kPref4, kDefaultPref4, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 108} 109 110void ExtensionControlledPrefsTest::InstallExtensionControlledPref( 111 Extension* extension, 112 const std::string& key, 113 Value* value) { 114 EnsureExtensionInstalled(extension); 115 test_preference_api_.SetExtensionControlledPref( 116 extension->id(), key, kExtensionPrefsScopeRegular, value); 117} 118 119void ExtensionControlledPrefsTest::InstallExtensionControlledPrefIncognito( 120 Extension* extension, 121 const std::string& key, 122 Value* value) { 123 EnsureExtensionInstalled(extension); 124 test_preference_api_.SetExtensionControlledPref( 125 extension->id(), key, kExtensionPrefsScopeIncognitoPersistent, value); 126} 127 128void ExtensionControlledPrefsTest:: 129InstallExtensionControlledPrefIncognitoSessionOnly(Extension* extension, 130 const std::string& key, 131 Value* value) { 132 EnsureExtensionInstalled(extension); 133 test_preference_api_.SetExtensionControlledPref( 134 extension->id(), key, kExtensionPrefsScopeIncognitoSessionOnly, value); 135} 136 137void ExtensionControlledPrefsTest::InstallExtension(Extension* extension) { 138 EnsureExtensionInstalled(extension); 139} 140 141void ExtensionControlledPrefsTest::UninstallExtension( 142 const std::string& extension_id) { 143 EnsureExtensionUninstalled(extension_id); 144} 145 146void ExtensionControlledPrefsTest::EnsureExtensionInstalled( 147 Extension* extension) { 148 // Install extension the first time a preference is set for it. 149 Extension* extensions[] = { extension1(), 150 extension2(), 151 extension3(), 152 extension4() }; 153 for (size_t i = 0; i < kNumInstalledExtensions; ++i) { 154 if (extension == extensions[i] && !installed_[i]) { 155 prefs()->OnExtensionInstalled(extension, Extension::ENABLED, 156 syncer::StringOrdinal()); 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 Value::CreateStringValue("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, Value::CreateStringValue("val1")); 200 InstallExtensionControlledPrefIncognito( 201 extension1(), kPref1, Value::CreateStringValue("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, Value::CreateStringValue("val1")); 229 InstallExtensionControlledPrefIncognitoSessionOnly( 230 extension1(), kPref1, Value::CreateStringValue("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, Value::CreateStringValue("val1")); 260 InstallExtensionControlledPref( 261 extension1(), kPref2, Value::CreateStringValue("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 Value::CreateStringValue("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 Value::CreateStringValue("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 Value::CreateStringValue("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 Value::CreateStringValue("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 Value::CreateStringValue("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, Value::CreateStringValue("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, Value::CreateStringValue("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 StringValue { 395 public: 396 explicit MockStringValue(const std::string& in_value) 397 : 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, Value::CreateStringValue("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