preference_api_prefs_unittest.cc revision a36e5920737c6adbddd3e43b760e5de8431db6e0
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, 156 Extension::ENABLED, 157 Blacklist::NOT_BLACKLISTED, 158 syncer::StringOrdinal()); 159 installed_[i] = true; 160 break; 161 } 162 } 163} 164 165void ExtensionControlledPrefsTest::EnsureExtensionUninstalled( 166 const std::string& extension_id) { 167 Extension* extensions[] = { extension1(), 168 extension2(), 169 extension3(), 170 extension4() }; 171 for (size_t i = 0; i < kNumInstalledExtensions; ++i) { 172 if (extensions[i]->id() == extension_id) { 173 installed_[i] = false; 174 break; 175 } 176 } 177 prefs()->OnExtensionUninstalled(extension_id, Manifest::INTERNAL, false); 178} 179 180class ControlledPrefsInstallOneExtension 181 : public ExtensionControlledPrefsTest { 182 virtual void Initialize() OVERRIDE { 183 InstallExtensionControlledPref(extension1(), 184 kPref1, 185 Value::CreateStringValue("val1")); 186 } 187 virtual void Verify() OVERRIDE { 188 std::string actual = prefs()->pref_service()->GetString(kPref1); 189 EXPECT_EQ("val1", actual); 190 } 191}; 192TEST_F(ControlledPrefsInstallOneExtension, 193 ControlledPrefsInstallOneExtension) { } 194 195// Check that we do not forget persistent incognito values after a reload. 196class ControlledPrefsInstallIncognitoPersistent 197 : public ExtensionControlledPrefsTest { 198 public: 199 virtual void Initialize() OVERRIDE { 200 InstallExtensionControlledPref( 201 extension1(), kPref1, Value::CreateStringValue("val1")); 202 InstallExtensionControlledPrefIncognito( 203 extension1(), kPref1, Value::CreateStringValue("val2")); 204 scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService()); 205 std::string actual = incog_prefs->GetString(kPref1); 206 EXPECT_EQ("val2", actual); 207 } 208 209 virtual void Verify() OVERRIDE { 210 // Main pref service shall see only non-incognito settings. 211 std::string actual = prefs()->pref_service()->GetString(kPref1); 212 EXPECT_EQ("val1", actual); 213 // Incognito pref service shall see incognito values. 214 scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService()); 215 actual = incog_prefs->GetString(kPref1); 216 EXPECT_EQ("val2", actual); 217 } 218}; 219TEST_F(ControlledPrefsInstallIncognitoPersistent, 220 ControlledPrefsInstallIncognitoPersistent) { } 221 222// Check that we forget 'session only' incognito values after a reload. 223class ControlledPrefsInstallIncognitoSessionOnly 224 : public ExtensionControlledPrefsTest { 225 public: 226 ControlledPrefsInstallIncognitoSessionOnly() : iteration_(0) {} 227 228 virtual void Initialize() OVERRIDE { 229 InstallExtensionControlledPref( 230 extension1(), kPref1, Value::CreateStringValue("val1")); 231 InstallExtensionControlledPrefIncognitoSessionOnly( 232 extension1(), kPref1, Value::CreateStringValue("val2")); 233 scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService()); 234 std::string actual = incog_prefs->GetString(kPref1); 235 EXPECT_EQ("val2", actual); 236 } 237 virtual void Verify() OVERRIDE { 238 // Main pref service shall see only non-incognito settings. 239 std::string actual = prefs()->pref_service()->GetString(kPref1); 240 EXPECT_EQ("val1", actual); 241 // Incognito pref service shall see session-only incognito values only 242 // during first run. Once the pref service was reloaded, all values shall be 243 // discarded. 244 scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService()); 245 actual = incog_prefs->GetString(kPref1); 246 if (iteration_ == 0) { 247 EXPECT_EQ("val2", actual); 248 } else { 249 EXPECT_EQ("val1", actual); 250 } 251 ++iteration_; 252 } 253 int iteration_; 254}; 255TEST_F(ControlledPrefsInstallIncognitoSessionOnly, 256 ControlledPrefsInstallIncognitoSessionOnly) { } 257 258class ControlledPrefsUninstallExtension : public ExtensionControlledPrefsTest { 259 virtual void Initialize() OVERRIDE { 260 InstallExtensionControlledPref( 261 extension1(), kPref1, Value::CreateStringValue("val1")); 262 InstallExtensionControlledPref( 263 extension1(), kPref2, Value::CreateStringValue("val2")); 264 ContentSettingsStore* store = prefs()->content_settings_store(); 265 ContentSettingsPattern pattern = 266 ContentSettingsPattern::FromString("http://[*.]example.com"); 267 store->SetExtensionContentSetting(extension1()->id(), 268 pattern, pattern, 269 CONTENT_SETTINGS_TYPE_IMAGES, 270 std::string(), 271 CONTENT_SETTING_BLOCK, 272 kExtensionPrefsScopeRegular); 273 274 UninstallExtension(extension1()->id()); 275 } 276 virtual void Verify() OVERRIDE { 277 EXPECT_FALSE(prefs()->HasPrefForExtension(extension1()->id())); 278 279 std::string actual; 280 actual = prefs()->pref_service()->GetString(kPref1); 281 EXPECT_EQ(kDefaultPref1, actual); 282 actual = prefs()->pref_service()->GetString(kPref2); 283 EXPECT_EQ(kDefaultPref2, actual); 284 } 285}; 286TEST_F(ControlledPrefsUninstallExtension, 287 ControlledPrefsUninstallExtension) { } 288 289// Tests triggering of notifications to registered observers. 290class ControlledPrefsNotifyWhenNeeded : public ExtensionControlledPrefsTest { 291 virtual void Initialize() OVERRIDE { 292 using testing::_; 293 using testing::Mock; 294 using testing::StrEq; 295 296 MockPrefChangeCallback observer(prefs()->pref_service()); 297 PrefChangeRegistrar registrar; 298 registrar.Init(prefs()->pref_service()); 299 registrar.Add(kPref1, observer.GetCallback()); 300 301 MockPrefChangeCallback incognito_observer(prefs()->pref_service()); 302 scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService()); 303 PrefChangeRegistrar incognito_registrar; 304 incognito_registrar.Init(incog_prefs.get()); 305 incognito_registrar.Add(kPref1, incognito_observer.GetCallback()); 306 307 // Write value and check notification. 308 EXPECT_CALL(observer, OnPreferenceChanged(_)); 309 EXPECT_CALL(incognito_observer, OnPreferenceChanged(_)); 310 InstallExtensionControlledPref(extension1(), kPref1, 311 Value::CreateStringValue("https://www.chromium.org")); 312 Mock::VerifyAndClearExpectations(&observer); 313 Mock::VerifyAndClearExpectations(&incognito_observer); 314 315 // Write same value. 316 EXPECT_CALL(observer, OnPreferenceChanged(_)).Times(0); 317 EXPECT_CALL(incognito_observer, OnPreferenceChanged(_)).Times(0); 318 InstallExtensionControlledPref(extension1(), kPref1, 319 Value::CreateStringValue("https://www.chromium.org")); 320 Mock::VerifyAndClearExpectations(&observer); 321 Mock::VerifyAndClearExpectations(&incognito_observer); 322 323 // Change value. 324 EXPECT_CALL(observer, OnPreferenceChanged(_)); 325 EXPECT_CALL(incognito_observer, OnPreferenceChanged(_)); 326 InstallExtensionControlledPref(extension1(), kPref1, 327 Value::CreateStringValue("chrome://newtab")); 328 Mock::VerifyAndClearExpectations(&observer); 329 Mock::VerifyAndClearExpectations(&incognito_observer); 330 // Change only incognito persistent value. 331 EXPECT_CALL(observer, OnPreferenceChanged(_)).Times(0); 332 EXPECT_CALL(incognito_observer, OnPreferenceChanged(_)); 333 InstallExtensionControlledPrefIncognito(extension1(), kPref1, 334 Value::CreateStringValue("chrome://newtab2")); 335 Mock::VerifyAndClearExpectations(&observer); 336 Mock::VerifyAndClearExpectations(&incognito_observer); 337 338 // Change only incognito session-only value. 339 EXPECT_CALL(observer, OnPreferenceChanged(_)).Times(0); 340 EXPECT_CALL(incognito_observer, OnPreferenceChanged(_)); 341 InstallExtensionControlledPrefIncognito(extension1(), kPref1, 342 Value::CreateStringValue("chrome://newtab3")); 343 Mock::VerifyAndClearExpectations(&observer); 344 Mock::VerifyAndClearExpectations(&incognito_observer); 345 346 // Uninstall. 347 EXPECT_CALL(observer, OnPreferenceChanged(_)); 348 EXPECT_CALL(incognito_observer, OnPreferenceChanged(_)); 349 UninstallExtension(extension1()->id()); 350 Mock::VerifyAndClearExpectations(&observer); 351 Mock::VerifyAndClearExpectations(&incognito_observer); 352 353 registrar.Remove(kPref1); 354 incognito_registrar.Remove(kPref1); 355 } 356 virtual void Verify() OVERRIDE { 357 std::string actual = prefs()->pref_service()->GetString(kPref1); 358 EXPECT_EQ(kDefaultPref1, actual); 359 } 360}; 361TEST_F(ControlledPrefsNotifyWhenNeeded, 362 ControlledPrefsNotifyWhenNeeded) { } 363 364// Tests disabling an extension. 365class ControlledPrefsDisableExtension : public ExtensionControlledPrefsTest { 366 virtual void Initialize() OVERRIDE { 367 InstallExtensionControlledPref( 368 extension1(), kPref1, Value::CreateStringValue("val1")); 369 std::string actual = prefs()->pref_service()->GetString(kPref1); 370 EXPECT_EQ("val1", actual); 371 prefs()->SetExtensionState(extension1()->id(), Extension::DISABLED); 372 } 373 virtual void Verify() OVERRIDE { 374 std::string actual = prefs()->pref_service()->GetString(kPref1); 375 EXPECT_EQ(kDefaultPref1, actual); 376 } 377}; 378TEST_F(ControlledPrefsDisableExtension, ControlledPrefsDisableExtension) { } 379 380// Tests disabling and reenabling an extension. 381class ControlledPrefsReenableExtension : public ExtensionControlledPrefsTest { 382 virtual void Initialize() OVERRIDE { 383 InstallExtensionControlledPref( 384 extension1(), kPref1, Value::CreateStringValue("val1")); 385 prefs()->SetExtensionState(extension1()->id(), Extension::DISABLED); 386 prefs()->SetExtensionState(extension1()->id(), Extension::ENABLED); 387 } 388 virtual void Verify() OVERRIDE { 389 std::string actual = prefs()->pref_service()->GetString(kPref1); 390 EXPECT_EQ("val1", actual); 391 } 392}; 393TEST_F(ControlledPrefsDisableExtension, ControlledPrefsReenableExtension) { } 394 395// Mock class to test whether objects are deleted correctly. 396class MockStringValue : public StringValue { 397 public: 398 explicit MockStringValue(const std::string& in_value) 399 : StringValue(in_value) { 400 } 401 virtual ~MockStringValue() { 402 Die(); 403 } 404 MOCK_METHOD0(Die, void()); 405}; 406 407class ControlledPrefsSetExtensionControlledPref 408 : public ExtensionControlledPrefsTest { 409 public: 410 virtual void Initialize() OVERRIDE { 411 MockStringValue* v1 = new MockStringValue("https://www.chromium.org"); 412 MockStringValue* v2 = new MockStringValue("https://www.chromium.org"); 413 MockStringValue* v1i = new MockStringValue("https://www.chromium.org"); 414 MockStringValue* v2i = new MockStringValue("https://www.chromium.org"); 415 // Ownership is taken, value shall not be deleted. 416 EXPECT_CALL(*v1, Die()).Times(0); 417 EXPECT_CALL(*v1i, Die()).Times(0); 418 InstallExtensionControlledPref(extension1(), kPref1, v1); 419 InstallExtensionControlledPrefIncognito(extension1(), kPref1, v1i); 420 testing::Mock::VerifyAndClearExpectations(v1); 421 testing::Mock::VerifyAndClearExpectations(v1i); 422 // Make sure there is no memory leak and both values are deleted. 423 EXPECT_CALL(*v1, Die()).Times(1); 424 EXPECT_CALL(*v1i, Die()).Times(1); 425 EXPECT_CALL(*v2, Die()).Times(1); 426 EXPECT_CALL(*v2i, Die()).Times(1); 427 InstallExtensionControlledPref(extension1(), kPref1, v2); 428 InstallExtensionControlledPrefIncognito(extension1(), kPref1, v2i); 429 prefs_.RecreateExtensionPrefs(); 430 testing::Mock::VerifyAndClearExpectations(v1); 431 testing::Mock::VerifyAndClearExpectations(v1i); 432 testing::Mock::VerifyAndClearExpectations(v2); 433 testing::Mock::VerifyAndClearExpectations(v2i); 434 } 435 436 virtual void Verify() OVERRIDE { 437 } 438}; 439TEST_F(ControlledPrefsSetExtensionControlledPref, 440 ControlledPrefsSetExtensionControlledPref) { } 441 442// Tests that the switches::kDisableExtensions command-line flag prevents 443// extension controlled preferences from being enacted. 444class ControlledPrefsDisableExtensions : public ExtensionControlledPrefsTest { 445 public: 446 ControlledPrefsDisableExtensions() 447 : iteration_(0) {} 448 virtual ~ControlledPrefsDisableExtensions() {} 449 virtual void Initialize() OVERRIDE { 450 InstallExtensionControlledPref( 451 extension1(), kPref1, Value::CreateStringValue("val1")); 452 // This becomes only active in the second verification phase. 453 prefs_.set_extensions_disabled(true); 454 } 455 virtual void Verify() OVERRIDE { 456 std::string actual = prefs()->pref_service()->GetString(kPref1); 457 if (iteration_ == 0) { 458 EXPECT_EQ("val1", actual); 459 ++iteration_; 460 } else { 461 EXPECT_EQ(kDefaultPref1, actual); 462 } 463 } 464 465 private: 466 int iteration_; 467}; 468TEST_F(ControlledPrefsDisableExtensions, ControlledPrefsDisableExtensions) { } 469 470} // namespace extensions 471