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