Index: chrome/browser/content_settings/content_settings_pref_provider.cc |
diff --git a/chrome/browser/content_settings/content_settings_pref_provider.cc b/chrome/browser/content_settings/content_settings_pref_provider.cc |
index c7fe7fdcdc13715573fbf2f236926aa08a0cee62..d088a8832f7bc51202688057be954591c5dae82a 100644 |
--- a/chrome/browser/content_settings/content_settings_pref_provider.cc |
+++ b/chrome/browser/content_settings/content_settings_pref_provider.cc |
@@ -4,7 +4,7 @@ |
#include "chrome/browser/content_settings/content_settings_pref_provider.h" |
-#include <list> |
+#include <map> |
#include <string> |
#include <utility> |
#include <vector> |
@@ -12,6 +12,7 @@ |
#include "base/auto_reset.h" |
#include "base/command_line.h" |
#include "base/metrics/histogram.h" |
+#include "base/scoped_ptr.h" |
#include "chrome/browser/content_settings/content_settings_pattern.h" |
#include "chrome/browser/content_settings/content_settings_utils.h" |
#include "chrome/browser/prefs/pref_service.h" |
@@ -30,6 +31,9 @@ |
namespace { |
+typedef std::pair<std::string, std::string> StringPair; |
+typedef std::map<std::string, std::string> StringMap; |
+ |
// The preference keys where resource identifiers are stored for |
// ContentSettingsType values that support resource identifiers. |
const char* kResourceTypeNames[] = { |
@@ -964,42 +968,80 @@ void PrefProvider::MigrateObsoletePopupsPref() { |
void PrefProvider::MigrateObsoleteContentSettingsPatternPref() { |
if (prefs_->HasPrefPath(prefs::kContentSettingsPatterns) && !is_incognito_) { |
- const DictionaryValue* all_settings_dictionary = |
+ const DictionaryValue* patterns_dictionary = |
prefs_->GetDictionary(prefs::kContentSettingsPatterns); |
- DictionaryPrefUpdate update(prefs_, prefs::kContentSettingsPatternPairs); |
- DictionaryValue* exceptions_dictionary; |
- exceptions_dictionary = update.Get(); |
- for (DictionaryValue::key_iterator i(all_settings_dictionary->begin_keys()); |
- i != all_settings_dictionary->end_keys(); |
- ++i) { |
- const std::string& key(*i); |
- if (key.empty()) |
- continue; |
+ // A map with an old key, new key mapping. If the new key is empty then the |
+ // value for the old key will be removed. |
+ StringMap keys_to_change; |
- // Validate pattern string and skip it if it is invalid. |
- std::pair<ContentSettingsPattern, ContentSettingsPattern> pattern_pair = |
- ParsePatternString(key); |
- const ContentSettingsPattern& primary_pattern = pattern_pair.first; |
- if (!primary_pattern.IsValid()) { |
- LOG(DFATAL) << "Invalid pattern strings: " << key; |
- continue; |
- } |
+ { |
+ DictionaryPrefUpdate update(prefs_, prefs::kContentSettingsPatternPairs); |
+ DictionaryValue* pattern_pairs_dictionary = update.Get(); |
+ for (DictionaryValue::key_iterator i( |
+ patterns_dictionary->begin_keys()); |
+ i != patterns_dictionary->end_keys(); |
+ ++i) { |
+ const std::string& key(*i); |
+ // Remove broken pattern keys and fix keys with pattern pairs. |
+ size_t sep_pos = key.find(","); |
+ ContentSettingsPattern pattern = |
+ ContentSettingsPattern::FromString(key.substr(0, sep_pos)); |
+ |
+ // Save the key if it contains a invalid patterns to remove it later. |
+ // Continue and don't try to migrate the broken pattern key. |
+ if (!pattern.IsValid()) { |
+ keys_to_change[key] = ""; |
+ continue; |
+ } |
- // Copy dictionary value. |
- // Get old settings. |
- DictionaryValue* dictionary = NULL; |
- bool found = all_settings_dictionary->GetDictionaryWithoutPathExpansion( |
- key, &dictionary); |
- DCHECK(found); |
+ // If the key contains a pattern pair, then remove the secondary |
+ // pattern from the key. |
+ if (sep_pos != std::string::npos) { |
+ // If the dictionary already has a key that equals the primary pattern |
+ // of the corrupted pattern pair key, don't fix the key but remove it. |
+ if (patterns_dictionary->HasKey(pattern.ToString())) { |
+ keys_to_change[key] = ""; |
+ continue; |
+ } |
- // Create new dictionary key. |
- std::string new_pattern_str = CreatePatternString( |
- primary_pattern, ContentSettingsPattern::Wildcard()); |
+ // If there is more than one key with a pattern pair that has the same |
+ // valid primary pattern, then the value of the last key processed |
+ // will win and overwrite the value any previous key. |
+ keys_to_change[key] = pattern.ToString(); |
+ } |
- // Existing values are overwritten. |
- exceptions_dictionary->SetWithoutPathExpansion( |
- new_pattern_str, dictionary->DeepCopy()); |
+ // Copy dictionary value. |
+ DictionaryValue* dictionary = NULL; |
+ bool found = patterns_dictionary->GetDictionaryWithoutPathExpansion( |
+ key, &dictionary); |
+ DCHECK(found); |
+ std::string new_key = CreatePatternString( |
+ pattern, ContentSettingsPattern::Wildcard()); |
+ // Existing values are overwritten. |
+ pattern_pairs_dictionary->SetWithoutPathExpansion( |
+ new_key, dictionary->DeepCopy()); |
+ } |
+ } |
+ |
+ { |
+ DictionaryPrefUpdate update(prefs_, prefs::kContentSettingsPatterns); |
+ DictionaryValue* mutable_patterns_dictionary = update.Get(); |
+ // Fix broken pattern strings. |
+ for (StringMap::iterator i(keys_to_change.begin()); |
+ i != keys_to_change.end(); |
+ ++i) { |
+ const StringPair& pattern_str_pair(*i); |
+ Value* dict_ptr = NULL; |
+ bool found = mutable_patterns_dictionary->RemoveWithoutPathExpansion( |
+ pattern_str_pair.first, &dict_ptr); |
+ scoped_ptr<Value> dict(dict_ptr); |
+ DCHECK(found); |
+ if (!pattern_str_pair.second.empty()) { |
+ mutable_patterns_dictionary->SetWithoutPathExpansion( |
+ pattern_str_pair.second, dict.release()); |
+ } |
+ } |
} |
} |
} |