1 // Copyright (c) 2011 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 "base/memory/scoped_ptr.h" 6 #include "base/values.h" 7 #include "chrome/browser/prefs/scoped_user_pref_update.h" 8 #include "chrome/browser/sync/glue/preference_model_associator.h" 9 #include "chrome/common/pref_names.h" 10 #include "chrome/test/testing_profile.h" 11 #include "testing/gtest/include/gtest/gtest.h" 12 13 using browser_sync::PreferenceModelAssociator; 14 15 class AbstractPreferenceMergeTest : public testing::Test { 16 protected: 17 virtual void SetUp() { 18 pref_service_ = profile_.GetPrefs(); 19 } 20 21 void SetContentPattern(DictionaryValue* patterns_dict, 22 const std::string& expression, 23 const std::string& content_type, 24 int setting) { 25 DictionaryValue* expression_dict; 26 bool found = 27 patterns_dict->GetDictionaryWithoutPathExpansion(expression, 28 &expression_dict); 29 if (!found) { 30 expression_dict = new DictionaryValue; 31 patterns_dict->SetWithoutPathExpansion(expression, expression_dict); 32 } 33 expression_dict->SetWithoutPathExpansion( 34 content_type, 35 Value::CreateIntegerValue(setting)); 36 } 37 38 void SetPrefToEmpty(const std::string& pref_name) { 39 scoped_ptr<Value> empty_value; 40 const PrefService::Preference* pref = 41 pref_service_->FindPreference(pref_name.c_str()); 42 ASSERT_TRUE(pref); 43 Value::ValueType type = pref->GetType(); 44 if (type == Value::TYPE_DICTIONARY) 45 empty_value.reset(new DictionaryValue); 46 else if (type == Value::TYPE_LIST) 47 empty_value.reset(new ListValue); 48 else 49 FAIL(); 50 pref_service_->Set(pref_name.c_str(), *empty_value); 51 } 52 53 TestingProfile profile_; 54 PrefService* pref_service_; 55 }; 56 57 class ListPreferenceMergeTest : public AbstractPreferenceMergeTest { 58 protected: 59 ListPreferenceMergeTest() : 60 server_url0_("http://example.com/server0"), 61 server_url1_("http://example.com/server1"), 62 local_url0_("http://example.com/local0"), 63 local_url1_("http://example.com/local1") {} 64 65 virtual void SetUp() { 66 AbstractPreferenceMergeTest::SetUp(); 67 server_url_list_.Append(Value::CreateStringValue(server_url0_)); 68 server_url_list_.Append(Value::CreateStringValue(server_url1_)); 69 } 70 71 std::string server_url0_; 72 std::string server_url1_; 73 std::string local_url0_; 74 std::string local_url1_; 75 ListValue server_url_list_; 76 }; 77 78 TEST_F(ListPreferenceMergeTest, NotListOrDictionary) { 79 pref_service_->SetString(prefs::kHomePage, local_url0_); 80 const PrefService::Preference* pref = 81 pref_service_->FindPreference(prefs::kHomePage); 82 scoped_ptr<Value> server_value(Value::CreateStringValue(server_url0_)); 83 scoped_ptr<Value> merged_value( 84 PreferenceModelAssociator::MergePreference(*pref, *server_value)); 85 EXPECT_TRUE(merged_value->Equals(server_value.get())); 86 } 87 88 TEST_F(ListPreferenceMergeTest, LocalEmpty) { 89 SetPrefToEmpty(prefs::kURLsToRestoreOnStartup); 90 const PrefService::Preference* pref = 91 pref_service_->FindPreference(prefs::kURLsToRestoreOnStartup); 92 scoped_ptr<Value> merged_value( 93 PreferenceModelAssociator::MergePreference(*pref, server_url_list_)); 94 EXPECT_TRUE(merged_value->Equals(&server_url_list_)); 95 } 96 97 TEST_F(ListPreferenceMergeTest, ServerNull) { 98 scoped_ptr<Value> null_value(Value::CreateNullValue()); 99 { 100 ListPrefUpdate update(pref_service_, prefs::kURLsToRestoreOnStartup); 101 ListValue* local_list_value = update.Get(); 102 local_list_value->Append(Value::CreateStringValue(local_url0_)); 103 } 104 105 const PrefService::Preference* pref = 106 pref_service_->FindPreference(prefs::kURLsToRestoreOnStartup); 107 scoped_ptr<Value> merged_value( 108 PreferenceModelAssociator::MergePreference(*pref, *null_value)); 109 const ListValue* local_list_value = 110 pref_service_->GetList(prefs::kURLsToRestoreOnStartup); 111 EXPECT_TRUE(merged_value->Equals(local_list_value)); 112 } 113 114 TEST_F(ListPreferenceMergeTest, ServerEmpty) { 115 scoped_ptr<Value> empty_value(new ListValue); 116 { 117 ListPrefUpdate update(pref_service_, prefs::kURLsToRestoreOnStartup); 118 ListValue* local_list_value = update.Get(); 119 local_list_value->Append(Value::CreateStringValue(local_url0_)); 120 } 121 122 const PrefService::Preference* pref = 123 pref_service_->FindPreference(prefs::kURLsToRestoreOnStartup); 124 scoped_ptr<Value> merged_value( 125 PreferenceModelAssociator::MergePreference(*pref, *empty_value)); 126 const ListValue* local_list_value = 127 pref_service_->GetList(prefs::kURLsToRestoreOnStartup); 128 EXPECT_TRUE(merged_value->Equals(local_list_value)); 129 } 130 131 TEST_F(ListPreferenceMergeTest, Merge) { 132 { 133 ListPrefUpdate update(pref_service_, prefs::kURLsToRestoreOnStartup); 134 ListValue* local_list_value = update.Get(); 135 local_list_value->Append(Value::CreateStringValue(local_url0_)); 136 local_list_value->Append(Value::CreateStringValue(local_url1_)); 137 } 138 139 const PrefService::Preference* pref = 140 pref_service_->FindPreference(prefs::kURLsToRestoreOnStartup); 141 scoped_ptr<Value> merged_value( 142 PreferenceModelAssociator::MergePreference(*pref, server_url_list_)); 143 144 ListValue expected; 145 expected.Append(Value::CreateStringValue(server_url0_)); 146 expected.Append(Value::CreateStringValue(server_url1_)); 147 expected.Append(Value::CreateStringValue(local_url0_)); 148 expected.Append(Value::CreateStringValue(local_url1_)); 149 EXPECT_TRUE(merged_value->Equals(&expected)); 150 } 151 152 TEST_F(ListPreferenceMergeTest, Duplicates) { 153 { 154 ListPrefUpdate update(pref_service_, prefs::kURLsToRestoreOnStartup); 155 ListValue* local_list_value = update.Get(); 156 local_list_value->Append(Value::CreateStringValue(local_url0_)); 157 local_list_value->Append(Value::CreateStringValue(server_url0_)); 158 local_list_value->Append(Value::CreateStringValue(server_url1_)); 159 } 160 161 const PrefService::Preference* pref = 162 pref_service_->FindPreference(prefs::kURLsToRestoreOnStartup); 163 scoped_ptr<Value> merged_value( 164 PreferenceModelAssociator::MergePreference(*pref, server_url_list_)); 165 166 ListValue expected; 167 expected.Append(Value::CreateStringValue(server_url0_)); 168 expected.Append(Value::CreateStringValue(server_url1_)); 169 expected.Append(Value::CreateStringValue(local_url0_)); 170 EXPECT_TRUE(merged_value->Equals(&expected)); 171 } 172 173 TEST_F(ListPreferenceMergeTest, Equals) { 174 { 175 ListPrefUpdate update(pref_service_, prefs::kURLsToRestoreOnStartup); 176 ListValue* local_list_value = update.Get(); 177 local_list_value->Append(Value::CreateStringValue(server_url0_)); 178 local_list_value->Append(Value::CreateStringValue(server_url1_)); 179 } 180 181 scoped_ptr<Value> original(server_url_list_.DeepCopy()); 182 const PrefService::Preference* pref = 183 pref_service_->FindPreference(prefs::kURLsToRestoreOnStartup); 184 scoped_ptr<Value> merged_value( 185 PreferenceModelAssociator::MergePreference(*pref, server_url_list_)); 186 EXPECT_TRUE(merged_value->Equals(original.get())); 187 } 188 189 class DictionaryPreferenceMergeTest : public AbstractPreferenceMergeTest { 190 protected: 191 DictionaryPreferenceMergeTest() : 192 expression0_("expression0"), 193 expression1_("expression1"), 194 expression2_("expression2"), 195 content_type0_("content_type0"), 196 content_type1_("content_type1") {} 197 198 virtual void SetUp() { 199 AbstractPreferenceMergeTest::SetUp(); 200 SetContentPattern(&server_patterns_, expression0_, content_type0_, 1); 201 SetContentPattern(&server_patterns_, expression0_, content_type1_, 2); 202 SetContentPattern(&server_patterns_, expression1_, content_type0_, 1); 203 } 204 205 std::string expression0_; 206 std::string expression1_; 207 std::string expression2_; 208 std::string content_type0_; 209 std::string content_type1_; 210 DictionaryValue server_patterns_; 211 }; 212 213 TEST_F(DictionaryPreferenceMergeTest, LocalEmpty) { 214 SetPrefToEmpty(prefs::kContentSettingsPatterns); 215 const PrefService::Preference* pref = 216 pref_service_->FindPreference(prefs::kContentSettingsPatterns); 217 scoped_ptr<Value> merged_value( 218 PreferenceModelAssociator::MergePreference(*pref, server_patterns_)); 219 EXPECT_TRUE(merged_value->Equals(&server_patterns_)); 220 } 221 222 TEST_F(DictionaryPreferenceMergeTest, ServerNull) { 223 scoped_ptr<Value> null_value(Value::CreateNullValue()); 224 { 225 DictionaryPrefUpdate update(pref_service_, prefs::kContentSettingsPatterns); 226 DictionaryValue* local_dict_value = update.Get(); 227 SetContentPattern(local_dict_value, expression2_, content_type0_, 1); 228 } 229 230 const PrefService::Preference* pref = 231 pref_service_->FindPreference(prefs::kContentSettingsPatterns); 232 scoped_ptr<Value> merged_value( 233 PreferenceModelAssociator::MergePreference(*pref, *null_value)); 234 const DictionaryValue* local_dict_value = 235 pref_service_->GetDictionary(prefs::kContentSettingsPatterns); 236 EXPECT_TRUE(merged_value->Equals(local_dict_value)); 237 } 238 239 TEST_F(DictionaryPreferenceMergeTest, ServerEmpty) { 240 scoped_ptr<Value> empty_value(new DictionaryValue); 241 { 242 DictionaryPrefUpdate update(pref_service_, prefs::kContentSettingsPatterns); 243 DictionaryValue* local_dict_value = update.Get(); 244 SetContentPattern(local_dict_value, expression2_, content_type0_, 1); 245 } 246 247 const PrefService::Preference* pref = 248 pref_service_->FindPreference(prefs::kContentSettingsPatterns); 249 scoped_ptr<Value> merged_value( 250 PreferenceModelAssociator::MergePreference(*pref, *empty_value)); 251 const DictionaryValue* local_dict_value = 252 pref_service_->GetDictionary(prefs::kContentSettingsPatterns); 253 EXPECT_TRUE(merged_value->Equals(local_dict_value)); 254 } 255 256 TEST_F(DictionaryPreferenceMergeTest, MergeNoConflicts) { 257 { 258 DictionaryPrefUpdate update(pref_service_, prefs::kContentSettingsPatterns); 259 DictionaryValue* local_dict_value = update.Get(); 260 SetContentPattern(local_dict_value, expression2_, content_type0_, 1); 261 } 262 263 scoped_ptr<Value> merged_value(PreferenceModelAssociator::MergePreference( 264 *pref_service_->FindPreference(prefs::kContentSettingsPatterns), 265 server_patterns_)); 266 267 DictionaryValue expected; 268 SetContentPattern(&expected, expression0_, content_type0_, 1); 269 SetContentPattern(&expected, expression0_, content_type1_, 2); 270 SetContentPattern(&expected, expression1_, content_type0_, 1); 271 SetContentPattern(&expected, expression2_, content_type0_, 1); 272 EXPECT_TRUE(merged_value->Equals(&expected)); 273 } 274 275 TEST_F(DictionaryPreferenceMergeTest, MergeConflicts) { 276 { 277 DictionaryPrefUpdate update(pref_service_, prefs::kContentSettingsPatterns); 278 DictionaryValue* local_dict_value = update.Get(); 279 SetContentPattern(local_dict_value, expression0_, content_type0_, 2); 280 SetContentPattern(local_dict_value, expression1_, content_type0_, 1); 281 SetContentPattern(local_dict_value, expression1_, content_type1_, 1); 282 SetContentPattern(local_dict_value, expression2_, content_type0_, 2); 283 } 284 285 scoped_ptr<Value> merged_value(PreferenceModelAssociator::MergePreference( 286 *pref_service_->FindPreference(prefs::kContentSettingsPatterns), 287 server_patterns_)); 288 289 DictionaryValue expected; 290 SetContentPattern(&expected, expression0_, content_type0_, 1); 291 SetContentPattern(&expected, expression0_, content_type1_, 2); 292 SetContentPattern(&expected, expression1_, content_type0_, 1); 293 SetContentPattern(&expected, expression1_, content_type1_, 1); 294 SetContentPattern(&expected, expression2_, content_type0_, 2); 295 EXPECT_TRUE(merged_value->Equals(&expected)); 296 } 297 298 TEST_F(DictionaryPreferenceMergeTest, Equal) { 299 { 300 DictionaryPrefUpdate update(pref_service_, prefs::kContentSettingsPatterns); 301 DictionaryValue* local_dict_value = update.Get(); 302 SetContentPattern(local_dict_value, expression0_, content_type0_, 1); 303 SetContentPattern(local_dict_value, expression0_, content_type1_, 2); 304 SetContentPattern(local_dict_value, expression1_, content_type0_, 1); 305 } 306 307 scoped_ptr<Value> merged_value(PreferenceModelAssociator::MergePreference( 308 *pref_service_->FindPreference(prefs::kContentSettingsPatterns), 309 server_patterns_)); 310 EXPECT_TRUE(merged_value->Equals(&server_patterns_)); 311 } 312 313 TEST_F(DictionaryPreferenceMergeTest, ConflictButServerWins) { 314 { 315 DictionaryPrefUpdate update(pref_service_, prefs::kContentSettingsPatterns); 316 DictionaryValue* local_dict_value = update.Get(); 317 SetContentPattern(local_dict_value, expression0_, content_type0_, 2); 318 SetContentPattern(local_dict_value, expression0_, content_type1_, 2); 319 SetContentPattern(local_dict_value, expression1_, content_type0_, 1); 320 } 321 322 scoped_ptr<Value> merged_value(PreferenceModelAssociator::MergePreference( 323 *pref_service_->FindPreference(prefs::kContentSettingsPatterns), 324 server_patterns_)); 325 EXPECT_TRUE(merged_value->Equals(&server_patterns_)); 326 } 327 328 class IndividualPreferenceMergeTest : public AbstractPreferenceMergeTest { 329 protected: 330 IndividualPreferenceMergeTest() : 331 url0_("http://example.com/server0"), 332 url1_("http://example.com/server1"), 333 expression0_("expression0"), 334 expression1_("expression1"), 335 content_type0_("content_type0") {} 336 337 virtual void SetUp() { 338 AbstractPreferenceMergeTest::SetUp(); 339 server_url_list_.Append(Value::CreateStringValue(url0_)); 340 SetContentPattern(&server_patterns_, expression0_, content_type0_, 1); 341 } 342 343 bool MergeListPreference(const char* pref) { 344 { 345 ListPrefUpdate update(pref_service_, pref); 346 ListValue* local_list_value = update.Get(); 347 local_list_value->Append(Value::CreateStringValue(url1_)); 348 } 349 350 scoped_ptr<Value> merged_value(PreferenceModelAssociator::MergePreference( 351 *pref_service_->FindPreference(pref), 352 server_url_list_)); 353 354 ListValue expected; 355 expected.Append(Value::CreateStringValue(url0_)); 356 expected.Append(Value::CreateStringValue(url1_)); 357 return merged_value->Equals(&expected); 358 } 359 360 bool MergeDictionaryPreference(const char* pref) { 361 { 362 DictionaryPrefUpdate update(pref_service_, pref); 363 DictionaryValue* local_dict_value = update.Get(); 364 SetContentPattern(local_dict_value, expression1_, content_type0_, 1); 365 } 366 367 scoped_ptr<Value> merged_value(PreferenceModelAssociator::MergePreference( 368 *pref_service_->FindPreference(pref), 369 server_patterns_)); 370 371 DictionaryValue expected; 372 SetContentPattern(&expected, expression0_, content_type0_, 1); 373 SetContentPattern(&expected, expression1_, content_type0_, 1); 374 return merged_value->Equals(&expected); 375 } 376 377 std::string url0_; 378 std::string url1_; 379 std::string expression0_; 380 std::string expression1_; 381 std::string content_type0_; 382 ListValue server_url_list_; 383 DictionaryValue server_patterns_; 384 }; 385 386 TEST_F(IndividualPreferenceMergeTest, URLsToRestoreOnStartup) { 387 EXPECT_TRUE(MergeListPreference(prefs::kURLsToRestoreOnStartup)); 388 } 389 390 TEST_F(IndividualPreferenceMergeTest, DesktopNotificationAllowedOrigins) { 391 EXPECT_TRUE(MergeListPreference(prefs::kDesktopNotificationAllowedOrigins)); 392 } 393 394 TEST_F(IndividualPreferenceMergeTest, DesktopNotificationDeniedOrigins) { 395 EXPECT_TRUE(MergeListPreference(prefs::kDesktopNotificationDeniedOrigins)); 396 } 397 398 TEST_F(IndividualPreferenceMergeTest, ContentSettingsPatterns) { 399 EXPECT_TRUE(MergeDictionaryPreference(prefs::kContentSettingsPatterns)); 400 } 401 402 TEST_F(IndividualPreferenceMergeTest, GeolocationContentSettings) { 403 EXPECT_TRUE(MergeDictionaryPreference(prefs::kGeolocationContentSettings)); 404 } 405