| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/content_settings/core/browser/content_settings_pref.h" | 5 #include "components/content_settings/core/browser/content_settings_pref.h" |
| 6 | 6 |
| 7 #include "base/auto_reset.h" | 7 #include "base/auto_reset.h" |
| 8 #include "base/bind.h" | 8 #include "base/bind.h" |
| 9 #include "base/memory/scoped_ptr.h" | 9 #include "base/memory/scoped_ptr.h" |
| 10 #include "base/metrics/histogram_macros.h" | 10 #include "base/metrics/histogram_macros.h" |
| 11 #include "base/prefs/scoped_user_pref_update.h" | 11 #include "base/prefs/scoped_user_pref_update.h" |
| 12 #include "base/strings/string_split.h" | 12 #include "base/strings/string_split.h" |
| 13 #include "base/time/clock.h" | 13 #include "base/time/clock.h" |
| 14 #include "components/content_settings/core/browser/content_settings_rule.h" | 14 #include "components/content_settings/core/browser/content_settings_rule.h" |
| 15 #include "components/content_settings/core/browser/content_settings_utils.h" | 15 #include "components/content_settings/core/browser/content_settings_utils.h" |
| 16 #include "components/content_settings/core/browser/host_content_settings_map.h" | 16 #include "components/content_settings/core/browser/host_content_settings_map.h" |
| 17 #include "components/content_settings/core/common/content_settings.h" | 17 #include "components/content_settings/core/common/content_settings.h" |
| 18 #include "components/content_settings/core/common/content_settings_pattern.h" | 18 #include "components/content_settings/core/common/content_settings_pattern.h" |
| 19 #include "components/content_settings/core/common/pref_names.h" | 19 #include "components/content_settings/core/common/pref_names.h" |
| 20 #include "url/gurl.h" | 20 #include "url/gurl.h" |
| 21 | 21 |
| 22 namespace { | 22 namespace { |
| 23 | 23 |
| 24 const char kSettingPath[] = "setting"; | 24 const char kSettingPath[] = "setting"; |
| 25 const char kPerResourceIdentifierPrefName[] = "per_resource"; | 25 const char kPerResourceIdentifierPrefName[] = "per_resource"; |
| 26 const char kPerPluginPrefName[] = "per_plugin"; | |
| 27 const char kLastUsed[] = "last_used"; | 26 const char kLastUsed[] = "last_used"; |
| 28 | 27 |
| 29 ContentSetting FixObsoleteCookiePromptMode(ContentSettingsType content_type, | 28 ContentSetting FixObsoleteCookiePromptMode(ContentSettingsType content_type, |
| 30 ContentSetting setting) { | 29 ContentSetting setting) { |
| 31 if (content_type == CONTENT_SETTINGS_TYPE_COOKIES && | 30 if (content_type == CONTENT_SETTINGS_TYPE_COOKIES && |
| 32 setting == CONTENT_SETTING_ASK) { | 31 setting == CONTENT_SETTING_ASK) { |
| 33 return CONTENT_SETTING_BLOCK; | 32 return CONTENT_SETTING_BLOCK; |
| 34 } | 33 } |
| 35 return setting; | 34 return setting; |
| 36 } | 35 } |
| 37 | 36 |
| 38 // If the given content type supports resource identifiers in user preferences, | 37 // If the given content type supports resource identifiers in user preferences, |
| 39 // returns true and sets |pref_key| to the key in the content settings | 38 // returns true and sets |pref_key| to the key in the content settings |
| 40 // dictionary under which per-resource content settings are stored. | 39 // dictionary under which per-resource content settings are stored. |
| 41 // Otherwise, returns false. | 40 // Otherwise, returns false. |
| 42 bool SupportsResourceIdentifiers(ContentSettingsType content_type) { | 41 bool SupportsResourceIdentifiers(ContentSettingsType content_type) { |
| 43 return content_type == CONTENT_SETTINGS_TYPE_PLUGINS; | 42 return content_type == CONTENT_SETTINGS_TYPE_PLUGINS; |
| 44 } | 43 } |
| 45 | 44 |
| 46 } // namespace | 45 } // namespace |
| 47 | 46 |
| 48 namespace content_settings { | 47 namespace content_settings { |
| 49 | 48 |
| 50 ContentSettingsPref::ContentSettingsPref( | 49 ContentSettingsPref::ContentSettingsPref( |
| 51 ContentSettingsType content_type, | 50 ContentSettingsType content_type, |
| 52 PrefService* prefs, | 51 PrefService* prefs, |
| 53 PrefChangeRegistrar* registrar, | 52 PrefChangeRegistrar* registrar, |
| 54 const char* pref_name, | 53 const char* pref_name, |
| 55 bool incognito, | 54 bool incognito, |
| 56 bool* updating_old_preferences_flag, | |
| 57 NotifyObserversCallback notify_callback) | 55 NotifyObserversCallback notify_callback) |
| 58 : content_type_(content_type), | 56 : content_type_(content_type), |
| 59 prefs_(prefs), | 57 prefs_(prefs), |
| 60 registrar_(registrar), | 58 registrar_(registrar), |
| 61 pref_name_(pref_name), | 59 pref_name_(pref_name), |
| 62 is_incognito_(incognito), | 60 is_incognito_(incognito), |
| 63 updating_preferences_(false), | 61 updating_preferences_(false), |
| 64 updating_old_preferences_(updating_old_preferences_flag), | |
| 65 notify_callback_(notify_callback) { | 62 notify_callback_(notify_callback) { |
| 66 DCHECK(prefs_); | 63 DCHECK(prefs_); |
| 67 | 64 |
| 68 // If the migration hasn't happened yet, or if this content setting | 65 ReadContentSettingsFromPref(); |
| 69 // is syncable, the parent |PrefProvider| is going to copy the contents | |
| 70 // of the old preference to this new preference. There is no need | |
| 71 // to initialize this preference separately (in fact, in the case | |
| 72 // of migration, we would be writing the empty new preference back to the | |
| 73 // old one, erasing it). Since copying between preferences is disallowed | |
| 74 // in incognito, |ContentSettingsPref| needs to be initialized from the new | |
| 75 // preference in incognito as well. | |
| 76 if ((prefs_->GetBoolean(prefs::kMigratedContentSettingsPatternPairs) && | |
| 77 !IsContentSettingsTypeSyncable(content_type_)) | |
| 78 || is_incognito_) { | |
| 79 ReadContentSettingsFromPrefAndWriteToOldPref(); | |
| 80 } | |
| 81 | 66 |
| 82 registrar_->Add( | 67 registrar_->Add( |
| 83 pref_name_, | 68 pref_name_, |
| 84 base::Bind(&ContentSettingsPref::OnPrefChanged, base::Unretained(this))); | 69 base::Bind(&ContentSettingsPref::OnPrefChanged, base::Unretained(this))); |
| 85 } | 70 } |
| 86 | 71 |
| 87 ContentSettingsPref::~ContentSettingsPref() { | 72 ContentSettingsPref::~ContentSettingsPref() { |
| 88 } | 73 } |
| 89 | 74 |
| 90 RuleIterator* ContentSettingsPref::GetRuleIterator( | 75 RuleIterator* ContentSettingsPref::GetRuleIterator( |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 content_type_, | 117 content_type_, |
| 133 resource_identifier); | 118 resource_identifier); |
| 134 } | 119 } |
| 135 } | 120 } |
| 136 // Update the content settings preference. | 121 // Update the content settings preference. |
| 137 if (!is_incognito_) { | 122 if (!is_incognito_) { |
| 138 UpdatePref(primary_pattern, | 123 UpdatePref(primary_pattern, |
| 139 secondary_pattern, | 124 secondary_pattern, |
| 140 resource_identifier, | 125 resource_identifier, |
| 141 value.get()); | 126 value.get()); |
| 142 if (IsContentSettingsTypeSyncable(content_type_)) { | |
| 143 UpdateOldPref(primary_pattern, | |
| 144 secondary_pattern, | |
| 145 resource_identifier, | |
| 146 value.get()); | |
| 147 } | |
| 148 } | 127 } |
| 149 | 128 |
| 150 notify_callback_.Run( | 129 notify_callback_.Run( |
| 151 primary_pattern, secondary_pattern, content_type_, resource_identifier); | 130 primary_pattern, secondary_pattern, content_type_, resource_identifier); |
| 152 | 131 |
| 153 return true; | 132 return true; |
| 154 } | 133 } |
| 155 | 134 |
| 156 void ContentSettingsPref::ClearAllContentSettingsRules() { | 135 void ContentSettingsPref::ClearAllContentSettingsRules() { |
| 157 DCHECK(thread_checker_.CalledOnValidThread()); | 136 DCHECK(thread_checker_.CalledOnValidThread()); |
| 158 DCHECK(prefs_); | 137 DCHECK(prefs_); |
| 159 | 138 |
| 160 OriginIdentifierValueMap* map_to_modify = &incognito_value_map_; | 139 OriginIdentifierValueMap* map_to_modify = &incognito_value_map_; |
| 161 if (!is_incognito_) | 140 if (!is_incognito_) |
| 162 map_to_modify = &value_map_; | 141 map_to_modify = &value_map_; |
| 163 | 142 |
| 164 { | 143 { |
| 165 base::AutoLock auto_lock(lock_); | 144 base::AutoLock auto_lock(lock_); |
| 166 map_to_modify->clear(); | 145 map_to_modify->clear(); |
| 167 } | 146 } |
| 168 | 147 |
| 169 if (!is_incognito_) { | 148 if (!is_incognito_) { |
| 170 // Clear the new preference. | 149 // Clear the preference. |
| 171 { | 150 { |
| 172 base::AutoReset<bool> auto_reset(&updating_preferences_, true); | 151 base::AutoReset<bool> auto_reset(&updating_preferences_, true); |
| 173 DictionaryPrefUpdate update(prefs_, pref_name_); | 152 DictionaryPrefUpdate update(prefs_, pref_name_); |
| 174 base::DictionaryValue* pattern_pairs_settings = update.Get(); | 153 base::DictionaryValue* pattern_pairs_settings = update.Get(); |
| 175 pattern_pairs_settings->Clear(); | 154 pattern_pairs_settings->Clear(); |
| 176 } | 155 } |
| 177 | |
| 178 if (IsContentSettingsTypeSyncable(content_type_)) | |
| 179 ClearOldPreference(); | |
| 180 } | 156 } |
| 181 | 157 |
| 182 notify_callback_.Run(ContentSettingsPattern(), | 158 notify_callback_.Run(ContentSettingsPattern(), |
| 183 ContentSettingsPattern(), | 159 ContentSettingsPattern(), |
| 184 content_type_, | 160 content_type_, |
| 185 ResourceIdentifier()); | 161 ResourceIdentifier()); |
| 186 } | 162 } |
| 187 | 163 |
| 188 void ContentSettingsPref::UpdateLastUsage( | 164 void ContentSettingsPref::UpdateLastUsage( |
| 189 const ContentSettingsPattern& primary_pattern, | 165 const ContentSettingsPattern& primary_pattern, |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 242 if (!found) | 218 if (!found) |
| 243 return base::Time(); | 219 return base::Time(); |
| 244 | 220 |
| 245 return base::Time::FromDoubleT(last_used_time); | 221 return base::Time::FromDoubleT(last_used_time); |
| 246 } | 222 } |
| 247 | 223 |
| 248 size_t ContentSettingsPref::GetNumExceptions() { | 224 size_t ContentSettingsPref::GetNumExceptions() { |
| 249 return value_map_.size(); | 225 return value_map_.size(); |
| 250 } | 226 } |
| 251 | 227 |
| 252 void ContentSettingsPref::ReadContentSettingsFromPrefAndWriteToOldPref() { | 228 void ContentSettingsPref::ReadContentSettingsFromPref() { |
| 253 // Clear the old preference, so we can copy the exceptions from the new | |
| 254 // preference into it. Note that copying in this direction is disallowed | |
| 255 // in incognito, to avoid the echo effect: New preference -> PrefProvider -> | |
| 256 // Old preference -> Incognito PrefProvider -> New preference -> etc. | |
| 257 if (!is_incognito_ && IsContentSettingsTypeSyncable(content_type_)) | |
| 258 ClearOldPreference(); | |
| 259 | |
| 260 // |DictionaryPrefUpdate| sends out notifications when destructed. This | 229 // |DictionaryPrefUpdate| sends out notifications when destructed. This |
| 261 // construction order ensures |AutoLock| gets destroyed first and |lock_| is | 230 // construction order ensures |AutoLock| gets destroyed first and |lock_| is |
| 262 // not held when the notifications are sent. Also, |auto_reset| must be still | 231 // not held when the notifications are sent. Also, |auto_reset| must be still |
| 263 // valid when the notifications are sent, so that |Observe| skips the | 232 // valid when the notifications are sent, so that |Observe| skips the |
| 264 // notification. | 233 // notification. |
| 265 base::AutoReset<bool> auto_reset(&updating_preferences_, true); | 234 base::AutoReset<bool> auto_reset(&updating_preferences_, true); |
| 266 DictionaryPrefUpdate update(prefs_, pref_name_); | 235 DictionaryPrefUpdate update(prefs_, pref_name_); |
| 267 base::AutoLock auto_lock(lock_); | 236 base::AutoLock auto_lock(lock_); |
| 268 | 237 |
| 269 const base::DictionaryValue* all_settings_dictionary = | 238 const base::DictionaryValue* all_settings_dictionary = |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 321 bool is_integer = j.value().GetAsInteger(&setting); | 290 bool is_integer = j.value().GetAsInteger(&setting); |
| 322 DCHECK(is_integer); | 291 DCHECK(is_integer); |
| 323 DCHECK_NE(CONTENT_SETTING_DEFAULT, setting); | 292 DCHECK_NE(CONTENT_SETTING_DEFAULT, setting); |
| 324 scoped_ptr<base::Value> setting_ptr( | 293 scoped_ptr<base::Value> setting_ptr( |
| 325 new base::FundamentalValue(setting)); | 294 new base::FundamentalValue(setting)); |
| 326 value_map_.SetValue(pattern_pair.first, | 295 value_map_.SetValue(pattern_pair.first, |
| 327 pattern_pair.second, | 296 pattern_pair.second, |
| 328 content_type_, | 297 content_type_, |
| 329 resource_identifier, | 298 resource_identifier, |
| 330 setting_ptr->DeepCopy()); | 299 setting_ptr->DeepCopy()); |
| 331 if (!is_incognito_ && IsContentSettingsTypeSyncable(content_type_)) { | |
| 332 UpdateOldPref(pattern_pair.first, | |
| 333 pattern_pair.second, | |
| 334 resource_identifier, | |
| 335 setting_ptr.get()); | |
| 336 } | |
| 337 } | 300 } |
| 338 } | 301 } |
| 339 } | 302 } |
| 340 base::Value* value = NULL; | 303 base::Value* value = NULL; |
| 341 if (HostContentSettingsMap::ContentTypeHasCompoundValue(content_type_)) { | 304 if (HostContentSettingsMap::ContentTypeHasCompoundValue(content_type_)) { |
| 342 const base::DictionaryValue* setting = NULL; | 305 const base::DictionaryValue* setting = NULL; |
| 343 // TODO(xians): Handle the non-dictionary types. | 306 // TODO(xians): Handle the non-dictionary types. |
| 344 if (settings_dictionary->GetDictionaryWithoutPathExpansion( | 307 if (settings_dictionary->GetDictionaryWithoutPathExpansion( |
| 345 kSettingPath, &setting)) { | 308 kSettingPath, &setting)) { |
| 346 DCHECK(!setting->empty()); | 309 DCHECK(!setting->empty()); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 357 } | 320 } |
| 358 } | 321 } |
| 359 | 322 |
| 360 if (value != NULL) { | 323 if (value != NULL) { |
| 361 scoped_ptr<base::Value> value_ptr(value); | 324 scoped_ptr<base::Value> value_ptr(value); |
| 362 value_map_.SetValue(pattern_pair.first, | 325 value_map_.SetValue(pattern_pair.first, |
| 363 pattern_pair.second, | 326 pattern_pair.second, |
| 364 content_type_, | 327 content_type_, |
| 365 ResourceIdentifier(), | 328 ResourceIdentifier(), |
| 366 value->DeepCopy()); | 329 value->DeepCopy()); |
| 367 if (!is_incognito_ && IsContentSettingsTypeSyncable(content_type_)) { | |
| 368 UpdateOldPref(pattern_pair.first, | |
| 369 pattern_pair.second, | |
| 370 ResourceIdentifier(), | |
| 371 value_ptr.get()); | |
| 372 } | |
| 373 if (content_type_ == CONTENT_SETTINGS_TYPE_COOKIES) { | 330 if (content_type_ == CONTENT_SETTINGS_TYPE_COOKIES) { |
| 374 ContentSetting s = ValueToContentSetting(value); | 331 ContentSetting s = ValueToContentSetting(value); |
| 375 switch (s) { | 332 switch (s) { |
| 376 case CONTENT_SETTING_ALLOW : | 333 case CONTENT_SETTING_ALLOW : |
| 377 ++cookies_allow_exception_count; | 334 ++cookies_allow_exception_count; |
| 378 break; | 335 break; |
| 379 case CONTENT_SETTING_BLOCK : | 336 case CONTENT_SETTING_BLOCK : |
| 380 ++cookies_block_exception_count; | 337 ++cookies_block_exception_count; |
| 381 break; | 338 break; |
| 382 case CONTENT_SETTING_SESSION_ONLY : | 339 case CONTENT_SETTING_SESSION_ONLY : |
| (...skipping 17 matching lines...) Expand all Loading... |
| 400 cookies_session_only_exception_count); | 357 cookies_session_only_exception_count); |
| 401 } | 358 } |
| 402 } | 359 } |
| 403 | 360 |
| 404 void ContentSettingsPref::OnPrefChanged() { | 361 void ContentSettingsPref::OnPrefChanged() { |
| 405 DCHECK(thread_checker_.CalledOnValidThread()); | 362 DCHECK(thread_checker_.CalledOnValidThread()); |
| 406 | 363 |
| 407 if (updating_preferences_) | 364 if (updating_preferences_) |
| 408 return; | 365 return; |
| 409 | 366 |
| 410 ReadContentSettingsFromPrefAndWriteToOldPref(); | 367 ReadContentSettingsFromPref(); |
| 411 | 368 |
| 412 notify_callback_.Run(ContentSettingsPattern(), | 369 notify_callback_.Run(ContentSettingsPattern(), |
| 413 ContentSettingsPattern(), | 370 ContentSettingsPattern(), |
| 414 content_type_, | 371 content_type_, |
| 415 ResourceIdentifier()); | 372 ResourceIdentifier()); |
| 416 } | 373 } |
| 417 | 374 |
| 418 void ContentSettingsPref::UpdatePref( | 375 void ContentSettingsPref::UpdatePref( |
| 419 const ContentSettingsPattern& primary_pattern, | 376 const ContentSettingsPattern& primary_pattern, |
| 420 const ContentSettingsPattern& secondary_pattern, | 377 const ContentSettingsPattern& secondary_pattern, |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 479 } | 436 } |
| 480 // Remove the settings dictionary if it is empty. | 437 // Remove the settings dictionary if it is empty. |
| 481 if (settings_dictionary->empty()) { | 438 if (settings_dictionary->empty()) { |
| 482 pattern_pairs_settings->RemoveWithoutPathExpansion( | 439 pattern_pairs_settings->RemoveWithoutPathExpansion( |
| 483 pattern_str, NULL); | 440 pattern_str, NULL); |
| 484 } | 441 } |
| 485 } | 442 } |
| 486 } | 443 } |
| 487 } | 444 } |
| 488 | 445 |
| 489 void ContentSettingsPref::UpdateOldPref( | |
| 490 const ContentSettingsPattern& primary_pattern, | |
| 491 const ContentSettingsPattern& secondary_pattern, | |
| 492 const ResourceIdentifier& resource_identifier, | |
| 493 const base::Value* value) { | |
| 494 DCHECK(IsContentSettingsTypeSyncable(content_type_)); | |
| 495 | |
| 496 // The incognito provider cannot write the settings to avoid echo effect: | |
| 497 // New preference -> PrefProvider -> Old preference -> | |
| 498 // -> Incognito PrefProvider -> New preference -> etc. | |
| 499 DCHECK(!is_incognito_); | |
| 500 | |
| 501 if (*updating_old_preferences_) | |
| 502 return; | |
| 503 | |
| 504 base::AutoReset<bool> auto_reset(updating_old_preferences_, true); | |
| 505 { | |
| 506 DictionaryPrefUpdate update(prefs_, | |
| 507 prefs::kContentSettingsPatternPairs); | |
| 508 base::DictionaryValue* pattern_pairs_settings = update.Get(); | |
| 509 | |
| 510 // Get settings dictionary for the given patterns. | |
| 511 std::string pattern_str(CreatePatternString(primary_pattern, | |
| 512 secondary_pattern)); | |
| 513 base::DictionaryValue* settings_dictionary = NULL; | |
| 514 bool found = pattern_pairs_settings->GetDictionaryWithoutPathExpansion( | |
| 515 pattern_str, &settings_dictionary); | |
| 516 | |
| 517 if (!found && value) { | |
| 518 settings_dictionary = new base::DictionaryValue; | |
| 519 pattern_pairs_settings->SetWithoutPathExpansion( | |
| 520 pattern_str, settings_dictionary); | |
| 521 } | |
| 522 | |
| 523 if (settings_dictionary) { | |
| 524 if (content_type_ == CONTENT_SETTINGS_TYPE_PLUGINS && | |
| 525 !resource_identifier.empty()) { | |
| 526 base::DictionaryValue* resource_dictionary = NULL; | |
| 527 found = settings_dictionary->GetDictionary( | |
| 528 kPerPluginPrefName, &resource_dictionary); | |
| 529 if (!found) { | |
| 530 if (value == NULL) | |
| 531 return; // Nothing to remove. Exit early. | |
| 532 resource_dictionary = new base::DictionaryValue; | |
| 533 settings_dictionary->Set(kPerPluginPrefName, resource_dictionary); | |
| 534 } | |
| 535 // Update resource dictionary. | |
| 536 if (value == NULL) { | |
| 537 resource_dictionary->RemoveWithoutPathExpansion(resource_identifier, | |
| 538 NULL); | |
| 539 if (resource_dictionary->empty()) { | |
| 540 settings_dictionary->RemoveWithoutPathExpansion( | |
| 541 kPerPluginPrefName, NULL); | |
| 542 } | |
| 543 } else { | |
| 544 resource_dictionary->SetWithoutPathExpansion( | |
| 545 resource_identifier, value->DeepCopy()); | |
| 546 } | |
| 547 } else { | |
| 548 // Update settings dictionary. | |
| 549 std::string setting_path = GetTypeName(content_type_); | |
| 550 if (value == NULL) { | |
| 551 settings_dictionary->RemoveWithoutPathExpansion(setting_path, | |
| 552 NULL); | |
| 553 settings_dictionary->RemoveWithoutPathExpansion(kLastUsed, NULL); | |
| 554 } else { | |
| 555 settings_dictionary->SetWithoutPathExpansion( | |
| 556 setting_path, value->DeepCopy()); | |
| 557 } | |
| 558 } | |
| 559 // Remove the settings dictionary if it is empty. | |
| 560 if (settings_dictionary->empty()) { | |
| 561 pattern_pairs_settings->RemoveWithoutPathExpansion( | |
| 562 pattern_str, NULL); | |
| 563 } | |
| 564 } | |
| 565 } | |
| 566 } | |
| 567 | |
| 568 void ContentSettingsPref::ClearOldPreference() { | |
| 569 DCHECK(IsContentSettingsTypeSyncable(content_type_)); | |
| 570 | |
| 571 if (*updating_old_preferences_) | |
| 572 return; | |
| 573 | |
| 574 std::vector<std::string> keys; | |
| 575 | |
| 576 base::AutoReset<bool> auto_reset(updating_old_preferences_, true); | |
| 577 DictionaryPrefUpdate update(prefs_, prefs::kContentSettingsPatternPairs); | |
| 578 base::DictionaryValue* old_dictionary = update.Get(); | |
| 579 | |
| 580 for (base::DictionaryValue::Iterator it(*old_dictionary); | |
| 581 !it.IsAtEnd(); it.Advance()) { | |
| 582 keys.push_back(it.key()); | |
| 583 } | |
| 584 | |
| 585 for (const std::string& key : keys) { | |
| 586 base::DictionaryValue* exception; | |
| 587 bool is_dictionary = | |
| 588 old_dictionary->GetDictionaryWithoutPathExpansion(key, &exception); | |
| 589 DCHECK(is_dictionary); | |
| 590 | |
| 591 exception->RemoveWithoutPathExpansion(GetTypeName(content_type_), NULL); | |
| 592 | |
| 593 base::DictionaryValue* last_used; | |
| 594 if (exception->GetDictionaryWithoutPathExpansion(kLastUsed, &last_used)) { | |
| 595 last_used->RemoveWithoutPathExpansion(GetTypeName(content_type_), NULL); | |
| 596 | |
| 597 if (last_used->empty()) | |
| 598 exception->RemoveWithoutPathExpansion(kLastUsed, NULL); | |
| 599 } | |
| 600 | |
| 601 if (content_type_ == CONTENT_SETTINGS_TYPE_PLUGINS) | |
| 602 exception->RemoveWithoutPathExpansion(kPerPluginPrefName, NULL); | |
| 603 | |
| 604 if (exception->empty()) | |
| 605 old_dictionary->RemoveWithoutPathExpansion(key, NULL); | |
| 606 } | |
| 607 | |
| 608 } | |
| 609 | |
| 610 // static | 446 // static |
| 611 void ContentSettingsPref::CanonicalizeContentSettingsExceptions( | 447 void ContentSettingsPref::CanonicalizeContentSettingsExceptions( |
| 612 base::DictionaryValue* all_settings_dictionary) { | 448 base::DictionaryValue* all_settings_dictionary) { |
| 613 DCHECK(all_settings_dictionary); | 449 DCHECK(all_settings_dictionary); |
| 614 | 450 |
| 615 std::vector<std::string> remove_items; | 451 std::vector<std::string> remove_items; |
| 616 base::StringPairs move_items; | 452 base::StringPairs move_items; |
| 617 for (base::DictionaryValue::Iterator i(*all_settings_dictionary); | 453 for (base::DictionaryValue::Iterator i(*all_settings_dictionary); |
| 618 !i.IsAtEnd(); | 454 !i.IsAtEnd(); |
| 619 i.Advance()) { | 455 i.Advance()) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 665 | 501 |
| 666 void ContentSettingsPref::AssertLockNotHeld() const { | 502 void ContentSettingsPref::AssertLockNotHeld() const { |
| 667 #if !defined(NDEBUG) | 503 #if !defined(NDEBUG) |
| 668 // |Lock::Acquire()| will assert if the lock is held by this thread. | 504 // |Lock::Acquire()| will assert if the lock is held by this thread. |
| 669 lock_.Acquire(); | 505 lock_.Acquire(); |
| 670 lock_.Release(); | 506 lock_.Release(); |
| 671 #endif | 507 #endif |
| 672 } | 508 } |
| 673 | 509 |
| 674 } // namespace content_settings | 510 } // namespace content_settings |
| OLD | NEW |