Fix partially broken pattern keys and delete invalid pattern keys of the...

Fix partially broken pattern keys and delete invalid pattern keys of the obsolete content settings pattern pref.

BUG=90490
TEST=content_settings_pref_provider_unittest.cc

Review URL: http://codereview.chromium.org/7529025

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@95991 0039d316-1c4b-4281-b951-d872f2087c98
parent ef3c1dae
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
#include "chrome/browser/content_settings/content_settings_pref_provider.h" #include "chrome/browser/content_settings/content_settings_pref_provider.h"
#include <list> #include <map>
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector> #include <vector>
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/auto_reset.h" #include "base/auto_reset.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "base/metrics/histogram.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_pattern.h"
#include "chrome/browser/content_settings/content_settings_utils.h" #include "chrome/browser/content_settings/content_settings_utils.h"
#include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/prefs/pref_service.h"
...@@ -30,6 +31,9 @@ ...@@ -30,6 +31,9 @@
namespace { 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 // The preference keys where resource identifiers are stored for
// ContentSettingsType values that support resource identifiers. // ContentSettingsType values that support resource identifiers.
const char* kResourceTypeNames[] = { const char* kResourceTypeNames[] = {
...@@ -964,42 +968,80 @@ void PrefProvider::MigrateObsoletePopupsPref() { ...@@ -964,42 +968,80 @@ void PrefProvider::MigrateObsoletePopupsPref() {
void PrefProvider::MigrateObsoleteContentSettingsPatternPref() { void PrefProvider::MigrateObsoleteContentSettingsPatternPref() {
if (prefs_->HasPrefPath(prefs::kContentSettingsPatterns) && !is_incognito_) { if (prefs_->HasPrefPath(prefs::kContentSettingsPatterns) && !is_incognito_) {
const DictionaryValue* all_settings_dictionary = const DictionaryValue* patterns_dictionary =
prefs_->GetDictionary(prefs::kContentSettingsPatterns); prefs_->GetDictionary(prefs::kContentSettingsPatterns);
DictionaryPrefUpdate update(prefs_, prefs::kContentSettingsPatternPairs); // A map with an old key, new key mapping. If the new key is empty then the
DictionaryValue* exceptions_dictionary; // value for the old key will be removed.
exceptions_dictionary = update.Get(); StringMap keys_to_change;
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;
// Validate pattern string and skip it if it is invalid. {
std::pair<ContentSettingsPattern, ContentSettingsPattern> pattern_pair = DictionaryPrefUpdate update(prefs_, prefs::kContentSettingsPatternPairs);
ParsePatternString(key); DictionaryValue* pattern_pairs_dictionary = update.Get();
const ContentSettingsPattern& primary_pattern = pattern_pair.first; for (DictionaryValue::key_iterator i(
if (!primary_pattern.IsValid()) { patterns_dictionary->begin_keys());
LOG(DFATAL) << "Invalid pattern strings: " << key; i != patterns_dictionary->end_keys();
continue; ++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. // If the key contains a pattern pair, then remove the secondary
// Get old settings. // pattern from the key.
DictionaryValue* dictionary = NULL; if (sep_pos != std::string::npos) {
bool found = all_settings_dictionary->GetDictionaryWithoutPathExpansion( // If the dictionary already has a key that equals the primary pattern
key, &dictionary); // of the corrupted pattern pair key, don't fix the key but remove it.
DCHECK(found); if (patterns_dictionary->HasKey(pattern.ToString())) {
keys_to_change[key] = "";
continue;
}
// Create new dictionary key. // If there is more than one key with a pattern pair that has the same
std::string new_pattern_str = CreatePatternString( // valid primary pattern, then the value of the last key processed
primary_pattern, ContentSettingsPattern::Wildcard()); // will win and overwrite the value any previous key.
keys_to_change[key] = pattern.ToString();
}
// Existing values are overwritten. // Copy dictionary value.
exceptions_dictionary->SetWithoutPathExpansion( DictionaryValue* dictionary = NULL;
new_pattern_str, dictionary->DeepCopy()); 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());
}
}
} }
} }
} }
......
...@@ -489,4 +489,70 @@ TEST_F(PrefProviderTest, SyncObsoletePref) { ...@@ -489,4 +489,70 @@ TEST_F(PrefProviderTest, SyncObsoletePref) {
provider.ShutdownOnUIThread(); provider.ShutdownOnUIThread();
} }
TEST_F(PrefProviderTest, FixOrRemoveMalformedPatternKeysFromObsoletePref) {
TestingProfile profile;
PrefService* prefs = profile.GetPrefs();
// Set obsolete preference for content settings pattern.
scoped_ptr<DictionaryValue> settings_dictionary(new DictionaryValue());
settings_dictionary->SetInteger("cookies", 2);
settings_dictionary->SetInteger("images", 2);
settings_dictionary->SetInteger("popups", 2);
scoped_ptr<DictionaryValue> all_settings_dictionary(new DictionaryValue());
// Good pattern key.
all_settings_dictionary->SetWithoutPathExpansion(
"http://www.example.com", settings_dictionary->DeepCopy());
// Bad pattern key that will be ignored since there is already a good pattern
// key for the primary patter of the bad pattern key.
all_settings_dictionary->SetWithoutPathExpansion(
"http://www.example.com,", settings_dictionary->DeepCopy());
// Bad pattern key that should be removed.
all_settings_dictionary->SetWithoutPathExpansion(
"http://www.broken.com*", settings_dictionary->DeepCopy());
all_settings_dictionary->SetWithoutPathExpansion(
"http://www.bar.com,", settings_dictionary->DeepCopy());
// Bad pattern key with a trailing comma that is supposed to be fixed.
// A trailing comma means that the secondary pattern string is empty and hence
// invalid.
all_settings_dictionary->SetWithoutPathExpansion(
"http://www.foo.com,", settings_dictionary->DeepCopy());
// Bad pattern key with an invalid secondary pattern that should be removed.
all_settings_dictionary->SetWithoutPathExpansion(
"http://www.foo.com,error*", settings_dictionary->DeepCopy());
// Pattern keys with valid pattern pairs.
all_settings_dictionary->SetWithoutPathExpansion(
"http://www.foo.com,[*.]bar.com", settings_dictionary->DeepCopy());
prefs->Set(prefs::kContentSettingsPatterns, *all_settings_dictionary);
all_settings_dictionary->SetWithoutPathExpansion(
"http://www.example2.com,*", settings_dictionary->DeepCopy());
prefs->Set(prefs::kContentSettingsPatterns, *all_settings_dictionary);
content_settings::PrefProvider provider(prefs, false);
// Tests that the broken pattern keys got fixed or removed.
const DictionaryValue* patterns_dictionary =
prefs->GetDictionary(prefs::kContentSettingsPatterns);
EXPECT_EQ(4U, patterns_dictionary->size());
EXPECT_TRUE(patterns_dictionary->HasKey("http://www.example.com"));
EXPECT_TRUE(patterns_dictionary->HasKey("http://www.bar.com"));
EXPECT_TRUE(patterns_dictionary->HasKey("http://www.foo.com"));
EXPECT_TRUE(patterns_dictionary->HasKey("http://www.example2.com"));
// Broken pattern keys that should be removed
EXPECT_FALSE(patterns_dictionary->HasKey("http://www.bar.com,"));
EXPECT_FALSE(patterns_dictionary->HasKey("http://www.foo.com,"));
EXPECT_FALSE(patterns_dictionary->HasKey("http://www.foo.com,error*"));
EXPECT_FALSE(patterns_dictionary->HasKey(
"http://www.foo.com,[*.]bar.com"));
EXPECT_FALSE(patterns_dictionary->HasKey("http://www.example2.com,*"));
EXPECT_FALSE(patterns_dictionary->HasKey("http://www.broken.com*"));
provider.ShutdownOnUIThread();
}
} // namespace content_settings } // namespace content_settings
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment