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