summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/content_exceptions_table_model.cc10
-rw-r--r--chrome/browser/host_content_settings_map.cc187
-rw-r--r--chrome/browser/host_content_settings_map.h15
-rw-r--r--chrome/browser/host_content_settings_map_unittest.cc123
4 files changed, 281 insertions, 54 deletions
diff --git a/chrome/browser/content_exceptions_table_model.cc b/chrome/browser/content_exceptions_table_model.cc
index 53801ef..84e8c2d 100644
--- a/chrome/browser/content_exceptions_table_model.cc
+++ b/chrome/browser/content_exceptions_table_model.cc
@@ -30,7 +30,7 @@ ContentExceptionsTableModel::ContentExceptionsTableModel(
ContentExceptionsTableModel::~ContentExceptionsTableModel() {}
void ContentExceptionsTableModel::AddException(
- const HostContentSettingsMap::Pattern& pattern,
+ const HostContentSettingsMap::Pattern& original_pattern,
ContentSetting setting,
bool is_off_the_record) {
DCHECK(!is_off_the_record || off_the_record_map_);
@@ -38,6 +38,9 @@ void ContentExceptionsTableModel::AddException(
int insert_position =
is_off_the_record ? RowCount() : static_cast<int>(entries_.size());
+ const HostContentSettingsMap::Pattern pattern(
+ original_pattern.CanonicalizePattern());
+
entries(is_off_the_record).push_back(
HostContentSettingsMap::PatternSettingPair(pattern, setting));
map(is_off_the_record)->SetContentSetting(pattern,
@@ -74,13 +77,16 @@ void ContentExceptionsTableModel::RemoveAll() {
}
int ContentExceptionsTableModel::IndexOfExceptionByPattern(
- const HostContentSettingsMap::Pattern& pattern,
+ const HostContentSettingsMap::Pattern& original_pattern,
bool is_off_the_record) {
DCHECK(!is_off_the_record || off_the_record_map_);
int offset =
is_off_the_record ? static_cast<int>(entries_.size()) : 0;
+ const HostContentSettingsMap::Pattern pattern(
+ original_pattern.CanonicalizePattern());
+
// This is called on every key type in the editor. Move to a map if we end up
// with lots of exceptions.
for (size_t i = 0; i < entries(is_off_the_record).size(); ++i) {
diff --git a/chrome/browser/host_content_settings_map.cc b/chrome/browser/host_content_settings_map.cc
index e20f725..5e2a78c 100644
--- a/chrome/browser/host_content_settings_map.cc
+++ b/chrome/browser/host_content_settings_map.cc
@@ -145,6 +145,26 @@ bool HostContentSettingsMap::Pattern::Matches(const GURL& url) const {
(match + pattern_.length() - kDomainWildcardLength == host.length());
}
+std::string HostContentSettingsMap::Pattern::CanonicalizePattern() const {
+ if (!IsValid()) {
+ return "";
+ }
+
+ bool starts_with_wildcard = pattern_.length() > kDomainWildcardLength &&
+ StartsWithASCII(pattern_, kDomainWildcard, false);
+
+ const std::string host(starts_with_wildcard ?
+ pattern_.substr(kDomainWildcardLength) : pattern_);
+
+ std::string canonicalized_pattern =
+ starts_with_wildcard ? kDomainWildcard : "";
+
+ url_canon::CanonHostInfo host_info;
+ canonicalized_pattern += net::CanonicalizeHost(host, &host_info);
+
+ return canonicalized_pattern;
+}
+
HostContentSettingsMap::HostContentSettingsMap(Profile* profile)
: profile_(profile),
block_third_party_cookies_(false),
@@ -152,58 +172,11 @@ HostContentSettingsMap::HostContentSettingsMap(Profile* profile)
updating_preferences_(false) {
PrefService* prefs = profile_->GetPrefs();
- // Migrate obsolete cookie pref.
- if (prefs->HasPrefPath(prefs::kCookieBehavior)) {
- int cookie_behavior = prefs->GetInteger(prefs::kCookieBehavior);
- prefs->ClearPref(prefs::kCookieBehavior);
- if (!prefs->HasPrefPath(prefs::kDefaultContentSettings)) {
- SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_COOKIES,
- (cookie_behavior == net::StaticCookiePolicy::BLOCK_ALL_COOKIES) ?
- CONTENT_SETTING_BLOCK : CONTENT_SETTING_ALLOW);
- }
- if (!prefs->HasPrefPath(prefs::kBlockThirdPartyCookies)) {
- SetBlockThirdPartyCookies(cookie_behavior ==
- net::StaticCookiePolicy::BLOCK_THIRD_PARTY_COOKIES);
- }
- }
+ MigrateObsoleteCookiePref(prefs);
- // Migrate obsolete popups pref.
- if (prefs->HasPrefPath(prefs::kPopupWhitelistedHosts)) {
- const ListValue* whitelist_pref =
- prefs->GetList(prefs::kPopupWhitelistedHosts);
- for (ListValue::const_iterator i(whitelist_pref->begin());
- i != whitelist_pref->end(); ++i) {
- std::string host;
- (*i)->GetAsString(&host);
- SetContentSetting(Pattern(host), CONTENT_SETTINGS_TYPE_POPUPS, "",
- CONTENT_SETTING_ALLOW);
- }
- prefs->ClearPref(prefs::kPopupWhitelistedHosts);
- }
+ MigrateObsoletePopupsPref(prefs);
- // Migrate obsolete per-host pref.
- if (prefs->HasPrefPath(prefs::kPerHostContentSettings)) {
- const DictionaryValue* all_settings_dictionary =
- prefs->GetDictionary(prefs::kPerHostContentSettings);
- for (DictionaryValue::key_iterator i(all_settings_dictionary->begin_keys());
- i != all_settings_dictionary->end_keys(); ++i) {
- const std::string& host(*i);
- Pattern pattern(std::string(kDomainWildcard) + host);
- DictionaryValue* host_settings_dictionary = NULL;
- bool found = all_settings_dictionary->GetDictionaryWithoutPathExpansion(
- host, &host_settings_dictionary);
- DCHECK(found);
- ContentSettings settings;
- GetSettingsFromDictionary(host_settings_dictionary, &settings);
- for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) {
- if (settings.settings[j] != CONTENT_SETTING_DEFAULT &&
- !RequiresResourceIdentifier(ContentSettingsType(j)))
- SetContentSetting(
- pattern, ContentSettingsType(j), "", settings.settings[j]);
- }
- }
- prefs->ClearPref(prefs::kPerHostContentSettings);
- }
+ MigrateObsoletePerhostPref(prefs);
// Read global defaults.
DCHECK_EQ(arraysize(kTypeNames),
@@ -484,7 +457,7 @@ void HostContentSettingsMap::SetDefaultContentSetting(
}
void HostContentSettingsMap::SetContentSetting(
- const Pattern& pattern,
+ const Pattern& original_pattern,
ContentSettingsType content_type,
const std::string& resource_identifier,
ContentSetting setting) {
@@ -493,6 +466,8 @@ void HostContentSettingsMap::SetContentSetting(
DCHECK_NE(RequiresResourceIdentifier(content_type),
resource_identifier.empty());
+ const Pattern pattern(original_pattern.CanonicalizePattern());
+
bool early_exit = false;
std::string pattern_str(pattern.AsString());
PrefService* prefs = NULL;
@@ -861,8 +836,10 @@ void HostContentSettingsMap::ReadDefaultSettings(bool overwrite) {
PrefService* prefs = profile_->GetPrefs();
const DictionaryValue* default_settings_dictionary =
prefs->GetDictionary(prefs::kDefaultContentSettings);
+
if (overwrite)
default_content_settings_ = ContentSettings();
+
// Careful: The returned value could be NULL if the pref has never been set.
if (default_settings_dictionary != NULL) {
GetSettingsFromDictionary(default_settings_dictionary,
@@ -873,12 +850,17 @@ void HostContentSettingsMap::ReadDefaultSettings(bool overwrite) {
void HostContentSettingsMap::ReadExceptions(bool overwrite) {
PrefService* prefs = profile_->GetPrefs();
- const DictionaryValue* all_settings_dictionary =
+ DictionaryValue* all_settings_dictionary =
prefs->GetMutableDictionary(prefs::kContentSettingsPatterns);
+
if (overwrite)
host_content_settings_.clear();
+
// Careful: The returned value could be NULL if the pref has never been set.
if (all_settings_dictionary != NULL) {
+ // Convert all Unicode patterns into punycode form, then read.
+ CanonicalizeContentSettingsExceptions(all_settings_dictionary);
+
for (DictionaryValue::key_iterator i(all_settings_dictionary->begin_keys());
i != all_settings_dictionary->end_keys(); ++i) {
const std::string& pattern(*i);
@@ -915,3 +897,104 @@ void HostContentSettingsMap::UnregisterObservers() {
Source<Profile>(profile_));
profile_ = NULL;
}
+
+void HostContentSettingsMap::MigrateObsoleteCookiePref(PrefService* prefs) {
+ if (prefs->HasPrefPath(prefs::kCookieBehavior)) {
+ int cookie_behavior = prefs->GetInteger(prefs::kCookieBehavior);
+ prefs->ClearPref(prefs::kCookieBehavior);
+ if (!prefs->HasPrefPath(prefs::kDefaultContentSettings)) {
+ SetDefaultContentSetting(CONTENT_SETTINGS_TYPE_COOKIES,
+ (cookie_behavior == net::StaticCookiePolicy::BLOCK_ALL_COOKIES) ?
+ CONTENT_SETTING_BLOCK : CONTENT_SETTING_ALLOW);
+ }
+ if (!prefs->HasPrefPath(prefs::kBlockThirdPartyCookies)) {
+ SetBlockThirdPartyCookies(cookie_behavior ==
+ net::StaticCookiePolicy::BLOCK_THIRD_PARTY_COOKIES);
+ }
+ }
+}
+
+void HostContentSettingsMap::MigrateObsoletePopupsPref(PrefService* prefs) {
+ if (prefs->HasPrefPath(prefs::kPopupWhitelistedHosts)) {
+ const ListValue* whitelist_pref =
+ prefs->GetList(prefs::kPopupWhitelistedHosts);
+ for (ListValue::const_iterator i(whitelist_pref->begin());
+ i != whitelist_pref->end(); ++i) {
+ std::string host;
+ (*i)->GetAsString(&host);
+ SetContentSetting(Pattern(host), CONTENT_SETTINGS_TYPE_POPUPS, "",
+ CONTENT_SETTING_ALLOW);
+ }
+ prefs->ClearPref(prefs::kPopupWhitelistedHosts);
+ }
+}
+
+void HostContentSettingsMap::MigrateObsoletePerhostPref(PrefService* prefs) {
+ if (prefs->HasPrefPath(prefs::kPerHostContentSettings)) {
+ const DictionaryValue* all_settings_dictionary =
+ prefs->GetDictionary(prefs::kPerHostContentSettings);
+ for (DictionaryValue::key_iterator i(all_settings_dictionary->begin_keys());
+ i != all_settings_dictionary->end_keys(); ++i) {
+ const std::string& host(*i);
+ Pattern pattern(std::string(kDomainWildcard) + host);
+ DictionaryValue* host_settings_dictionary = NULL;
+ bool found = all_settings_dictionary->GetDictionaryWithoutPathExpansion(
+ host, &host_settings_dictionary);
+ DCHECK(found);
+ ContentSettings settings;
+ GetSettingsFromDictionary(host_settings_dictionary, &settings);
+ for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) {
+ if (settings.settings[j] != CONTENT_SETTING_DEFAULT &&
+ !RequiresResourceIdentifier(ContentSettingsType(j)))
+ SetContentSetting(
+ pattern, ContentSettingsType(j), "", settings.settings[j]);
+ }
+ }
+ prefs->ClearPref(prefs::kPerHostContentSettings);
+ }
+}
+
+void HostContentSettingsMap::CanonicalizeContentSettingsExceptions(
+ DictionaryValue* all_settings_dictionary) {
+ DCHECK(all_settings_dictionary);
+
+ std::vector<std::string> remove_items;
+ std::vector<std::pair<std::string, std::string> > move_items;
+ for (DictionaryValue::key_iterator i(all_settings_dictionary->begin_keys());
+ i != all_settings_dictionary->end_keys(); ++i) {
+ const std::string& pattern(*i);
+ const std::string canonicalized_pattern =
+ Pattern(pattern).CanonicalizePattern();
+
+ if (canonicalized_pattern.empty() || canonicalized_pattern == pattern)
+ continue;
+
+ // Clear old pattern if prefs already have canonicalized pattern.
+ DictionaryValue* new_pattern_settings_dictionary = NULL;
+ if (all_settings_dictionary->GetDictionaryWithoutPathExpansion(
+ canonicalized_pattern, &new_pattern_settings_dictionary)) {
+ remove_items.push_back(pattern);
+ continue;
+ }
+
+ // Move old pattern to canonicalized pattern.
+ DictionaryValue* old_pattern_settings_dictionary = NULL;
+ if (all_settings_dictionary->GetDictionaryWithoutPathExpansion(
+ pattern, &old_pattern_settings_dictionary)) {
+ move_items.push_back(std::make_pair(pattern, canonicalized_pattern));
+ }
+ }
+
+ for (size_t i = 0; i < remove_items.size(); ++i) {
+ all_settings_dictionary->RemoveWithoutPathExpansion(remove_items[i], NULL);
+ }
+
+ for (size_t i = 0; i < move_items.size(); ++i) {
+ Value* pattern_settings_dictionary = NULL;
+ all_settings_dictionary->RemoveWithoutPathExpansion(
+ move_items[i].first, &pattern_settings_dictionary);
+ all_settings_dictionary->SetWithoutPathExpansion(
+ move_items[i].second, pattern_settings_dictionary);
+ }
+}
+
diff --git a/chrome/browser/host_content_settings_map.h b/chrome/browser/host_content_settings_map.h
index f6021a9..24518bf 100644
--- a/chrome/browser/host_content_settings_map.h
+++ b/chrome/browser/host_content_settings_map.h
@@ -63,6 +63,10 @@ class HostContentSettingsMap
return pattern_ == other.pattern_;
}
+ // Canonicalizes the pattern so that it's ASCII only, either
+ // in original or punycode form.
+ std::string CanonicalizePattern() const;
+
private:
std::string pattern_;
};
@@ -281,6 +285,17 @@ class HostContentSettingsMap
void UnregisterObservers();
+ // Various migration methods (old cookie, popup and per-host data gets
+ // migrated to the new format).
+ void MigrateObsoleteCookiePref(PrefService* prefs);
+ void MigrateObsoletePopupsPref(PrefService* prefs);
+ void MigrateObsoletePerhostPref(PrefService* prefs);
+
+ // Converts all exceptions that have non-canonicalized pattern into
+ // canonicalized pattern. If such pattern already exists, we just remove the
+ // old exception.
+ void CanonicalizeContentSettingsExceptions(DictionaryValue* settings);
+
// The profile we're associated with.
Profile* profile_;
diff --git a/chrome/browser/host_content_settings_map_unittest.cc b/chrome/browser/host_content_settings_map_unittest.cc
index 5bf5894..ea829d4 100644
--- a/chrome/browser/host_content_settings_map_unittest.cc
+++ b/chrome/browser/host_content_settings_map_unittest.cc
@@ -15,6 +15,7 @@
#include "chrome/common/url_constants.h"
#include "chrome/test/testing_profile.h"
#include "googleurl/src/gurl.h"
+#include "net/base/static_cookie_policy.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -248,6 +249,40 @@ TEST_F(HostContentSettingsMapTest, PatternSupport) {
GURL("http://example.org/")));
}
+TEST_F(HostContentSettingsMapTest, CanonicalizePattern) {
+ // Basic patterns.
+ EXPECT_STREQ("[*.]ikea.com", HostContentSettingsMap::Pattern("[*.]ikea.com")
+ .CanonicalizePattern().c_str());
+ EXPECT_STREQ("example.com", HostContentSettingsMap::Pattern("example.com")
+ .CanonicalizePattern().c_str());
+ EXPECT_STREQ("192.168.1.1", HostContentSettingsMap::Pattern("192.168.1.1")
+ .CanonicalizePattern().c_str());
+ EXPECT_STREQ("[::1]", HostContentSettingsMap::Pattern("[::1]")
+ .CanonicalizePattern().c_str());
+ // IsValid returns false for file:/// patterns.
+ EXPECT_STREQ("", HostContentSettingsMap::Pattern(
+ "file:///temp/file.html").CanonicalizePattern().c_str());
+
+ // UTF-8 patterns.
+ EXPECT_STREQ("[*.]xn--ira-ppa.com", HostContentSettingsMap::Pattern(
+ "[*.]\xC4\x87ira.com").CanonicalizePattern().c_str());
+ EXPECT_STREQ("xn--ira-ppa.com", HostContentSettingsMap::Pattern(
+ "\xC4\x87ira.com").CanonicalizePattern().c_str());
+ // IsValid returns false for file:/// patterns.
+ EXPECT_STREQ("", HostContentSettingsMap::Pattern(
+ "file:///\xC4\x87ira.html").CanonicalizePattern().c_str());
+
+ // Invalid patterns.
+ EXPECT_STREQ("", HostContentSettingsMap::Pattern(
+ "*example.com").CanonicalizePattern().c_str());
+ EXPECT_STREQ("", HostContentSettingsMap::Pattern(
+ "example.*").CanonicalizePattern().c_str());
+ EXPECT_STREQ("", HostContentSettingsMap::Pattern(
+ "*\xC4\x87ira.com").CanonicalizePattern().c_str());
+ EXPECT_STREQ("", HostContentSettingsMap::Pattern(
+ "\xC4\x87ira.*").CanonicalizePattern().c_str());
+}
+
TEST_F(HostContentSettingsMapTest, Observer) {
TestingProfile profile;
HostContentSettingsMap* host_content_settings_map =
@@ -529,6 +564,94 @@ TEST_F(HostContentSettingsMapTest, OffTheRecord) {
host, CONTENT_SETTINGS_TYPE_IMAGES, ""));
}
+TEST_F(HostContentSettingsMapTest, MigrateObsoletePrefs) {
+ // This feature is currently behind a flag.
+ CommandLine cl(*CommandLine::ForCurrentProcess());
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableResourceContentSettings);
+
+ TestingProfile profile;
+ PrefService* prefs = profile.GetPrefs();
+
+ // Set obsolete data.
+ prefs->SetInteger(prefs::kCookieBehavior,
+ net::StaticCookiePolicy::BLOCK_ALL_COOKIES);
+
+ ListValue popup_hosts;
+ popup_hosts.Append(new StringValue("[*.]example.com"));
+ prefs->Set(prefs::kPopupWhitelistedHosts, popup_hosts);
+
+ HostContentSettingsMap* host_content_settings_map =
+ profile.GetHostContentSettingsMap();
+
+ EXPECT_EQ(CONTENT_SETTING_BLOCK,
+ host_content_settings_map->GetDefaultContentSetting(
+ CONTENT_SETTINGS_TYPE_COOKIES));
+
+ GURL host("http://example.com");
+ EXPECT_EQ(CONTENT_SETTING_ALLOW,
+ host_content_settings_map->GetContentSetting(
+ host, CONTENT_SETTINGS_TYPE_POPUPS, ""));
+ *CommandLine::ForCurrentProcess() = cl;
+}
+
+// For a single Unicode encoded pattern, check if it gets converted to punycode
+// and old pattern gets deleted.
+TEST_F(HostContentSettingsMapTest, CanonicalizeExceptionsUnicodeOnly) {
+ TestingProfile profile;
+ PrefService* prefs = profile.GetPrefs();
+
+ // Set utf-8 data.
+ DictionaryValue* all_settings_dictionary =
+ prefs->GetMutableDictionary(prefs::kContentSettingsPatterns);
+ ASSERT_TRUE(NULL != all_settings_dictionary);
+
+ DictionaryValue* dummy_payload = new DictionaryValue;
+ dummy_payload->SetInteger("images", CONTENT_SETTING_ALLOW);
+ all_settings_dictionary->SetWithoutPathExpansion("[*.]\xC4\x87ira.com",
+ dummy_payload);
+
+ profile.GetHostContentSettingsMap();
+
+ DictionaryValue* result = NULL;
+ EXPECT_FALSE(all_settings_dictionary->GetDictionaryWithoutPathExpansion(
+ "[*.]\xC4\x87ira.com", &result));
+ EXPECT_TRUE(all_settings_dictionary->GetDictionaryWithoutPathExpansion(
+ "[*.]xn--ira-ppa.com", &result));
+}
+
+// If both Unicode and its punycode pattern exist, make sure we don't touch the
+// settings for the punycode, and that Unicode pattern gets deleted.
+TEST_F(HostContentSettingsMapTest, CanonicalizeExceptionsUnicodeAndPunycode) {
+ // This feature is currently behind a flag.
+ CommandLine cl(*CommandLine::ForCurrentProcess());
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableResourceContentSettings);
+
+ TestingProfile profile;
+
+ scoped_ptr<Value> value(base::JSONReader::Read(
+ "{\"[*.]\\xC4\\x87ira.com\":{\"per_plugin\":{\"pluginx\":2}}}", false));
+ profile.GetPrefs()->Set(prefs::kContentSettingsPatterns, *value);
+
+ // Set punycode equivalent, with different setting.
+ scoped_ptr<Value> puny_value(base::JSONReader::Read(
+ "{\"[*.]xn--ira-ppa.com\":{\"per_plugin\":{\"pluginy\":2}}}", false));
+ profile.GetPrefs()->Set(prefs::kContentSettingsPatterns, *puny_value);
+
+ // Initialize the content map.
+ profile.GetHostContentSettingsMap();
+
+ const DictionaryValue* content_setting_prefs =
+ profile.GetPrefs()->GetDictionary(prefs::kContentSettingsPatterns);
+ std::string prefs_as_json;
+ base::JSONWriter::Write(content_setting_prefs, false, &prefs_as_json);
+ EXPECT_STREQ("{\"[*.]xn--ira-ppa.com\":{\"per_plugin\":{\"pluginy\":2}}}",
+ prefs_as_json.c_str());
+
+ *CommandLine::ForCurrentProcess() = cl;
+}
+
TEST_F(HostContentSettingsMapTest, NonDefaultSettings) {
TestingProfile profile;
HostContentSettingsMap* host_content_settings_map =