summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/app/nibs/ContentExceptionsWindow.xib6
-rw-r--r--chrome/browser/automation/automation_provider.cc3
-rw-r--r--chrome/browser/cocoa/content_blocked_bubble_controller.mm5
-rw-r--r--chrome/browser/cocoa/content_exceptions_window_controller.h4
-rw-r--r--chrome/browser/cocoa/content_exceptions_window_controller.mm66
-rw-r--r--chrome/browser/cocoa/content_exceptions_window_controller_unittest.mm12
-rw-r--r--chrome/browser/content_exceptions_table_model.cc24
-rw-r--r--chrome/browser/content_exceptions_table_model.h7
-rw-r--r--chrome/browser/content_setting_bubble_model.cc5
-rw-r--r--chrome/browser/content_setting_bubble_model.h4
-rw-r--r--chrome/browser/cookie_modal_dialog.cc6
-rw-r--r--chrome/browser/gtk/options/content_exception_editor.cc51
-rw-r--r--chrome/browser/gtk/options/content_exception_editor.h17
-rw-r--r--chrome/browser/gtk/options/content_exceptions_window_gtk.cc33
-rw-r--r--chrome/browser/gtk/options/content_exceptions_window_gtk.h11
-rw-r--r--chrome/browser/host_content_settings_map.cc233
-rw-r--r--chrome/browser/host_content_settings_map.h93
-rw-r--r--chrome/browser/host_content_settings_map_unittest.cc129
-rw-r--r--chrome/browser/renderer_host/render_view_host.cc4
-rw-r--r--chrome/browser/renderer_host/render_view_host.h2
-rw-r--r--chrome/browser/tab_contents/tab_contents.cc13
-rw-r--r--chrome/browser/views/options/exception_editor_view.cc70
-rw-r--r--chrome/browser/views/options/exception_editor_view.h20
-rw-r--r--chrome/browser/views/options/exceptions_view.cc22
-rw-r--r--chrome/browser/views/options/exceptions_view.h9
-rw-r--r--chrome/common/pref_names.cc15
-rw-r--r--chrome/common/pref_names.h4
-rw-r--r--chrome/common/render_messages_internal.h8
-rw-r--r--chrome/renderer/render_thread.cc18
-rw-r--r--chrome/renderer/render_thread.h4
30 files changed, 553 insertions, 345 deletions
diff --git a/chrome/app/nibs/ContentExceptionsWindow.xib b/chrome/app/nibs/ContentExceptionsWindow.xib
index e5b1324..1ccb4c4 100644
--- a/chrome/app/nibs/ContentExceptionsWindow.xib
+++ b/chrome/app/nibs/ContentExceptionsWindow.xib
@@ -3,7 +3,7 @@
<data>
<int key="IBDocument.SystemTarget">1050</int>
<string key="IBDocument.SystemVersion">9L31a</string>
- <string key="IBDocument.InterfaceBuilderVersion">677</string>
+ <string key="IBDocument.InterfaceBuilderVersion">680</string>
<string key="IBDocument.AppKitVersion">949.54</string>
<string key="IBDocument.HIToolboxVersion">353.00</string>
<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
@@ -81,14 +81,14 @@
<object class="NSMutableArray" key="NSTableColumns">
<bool key="EncodedWithXMLCoder">YES</bool>
<object class="NSTableColumn" id="20203331">
- <string key="NSIdentifier">hostname</string>
+ <string key="NSIdentifier">pattern</string>
<double key="NSWidth">3.020000e+02</double>
<double key="NSMinWidth">4.000000e+01</double>
<double key="NSMaxWidth">1.000000e+03</double>
<object class="NSTableHeaderCell" key="NSHeaderCell">
<int key="NSCellFlags">75628096</int>
<int key="NSCellFlags2">2048</int>
- <string key="NSContents">^IDS_EXCEPTIONS_HOSTNAME_HEADER</string>
+ <string key="NSContents">^IDS_EXCEPTIONS_PATTERN_HEADER</string>
<object class="NSFont" key="NSSupport" id="26">
<string key="NSName">LucidaGrande</string>
<double key="NSSize">1.100000e+01</double>
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc
index fc3ba498..f796af5 100644
--- a/chrome/browser/automation/automation_provider.cc
+++ b/chrome/browser/automation/automation_provider.cc
@@ -2913,7 +2913,8 @@ void AutomationProvider::SetContentSetting(
if (host.empty()) {
map->SetDefaultContentSetting(content_type, setting);
} else {
- map->SetContentSetting(host, content_type, setting);
+ map->SetContentSetting(HostContentSettingsMap::Pattern(host),
+ content_type, setting);
}
*success = true;
}
diff --git a/chrome/browser/cocoa/content_blocked_bubble_controller.mm b/chrome/browser/cocoa/content_blocked_bubble_controller.mm
index 0bd90a4..0455da1 100644
--- a/chrome/browser/cocoa/content_blocked_bubble_controller.mm
+++ b/chrome/browser/cocoa/content_blocked_bubble_controller.mm
@@ -186,9 +186,8 @@ NSTextField* LabelWithFrame(NSString* text, const NSRect& frame) {
// Copy |host_| into radio group label.
NSCell* radioCell = [allowBlockRadioGroup_ cellWithTag:kAllowTag];
- [radioCell setTitle:ReplaceNSStringPlaceholders([radioCell title],
- UTF8ToUTF16(radioGroup.host),
- NULL)];
+ [radioCell setTitle:ReplaceNSStringPlaceholders(
+ [radioCell title], UTF8ToUTF16(radioGroup.url.host()), NULL)];
// Layout radio group labels post-localization.
[GTMUILocalizerAndLayoutTweaker
diff --git a/chrome/browser/cocoa/content_exceptions_window_controller.h b/chrome/browser/cocoa/content_exceptions_window_controller.h
index c3344ca..91a5b33 100644
--- a/chrome/browser/cocoa/content_exceptions_window_controller.h
+++ b/chrome/browser/cocoa/content_exceptions_window_controller.h
@@ -40,9 +40,9 @@ class UpdatingContentSettingsObserver;
// is used to suppress updates at bad times.
BOOL updatesEnabled_;
- // This is non-NULL only while a new element is being added and its host
+ // This is non-NULL only while a new element is being added and its pattern
// is being edited.
- scoped_ptr<HostContentSettingsMap::HostSettingPair> newException_;
+ scoped_ptr<HostContentSettingsMap::PatternSettingPair> newException_;
}
// Shows or makes frontmost the content exceptions window for |settingsType|.
diff --git a/chrome/browser/cocoa/content_exceptions_window_controller.mm b/chrome/browser/cocoa/content_exceptions_window_controller.mm
index 6c2c7c8..de51985 100644
--- a/chrome/browser/cocoa/content_exceptions_window_controller.mm
+++ b/chrome/browser/cocoa/content_exceptions_window_controller.mm
@@ -13,14 +13,13 @@
#include "chrome/common/notification_registrar.h"
#include "chrome/common/notification_service.h"
#include "grit/generated_resources.h"
-#include "net/base/net_util.h"
#include "third_party/GTM/AppKit/GTMUILocalizerAndLayoutTweaker.h"
@interface ContentExceptionsWindowController (Private)
- (id)initWithType:(ContentSettingsType)settingsType
settingsMap:(HostContentSettingsMap*)settingsMap;
- (void)updateRow:(NSInteger)row
- withEntry:(const HostContentSettingsMap::HostSettingPair&)entry;
+ withEntry:(const HostContentSettingsMap::PatternSettingPair&)entry;
- (void)adjustEditingButtons;
- (void)modelDidChange;
- (size_t)menuItemCount;
@@ -30,13 +29,13 @@
@end
////////////////////////////////////////////////////////////////////////////////
-// HostnameFormatter
+// PatternFormatter
-// A simple formatter that accepts text that vaguely looks like a hostname.
-@interface HostnameFormatter : NSFormatter
+// A simple formatter that accepts text that vaguely looks like a pattern.
+@interface PatternFormatter : NSFormatter
@end
-@implementation HostnameFormatter
+@implementation PatternFormatter
- (NSString*)stringForObjectValue:(id)object {
if (![object isKindOfClass:[NSString class]])
return nil;
@@ -47,15 +46,14 @@
forString:(NSString*)string
errorDescription:(NSString**)error {
if ([string length]) {
- url_canon::CanonHostInfo hostInfo;
- if (!net::CanonicalizeHost(
- base::SysNSStringToUTF8(string), &hostInfo).empty()) {
+ if (HostContentSettingsMap::Pattern(
+ base::SysNSStringToUTF8(string)).IsValid()) {
*object = string;
return YES;
}
}
if (error)
- *error = @"Invalid hostname";
+ *error = @"Invalid pattern";
return NO;
}
@@ -202,9 +200,9 @@ static ContentExceptionsWindowController*
[[tableView_ tableColumnWithIdentifier:@"action"] dataCell];
[menuCell setMenu:menu.get()];
- NSCell* hostCell =
- [[tableView_ tableColumnWithIdentifier:@"hostname"] dataCell];
- [hostCell setFormatter:[[[HostnameFormatter alloc] init] autorelease]];
+ NSCell* patternCell =
+ [[tableView_ tableColumnWithIdentifier:@"pattern"] dataCell];
+ [patternCell setFormatter:[[[PatternFormatter alloc] init] autorelease]];
// Give the button bar on the bottom of the window the "iTunes/iChat" look.
[[self window] setAutorecalculatesContentBorderThickness:NO
@@ -225,7 +223,7 @@ static ContentExceptionsWindowController*
return newException_.get() != NULL;
}
-// Let esc cancel editing if the user is currently editing a hostname. Else, let
+// Let esc cancel editing if the user is currently editing a pattern. Else, let
// esc close the window.
- (void)cancel:(id)sender {
if ([tableView_ currentEditor] != nil) {
@@ -268,13 +266,14 @@ static ContentExceptionsWindowController*
- (IBAction)addException:(id)sender {
if (newException_.get()) {
- // The invariant is that |newException_| is non-NULL exactly if the host of
- // a new exception is currently being edited - so there's nothing to do in
- // that case.
+ // The invariant is that |newException_| is non-NULL exactly if the pattern
+ // of a new exception is currently being edited - so there's nothing to do
+ // in that case.
return;
}
- newException_.reset(new HostContentSettingsMap::HostSettingPair);
- newException_->first = "example.com";
+ newException_.reset(new HostContentSettingsMap::PatternSettingPair);
+ newException_->first = HostContentSettingsMap::Pattern(
+ l10n_util::GetStringUTF8(IDS_EXCEPTIONS_SAMPLE_PATTERN));
newException_->second = CONTENT_SETTING_BLOCK;
[tableView_ reloadData];
@@ -320,7 +319,7 @@ static ContentExceptionsWindowController*
- (id)tableView:(NSTableView*)tv
objectValueForTableColumn:(NSTableColumn*)tableColumn
row:(NSInteger)row {
- const HostContentSettingsMap::HostSettingPair* entry;
+ const HostContentSettingsMap::PatternSettingPair* entry;
if (newException_.get() && row >= model_->RowCount())
entry = newException_.get();
else
@@ -328,8 +327,8 @@ static ContentExceptionsWindowController*
NSObject* result = nil;
NSString* identifier = [tableColumn identifier];
- if ([identifier isEqualToString:@"hostname"]) {
- result = base::SysUTF8ToNSString(entry->first);
+ if ([identifier isEqualToString:@"pattern"]) {
+ result = base::SysUTF8ToNSString(entry->first.AsString());
} else if ([identifier isEqualToString:@"action"]) {
result = [NSNumber numberWithInt:[self indexForSetting:entry->second]];
} else {
@@ -340,7 +339,7 @@ static ContentExceptionsWindowController*
// Updates exception at |row| to contain the data in |entry|.
- (void)updateRow:(NSInteger)row
- withEntry:(const HostContentSettingsMap::HostSettingPair&)entry {
+ withEntry:(const HostContentSettingsMap::PatternSettingPair&)entry {
// TODO(thakis): This apparently moves an edited row to the back of the list.
// It's what windows and linux do, but it's kinda sucky. Fix.
// http://crbug.com/36904
@@ -352,7 +351,7 @@ static ContentExceptionsWindowController*
[self modelDidChange];
// For now, at least re-select the edited element.
- int newIndex = model_->IndexOfExceptionByHost(entry.first);
+ int newIndex = model_->IndexOfExceptionByPattern(entry.first);
DCHECK(newIndex != -1);
[tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:newIndex]
byExtendingSelection:NO];
@@ -366,7 +365,7 @@ static ContentExceptionsWindowController*
// calls this method if a cell is currently being edited. Do not commit edits
// of rows that are about to be deleted.
if (!updatesEnabled_) {
- // If this method gets called, the host filed of the new exception can no
+ // If this method gets called, the pattern filed of the new exception can no
// longer be being edited. Reset |newException_| to keep the invariant true.
newException_.reset();
return;
@@ -374,14 +373,15 @@ static ContentExceptionsWindowController*
// Get model object.
bool isNewRow = newException_.get() && row >= model_->RowCount();
- HostContentSettingsMap::HostSettingPair originalEntry =
+ HostContentSettingsMap::PatternSettingPair originalEntry =
isNewRow ? *newException_ : model_->entry_at(row);
- HostContentSettingsMap::HostSettingPair entry = originalEntry;
+ HostContentSettingsMap::PatternSettingPair entry = originalEntry;
// Modify it.
NSString* identifier = [tableColumn identifier];
- if ([identifier isEqualToString:@"hostname"]) {
- entry.first = base::SysNSStringToUTF8(object);
+ if ([identifier isEqualToString:@"pattern"]) {
+ entry.first = HostContentSettingsMap::Pattern(
+ base::SysNSStringToUTF8(object));
}
if ([identifier isEqualToString:@"action"]) {
int index = [object intValue];
@@ -391,14 +391,14 @@ static ContentExceptionsWindowController*
// Commit modification, if any.
if (isNewRow) {
newException_.reset();
- if (![identifier isEqualToString:@"hostname"]) {
+ if (![identifier isEqualToString:@"pattern"]) {
[tableView_ reloadData];
[self adjustEditingButtons];
- return; // Commit new rows only when the hostname has been set.
+ return; // Commit new rows only when the pattern has been set.
}
- int newIndex = model_->IndexOfExceptionByHost(entry.first);
+ int newIndex = model_->IndexOfExceptionByPattern(entry.first);
if (newIndex != -1) {
- // The new host was already in the table. Focus existing row instead of
+ // The new pattern was already in the table. Focus existing row instead of
// overwriting it with a new one.
[tableView_ selectRowIndexes:[NSIndexSet indexSetWithIndex:newIndex]
byExtendingSelection:NO];
diff --git a/chrome/browser/cocoa/content_exceptions_window_controller_unittest.mm b/chrome/browser/cocoa/content_exceptions_window_controller_unittest.mm
index 09a1646..2256f2c 100644
--- a/chrome/browser/cocoa/content_exceptions_window_controller_unittest.mm
+++ b/chrome/browser/cocoa/content_exceptions_window_controller_unittest.mm
@@ -150,7 +150,7 @@ TEST_F(ContentExceptionsWindowControllerTest, Add) {
settingsMap_->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_PLUGINS,
&settings);
EXPECT_EQ(1u, settings.size());
- EXPECT_EQ("addedhost", settings[0].first);
+ EXPECT_EQ(HostContentSettingsMap::Pattern("addedhost"), settings[0].first);
}
TEST_F(ContentExceptionsWindowControllerTest, AddEscDoesNotAdd) {
@@ -190,8 +190,9 @@ TEST_F(ContentExceptionsWindowControllerTest, AddEditAddAdd) {
}
TEST_F(ContentExceptionsWindowControllerTest, AddExistingEditAdd) {
- settingsMap_->SetContentSetting(
- "myhost", CONTENT_SETTINGS_TYPE_PLUGINS, CONTENT_SETTING_BLOCK);
+ settingsMap_->SetContentSetting(HostContentSettingsMap::Pattern("myhost"),
+ CONTENT_SETTINGS_TYPE_PLUGINS,
+ CONTENT_SETTING_BLOCK);
ContentExceptionsWindowController* controller =
GetController(CONTENT_SETTINGS_TYPE_PLUGINS);
@@ -211,8 +212,9 @@ TEST_F(ContentExceptionsWindowControllerTest, AddExistingEditAdd) {
}
TEST_F(ContentExceptionsWindowControllerTest, AddExistingDoesNotOverwrite) {
- settingsMap_->SetContentSetting(
- "myhost", CONTENT_SETTINGS_TYPE_COOKIES, CONTENT_SETTING_ASK);
+ settingsMap_->SetContentSetting(HostContentSettingsMap::Pattern("myhost"),
+ CONTENT_SETTINGS_TYPE_COOKIES,
+ CONTENT_SETTING_ASK);
ContentExceptionsWindowController* controller =
GetController(CONTENT_SETTINGS_TYPE_COOKIES);
diff --git a/chrome/browser/content_exceptions_table_model.cc b/chrome/browser/content_exceptions_table_model.cc
index 4d4eda9..93efed5 100644
--- a/chrome/browser/content_exceptions_table_model.cc
+++ b/chrome/browser/content_exceptions_table_model.cc
@@ -20,16 +20,18 @@ ContentExceptionsTableModel::ContentExceptionsTableModel(
map->GetSettingsForOneType(type, &entries_);
}
-void ContentExceptionsTableModel::AddException(const std::string& host,
- ContentSetting setting) {
- entries_.push_back(HostContentSettingsMap::HostSettingPair(host, setting));
- map_->SetContentSetting(host, content_type_, setting);
+void ContentExceptionsTableModel::AddException(
+ const HostContentSettingsMap::Pattern& pattern,
+ ContentSetting setting) {
+ entries_.push_back(
+ HostContentSettingsMap::PatternSettingPair(pattern, setting));
+ map_->SetContentSetting(pattern, content_type_, setting);
if (observer_)
observer_->OnItemsAdded(RowCount() - 1, 1);
}
void ContentExceptionsTableModel::RemoveException(int row) {
- const HostContentSettingsMap::HostSettingPair& pair = entries_[row];
+ const HostContentSettingsMap::PatternSettingPair& pair = entries_[row];
map_->SetContentSetting(pair.first, content_type_, CONTENT_SETTING_DEFAULT);
entries_.erase(entries_.begin() + row);
if (observer_)
@@ -44,12 +46,12 @@ void ContentExceptionsTableModel::RemoveAll() {
observer_->OnItemsRemoved(0, old_row_count);
}
-int ContentExceptionsTableModel::IndexOfExceptionByHost(
- const std::string& host) {
+int ContentExceptionsTableModel::IndexOfExceptionByPattern(
+ const HostContentSettingsMap::Pattern& pattern) {
// 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_.size(); ++i) {
- if (entries_[i].first == host)
+ if (entries_[i].first == pattern)
return static_cast<int>(i);
}
return -1;
@@ -60,11 +62,11 @@ int ContentExceptionsTableModel::RowCount() {
}
std::wstring ContentExceptionsTableModel::GetText(int row, int column_id) {
- HostContentSettingsMap::HostSettingPair entry = entries_[row];
+ HostContentSettingsMap::PatternSettingPair entry = entries_[row];
switch (column_id) {
- case IDS_EXCEPTIONS_HOSTNAME_HEADER:
- return UTF8ToWide(entry.first);
+ case IDS_EXCEPTIONS_PATTERN_HEADER:
+ return UTF8ToWide(entry.first.AsString());
case IDS_EXCEPTIONS_ACTION_HEADER:
switch (entry.second) {
diff --git a/chrome/browser/content_exceptions_table_model.h b/chrome/browser/content_exceptions_table_model.h
index 9ade4d8..da8889e 100644
--- a/chrome/browser/content_exceptions_table_model.h
+++ b/chrome/browser/content_exceptions_table_model.h
@@ -20,12 +20,13 @@ class ContentExceptionsTableModel : public TableModel {
HostContentSettingsMap* map() const { return map_; }
ContentSettingsType content_type() const { return content_type_; }
- const HostContentSettingsMap::HostSettingPair& entry_at(int index) {
+ const HostContentSettingsMap::PatternSettingPair& entry_at(int index) {
return entries_[index];
}
// Adds a new exception on the map and table model.
- void AddException(const std::string& host, ContentSetting setting);
+ void AddException(const HostContentSettingsMap::Pattern& pattern,
+ ContentSetting setting);
// Removes the exception at the specified index from both the map and model.
void RemoveException(int row);
@@ -35,7 +36,7 @@ class ContentExceptionsTableModel : public TableModel {
// Returns the index of the specified exception given a host, or -1 if there
// is no exception for the specified host.
- int IndexOfExceptionByHost(const std::string& host);
+ int IndexOfExceptionByPattern(const HostContentSettingsMap::Pattern& pattern);
// TableModel overrides:
virtual int RowCount();
diff --git a/chrome/browser/content_setting_bubble_model.cc b/chrome/browser/content_setting_bubble_model.cc
index 573111a..1318ac0 100644
--- a/chrome/browser/content_setting_bubble_model.cc
+++ b/chrome/browser/content_setting_bubble_model.cc
@@ -80,7 +80,7 @@ class ContentSettingSingleRadioGroup : public ContentSettingTitleAndLinkModel {
std::string display_host(WideToUTF8(display_host_wide));
RadioGroup radio_group;
- radio_group.host = url.host();
+ radio_group.url = url;
static const int kAllowIDs[] = {
0, // We don't manage cookies here.
@@ -120,7 +120,8 @@ class ContentSettingSingleRadioGroup : public ContentSettingTitleAndLinkModel {
virtual void OnRadioClicked(int radio_group, int radio_index) {
profile()->GetHostContentSettingsMap()->SetContentSetting(
- bubble_content().radio_groups[radio_group].host,
+ HostContentSettingsMap::Pattern::FromURL(
+ bubble_content().radio_groups[radio_group].url),
content_type(),
radio_index == 0 ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK);
}
diff --git a/chrome/browser/content_setting_bubble_model.h b/chrome/browser/content_setting_bubble_model.h
index f506b48..5c21460 100644
--- a/chrome/browser/content_setting_bubble_model.h
+++ b/chrome/browser/content_setting_bubble_model.h
@@ -12,9 +12,9 @@
#include "chrome/common/content_settings.h"
#include "chrome/common/notification_observer.h"
#include "chrome/common/notification_registrar.h"
+#include "googleurl/src/gurl.h"
#include "third_party/skia/include/core/SkBitmap.h"
-class GURL;
class Profile;
class SkBitmap;
class TabContents;
@@ -41,7 +41,7 @@ class ContentSettingBubbleModel : public NotificationObserver {
typedef std::vector<std::string> RadioItems;
struct RadioGroup {
- std::string host;
+ GURL url;
std::string title;
RadioItems radio_items;
int default_item;
diff --git a/chrome/browser/cookie_modal_dialog.cc b/chrome/browser/cookie_modal_dialog.cc
index 4435bcb..1e1526c 100644
--- a/chrome/browser/cookie_modal_dialog.cc
+++ b/chrome/browser/cookie_modal_dialog.cc
@@ -101,7 +101,8 @@ void CookiePromptModalDialog::AllowSiteData(bool remember,
bool session_expire) {
if (remember) {
host_content_settings_map_->SetContentSetting(
- origin_.host(), CONTENT_SETTINGS_TYPE_COOKIES, CONTENT_SETTING_ALLOW);
+ HostContentSettingsMap::Pattern::FromURL(origin_),
+ CONTENT_SETTINGS_TYPE_COOKIES, CONTENT_SETTING_ALLOW);
}
if (delegate_) {
@@ -113,7 +114,8 @@ void CookiePromptModalDialog::AllowSiteData(bool remember,
void CookiePromptModalDialog::BlockSiteData(bool remember) {
if (remember) {
host_content_settings_map_->SetContentSetting(
- origin_.host(), CONTENT_SETTINGS_TYPE_COOKIES, CONTENT_SETTING_BLOCK);
+ HostContentSettingsMap::Pattern::FromURL(origin_),
+ CONTENT_SETTINGS_TYPE_COOKIES, CONTENT_SETTING_BLOCK);
}
if (delegate_) {
diff --git a/chrome/browser/gtk/options/content_exception_editor.cc b/chrome/browser/gtk/options/content_exception_editor.cc
index 9e73704..264282f 100644
--- a/chrome/browser/gtk/options/content_exception_editor.cc
+++ b/chrome/browser/gtk/options/content_exception_editor.cc
@@ -11,37 +11,21 @@
#include "chrome/browser/content_exceptions_table_model.h"
#include "chrome/browser/gtk/gtk_util.h"
#include "chrome/browser/host_content_settings_map.h"
-#include "googleurl/src/url_canon.h"
-#include "googleurl/src/url_parse.h"
#include "grit/app_resources.h"
#include "grit/generated_resources.h"
-#include "net/base/net_util.h"
-
-namespace {
-
-// Returns true if the host name is valid.
-bool ValidHost(const std::string& host) {
- if (host.empty())
- return false;
-
- url_canon::CanonHostInfo host_info;
- return !net::CanonicalizeHost(host, &host_info).empty();
-}
-
-} // namespace
ContentExceptionEditor::ContentExceptionEditor(
GtkWindow* parent,
ContentExceptionEditor::Delegate* delegate,
ContentExceptionsTableModel* model,
int index,
- const std::string& host,
+ const HostContentSettingsMap::Pattern& pattern,
ContentSetting setting)
: delegate_(delegate),
model_(model),
cb_model_(model->content_type() == CONTENT_SETTINGS_TYPE_COOKIES),
index_(index),
- host_(host),
+ pattern_(pattern),
setting_(setting) {
dialog_ = gtk_dialog_new_with_buttons(
l10n_util::GetStringUTF8(is_new() ?
@@ -58,11 +42,11 @@ ContentExceptionEditor::ContentExceptionEditor(
gtk_dialog_set_default_response(GTK_DIALOG(dialog_), GTK_RESPONSE_OK);
entry_ = gtk_entry_new();
- gtk_entry_set_text(GTK_ENTRY(entry_), host_.c_str());
+ gtk_entry_set_text(GTK_ENTRY(entry_), pattern_.AsString().c_str());
g_signal_connect(entry_, "changed", G_CALLBACK(OnEntryChangedThunk), this);
gtk_entry_set_activates_default(GTK_ENTRY(entry_), TRUE);
- host_image_ = gtk_image_new_from_pixbuf(NULL);
+ pattern_image_ = gtk_image_new_from_pixbuf(NULL);
action_combo_ = gtk_combo_box_new_text();
for (int i = 0; i < cb_model_.GetItemCount(); ++i) {
@@ -74,8 +58,8 @@ ContentExceptionEditor::ContentExceptionEditor(
GtkWidget* table = gtk_util::CreateLabeledControlsGroup(
NULL,
- l10n_util::GetStringUTF8(IDS_EXCEPTION_EDITOR_HOST_TITLE).c_str(),
- gtk_util::CreateEntryImageHBox(entry_, host_image_),
+ l10n_util::GetStringUTF8(IDS_EXCEPTION_EDITOR_PATTERN_TITLE).c_str(),
+ gtk_util::CreateEntryImageHBox(entry_, pattern_image_),
l10n_util::GetStringUTF8(IDS_EXCEPTION_EDITOR_ACTION_TITLE).c_str(),
action_combo_,
NULL);
@@ -94,12 +78,13 @@ ContentExceptionEditor::ContentExceptionEditor(
g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroyThunk), this);
}
-bool ContentExceptionEditor::IsHostValid(const std::string& host) const {
- bool is_valid_host = ValidHost(host) &&
- (model_->IndexOfExceptionByHost(host) == -1);
+bool ContentExceptionEditor::IsPatternValid(
+ const HostContentSettingsMap::Pattern& pattern) const {
+ bool is_valid_pattern = pattern.IsValid() &&
+ (model_->IndexOfExceptionByPattern(pattern) == -1);
- return is_new() ? is_valid_host : (!host.empty() &&
- ((host_ == host) || is_valid_host));
+ return is_new() ? is_valid_pattern : (!pattern.AsString().empty() &&
+ ((pattern_ == pattern) || is_valid_pattern));
}
void ContentExceptionEditor::UpdateImage(GtkWidget* image, bool is_valid) {
@@ -109,20 +94,22 @@ void ContentExceptionEditor::UpdateImage(GtkWidget* image, bool is_valid) {
}
void ContentExceptionEditor::OnEntryChanged(GtkWidget* entry) {
- std::string new_host = gtk_entry_get_text(GTK_ENTRY(entry));
- bool is_valid = IsHostValid(new_host);
+ HostContentSettingsMap::Pattern new_pattern(
+ gtk_entry_get_text(GTK_ENTRY(entry)));
+ bool is_valid = IsPatternValid(new_pattern);
gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog_),
GTK_RESPONSE_OK, is_valid);
- UpdateImage(host_image_, is_valid);
+ UpdateImage(pattern_image_, is_valid);
}
void ContentExceptionEditor::OnResponse(GtkWidget* sender, int response_id) {
if (response_id == GTK_RESPONSE_OK) {
// Notify our delegate to update everything.
- std::string new_host = gtk_entry_get_text(GTK_ENTRY(entry_));
+ HostContentSettingsMap::Pattern new_pattern(
+ gtk_entry_get_text(GTK_ENTRY(entry_)));
ContentSetting setting = cb_model_.SettingForIndex(
gtk_combo_box_get_active(GTK_COMBO_BOX(action_combo_)));
- delegate_->AcceptExceptionEdit(new_host, setting, index_, is_new());
+ delegate_->AcceptExceptionEdit(new_pattern, setting, index_, is_new());
}
gtk_widget_destroy(dialog_);
diff --git a/chrome/browser/gtk/options/content_exception_editor.h b/chrome/browser/gtk/options/content_exception_editor.h
index 405240c..5bd7ad0 100644
--- a/chrome/browser/gtk/options/content_exception_editor.h
+++ b/chrome/browser/gtk/options/content_exception_editor.h
@@ -23,10 +23,11 @@ class ContentExceptionEditor {
class Delegate {
public:
// Invoked when the user accepts the edit.
- virtual void AcceptExceptionEdit(const std::string& host,
- ContentSetting setting,
- int index,
- bool is_new) = 0;
+ virtual void AcceptExceptionEdit(
+ const HostContentSettingsMap::Pattern& pattern,
+ ContentSetting setting,
+ int index,
+ bool is_new) = 0;
protected:
virtual ~Delegate() {}
@@ -36,14 +37,14 @@ class ContentExceptionEditor {
Delegate* delegate,
ContentExceptionsTableModel* model,
int index,
- const std::string& host,
+ const HostContentSettingsMap::Pattern& pattern,
ContentSetting setting);
private:
// Returns true if we're adding a new item.
bool is_new() const { return index_ == -1; }
- bool IsHostValid(const std::string& host) const;
+ bool IsPatternValid(const HostContentSettingsMap::Pattern& pattern) const;
void UpdateImage(GtkWidget* image, bool is_valid);
@@ -60,13 +61,13 @@ class ContentExceptionEditor {
// Index of the item being edited. If -1, indicates this is a new entry.
const int index_;
- const std::string host_;
+ const HostContentSettingsMap::Pattern pattern_;
const ContentSetting setting_;
// UI widgets.
GtkWidget* dialog_;
GtkWidget* entry_;
- GtkWidget* host_image_;
+ GtkWidget* pattern_image_;
GtkWidget* action_combo_;
DISALLOW_COPY_AND_ASSIGN(ContentExceptionEditor);
diff --git a/chrome/browser/gtk/options/content_exceptions_window_gtk.cc b/chrome/browser/gtk/options/content_exceptions_window_gtk.cc
index 4106be2..d92aa25 100644
--- a/chrome/browser/gtk/options/content_exceptions_window_gtk.cc
+++ b/chrome/browser/gtk/options/content_exceptions_window_gtk.cc
@@ -56,12 +56,12 @@ ContentExceptionsWindowGtk::ContentExceptionsWindowGtk(
g_signal_connect(treeview_, "row-activated",
G_CALLBACK(OnTreeViewRowActivateThunk), this);
- GtkTreeViewColumn* hostname_column = gtk_tree_view_column_new_with_attributes(
- l10n_util::GetStringUTF8(IDS_EXCEPTIONS_HOSTNAME_HEADER).c_str(),
+ GtkTreeViewColumn* pattern_column = gtk_tree_view_column_new_with_attributes(
+ l10n_util::GetStringUTF8(IDS_EXCEPTIONS_PATTERN_HEADER).c_str(),
gtk_cell_renderer_text_new(),
- "text", COL_HOSTNAME,
+ "text", COL_PATTERN,
NULL);
- gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_), hostname_column);
+ gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_), pattern_column);
GtkTreeViewColumn* action_column = gtk_tree_view_column_new_with_attributes(
l10n_util::GetStringUTF8(IDS_EXCEPTIONS_ACTION_HEADER).c_str(),
@@ -147,24 +147,26 @@ ContentExceptionsWindowGtk::ContentExceptionsWindowGtk(
}
void ContentExceptionsWindowGtk::SetColumnValues(int row, GtkTreeIter* iter) {
- std::wstring hostname = model_->GetText(row, IDS_EXCEPTIONS_HOSTNAME_HEADER);
- gtk_list_store_set(list_store_, iter, COL_HOSTNAME,
- WideToUTF8(hostname).c_str(), -1);
+ std::wstring pattern = model_->GetText(row, IDS_EXCEPTIONS_PATTERN_HEADER);
+ gtk_list_store_set(list_store_, iter, COL_PATTERN,
+ WideToUTF8(pattern).c_str(), -1);
std::wstring action = model_->GetText(row, IDS_EXCEPTIONS_ACTION_HEADER);
gtk_list_store_set(list_store_, iter, COL_ACTION,
WideToUTF8(action).c_str(), -1);
}
-void ContentExceptionsWindowGtk::AcceptExceptionEdit(const std::string& host,
- ContentSetting setting,
- int index,
- bool is_new) {
+void ContentExceptionsWindowGtk::AcceptExceptionEdit(
+ const HostContentSettingsMap::Pattern& pattern,
+ ContentSetting setting,
+ int index,
+ bool is_new) {
if (!is_new)
model_->RemoveException(index);
- model_->AddException(host, setting);
- int new_index = model_->IndexOfExceptionByHost(host);
+ model_->AddException(pattern, setting);
+
+ int new_index = model_->IndexOfExceptionByPattern(pattern);
DCHECK_NE(-1, new_index);
GtkTreePath* path = gtk_tree_path_new_from_indices(new_index, -1);
@@ -189,7 +191,8 @@ void ContentExceptionsWindowGtk::UpdateButtonState() {
void ContentExceptionsWindowGtk::Add(GtkWidget* widget) {
new ContentExceptionEditor(GTK_WINDOW(dialog_),
- this, model_.get(), -1, std::string(),
+ this, model_.get(), -1,
+ HostContentSettingsMap::Pattern(),
CONTENT_SETTING_BLOCK);
}
@@ -198,7 +201,7 @@ void ContentExceptionsWindowGtk::Edit(GtkWidget* widget) {
gtk_tree::GetSelectedIndicies(treeview_selection_, &indices);
DCHECK_GT(indices.size(), 0u);
int index = *indices.begin();
- const HostContentSettingsMap::HostSettingPair& entry =
+ const HostContentSettingsMap::PatternSettingPair& entry =
model_->entry_at(index);
new ContentExceptionEditor(GTK_WINDOW(dialog_), this, model_.get(), index,
entry.first, entry.second);
diff --git a/chrome/browser/gtk/options/content_exceptions_window_gtk.h b/chrome/browser/gtk/options/content_exceptions_window_gtk.h
index 5607fef..c415419 100644
--- a/chrome/browser/gtk/options/content_exceptions_window_gtk.h
+++ b/chrome/browser/gtk/options/content_exceptions_window_gtk.h
@@ -34,15 +34,16 @@ class ContentExceptionsWindowGtk : public gtk_tree::TableAdapter::Delegate,
virtual void SetColumnValues(int row, GtkTreeIter* iter);
// ContentExceptionEditor::Delegate implementation:
- virtual void AcceptExceptionEdit(const std::string& host,
- ContentSetting setting,
- int index,
- bool is_new);
+ virtual void AcceptExceptionEdit(
+ const HostContentSettingsMap::Pattern& pattern,
+ ContentSetting setting,
+ int index,
+ bool is_new);
private:
// Column ids for |list_store_|.
enum {
- COL_HOSTNAME,
+ COL_PATTERN,
COL_ACTION,
COL_COUNT
};
diff --git a/chrome/browser/host_content_settings_map.cc b/chrome/browser/host_content_settings_map.cc
index a45dc8e..fd7517a 100644
--- a/chrome/browser/host_content_settings_map.cc
+++ b/chrome/browser/host_content_settings_map.cc
@@ -4,6 +4,7 @@
#include "chrome/browser/host_content_settings_map.h"
+#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/pref_service.h"
@@ -12,9 +13,71 @@
#include "chrome/common/notification_type.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
+#include "googleurl/src/gurl.h"
+#include "googleurl/src/url_canon.h"
+#include "googleurl/src/url_parse.h"
#include "net/base/dns_util.h"
+#include "net/base/net_util.h"
#include "net/base/static_cookie_policy.h"
+namespace {
+// The version of the pattern format implemented. Version 1 includes the
+// following patterns:
+// - [*.]domain.tld (matches domain.tld and all sub-domains)
+// - host (matches an exact hostname)
+// - a.b.c.d (matches an exact IPv4 ip)
+// - [a:b:c:d:e:f:g:h] (matches an exact IPv6 ip)
+const int kContentSettingsPatternVersion = 1;
+
+// The format of a domain wildcard.
+const char kDomainWildcard[] = "[*.]";
+
+// The length of kDomainWildcard (without the trailing '\0')
+const size_t kDomainWildcardLength = arraysize(kDomainWildcard) - 1;
+
+// Returns the host part of an URL, or the spec, if no host is present.
+std::string HostFromURL(const GURL& url) {
+ return url.has_host() ? net::TrimEndingDot(url.host()) : url.spec();
+}
+} // namespace
+
+// static
+HostContentSettingsMap::Pattern HostContentSettingsMap::Pattern::FromURL(
+ const GURL& url) {
+ return Pattern(!url.has_host() || url.HostIsIPAddress() ?
+ HostFromURL(url) : std::string(kDomainWildcard) + url.host());
+}
+
+bool HostContentSettingsMap::Pattern::IsValid() const {
+ if (pattern_.empty())
+ return false;
+
+ const std::string host(pattern_.length() > kDomainWildcardLength &&
+ StartsWithASCII(pattern_, kDomainWildcard, false) ?
+ pattern_.substr(kDomainWildcardLength) :
+ pattern_);
+ url_canon::CanonHostInfo host_info;
+ return host.find('*') == std::string::npos &&
+ !net::CanonicalizeHost(host, &host_info).empty();
+}
+
+bool HostContentSettingsMap::Pattern::Matches(const GURL& url) const {
+ if (!IsValid())
+ return false;
+
+ const std::string host(HostFromURL(url));
+ if (pattern_.length() < kDomainWildcardLength ||
+ !StartsWithASCII(pattern_, kDomainWildcard, false))
+ return pattern_ == host;
+
+ const size_t match =
+ host.rfind(pattern_.substr(kDomainWildcardLength));
+
+ return (match != std::string::npos) &&
+ (match == 0 || host[match - 1] == '.') &&
+ (match + pattern_.length() - kDomainWildcardLength == host.length());
+}
+
// static
const wchar_t*
HostContentSettingsMap::kTypeNames[CONTENT_SETTINGS_NUM_TYPES] = {
@@ -65,12 +128,35 @@ HostContentSettingsMap::HostContentSettingsMap(Profile* profile)
i != whitelist_pref->end(); ++i) {
std::string host;
(*i)->GetAsString(&host);
- SetContentSetting(host, CONTENT_SETTINGS_TYPE_POPUPS,
+ SetContentSetting(Pattern(host), CONTENT_SETTINGS_TYPE_POPUPS,
CONTENT_SETTING_ALLOW);
}
prefs->ClearPref(prefs::kPopupWhitelistedHosts);
}
+ // 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) {
+ std::wstring wide_host(*i);
+ Pattern pattern(std::string(kDomainWildcard) + WideToUTF8(wide_host));
+ DictionaryValue* host_settings_dictionary = NULL;
+ bool found = all_settings_dictionary->GetDictionaryWithoutPathExpansion(
+ wide_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)
+ SetContentSetting(
+ pattern, ContentSettingsType(j), settings.settings[j]);
+ }
+ }
+ prefs->ClearPref(prefs::kPerHostContentSettings);
+ }
+
// Read global defaults.
DCHECK_EQ(arraysize(kTypeNames),
static_cast<size_t>(CONTENT_SETTINGS_NUM_TYPES));
@@ -83,33 +169,48 @@ HostContentSettingsMap::HostContentSettingsMap(Profile* profile)
}
ForceDefaultsToBeExplicit();
- // Read host-specific exceptions.
+ // Read misc. global settings.
+ block_third_party_cookies_ =
+ prefs->GetBoolean(prefs::kBlockThirdPartyCookies);
+
+ // Verify preferences version.
+ if (!prefs->HasPrefPath(prefs::kContentSettingsVersion)) {
+ prefs->SetInteger(prefs::kContentSettingsVersion,
+ kContentSettingsPatternVersion);
+ }
+ if (prefs->GetInteger(prefs::kContentSettingsVersion) >
+ kContentSettingsPatternVersion) {
+ LOG(ERROR) << "Unknown content settings version in preferences.";
+ return;
+ }
+
+ // Read exceptions.
const DictionaryValue* all_settings_dictionary =
- prefs->GetDictionary(prefs::kPerHostContentSettings);
+ prefs->GetMutableDictionary(prefs::kContentSettingsPatterns);
// Careful: The returned value could be NULL if the pref has never been set.
if (all_settings_dictionary != NULL) {
for (DictionaryValue::key_iterator i(all_settings_dictionary->begin_keys());
i != all_settings_dictionary->end_keys(); ++i) {
- std::wstring wide_host(*i);
- DictionaryValue* host_settings_dictionary = NULL;
+ std::wstring wide_pattern(*i);
+ if (!Pattern(WideToUTF8(wide_pattern)).IsValid())
+ LOG(WARNING) << "Invalid pattern stored in content settings";
+ DictionaryValue* pattern_settings_dictionary = NULL;
bool found = all_settings_dictionary->GetDictionaryWithoutPathExpansion(
- wide_host, &host_settings_dictionary);
+ wide_pattern, &pattern_settings_dictionary);
DCHECK(found);
ContentSettings settings;
- GetSettingsFromDictionary(host_settings_dictionary, &settings);
- host_content_settings_[WideToUTF8(wide_host)] = settings;
+ GetSettingsFromDictionary(pattern_settings_dictionary, &settings);
+ host_content_settings_[WideToUTF8(wide_pattern)] = settings;
}
}
-
- // Read misc. global settings.
- block_third_party_cookies_ =
- prefs->GetBoolean(prefs::kBlockThirdPartyCookies);
}
// static
void HostContentSettingsMap::RegisterUserPrefs(PrefService* prefs) {
prefs->RegisterDictionaryPref(prefs::kDefaultContentSettings);
- prefs->RegisterDictionaryPref(prefs::kPerHostContentSettings);
+ prefs->RegisterIntegerPref(prefs::kContentSettingsVersion,
+ kContentSettingsPatternVersion);
+ prefs->RegisterDictionaryPref(prefs::kContentSettingsPatterns);
prefs->RegisterBooleanPref(prefs::kBlockThirdPartyCookies, false);
prefs->RegisterIntegerPref(prefs::kContentSettingsWindowLastTabIndex, 0);
@@ -117,6 +218,7 @@ void HostContentSettingsMap::RegisterUserPrefs(PrefService* prefs) {
prefs->RegisterIntegerPref(prefs::kCookieBehavior,
net::StaticCookiePolicy::ALLOW_ALL_COOKIES);
prefs->RegisterListPref(prefs::kPopupWhitelistedHosts);
+ prefs->RegisterDictionaryPref(prefs::kPerHostContentSettings);
}
ContentSetting HostContentSettingsMap::GetDefaultContentSetting(
@@ -126,46 +228,48 @@ ContentSetting HostContentSettingsMap::GetDefaultContentSetting(
}
ContentSetting HostContentSettingsMap::GetContentSetting(
- const std::string& host,
- ContentSettingsType content_type) const {
- AutoLock auto_lock(lock_);
- HostContentSettings::const_iterator i(host_content_settings_.find(
- net::TrimEndingDot(host)));
- if (i != host_content_settings_.end()) {
- ContentSetting setting = i->second.settings[content_type];
- if (setting != CONTENT_SETTING_DEFAULT)
- return setting;
- }
- return default_content_settings_.settings[content_type];
-}
-
-ContentSetting HostContentSettingsMap::GetContentSetting(
const GURL& url,
ContentSettingsType content_type) const {
- return ShouldAllowAllContent(url) ?
- CONTENT_SETTING_ALLOW : GetContentSetting(url.host(), content_type);
+ return GetContentSettings(url).settings[content_type];
}
ContentSettings HostContentSettingsMap::GetContentSettings(
- const std::string& host) const {
+ const GURL& url) const {
+ if (ShouldAllowAllContent(url))
+ return ContentSettings(CONTENT_SETTING_ALLOW);
+
AutoLock auto_lock(lock_);
- HostContentSettings::const_iterator i(host_content_settings_.find(
- net::TrimEndingDot(host)));
- if (i == host_content_settings_.end())
- return default_content_settings_;
-
- ContentSettings output = i->second;
- for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) {
- if (output.settings[j] == CONTENT_SETTING_DEFAULT)
- output.settings[j] = default_content_settings_.settings[j];
+
+ const std::string host(HostFromURL(url));
+
+ // Check for exact matches first.
+ HostContentSettings::const_iterator i(host_content_settings_.find(host));
+ if (i != host_content_settings_.end()) {
+ ContentSettings output = i->second;
+ for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) {
+ if (output.settings[j] == CONTENT_SETTING_DEFAULT)
+ output.settings[j] = default_content_settings_.settings[j];
+ }
+ return output;
}
- return output;
-}
-ContentSettings HostContentSettingsMap::GetContentSettings(
- const GURL& url) const {
- return ShouldAllowAllContent(url) ?
- ContentSettings(CONTENT_SETTING_ALLOW) : GetContentSettings(url.host());
+ // Find the most concrete pattern match.
+ for (std::string key = std::string(kDomainWildcard) + host; ; ) {
+ HostContentSettings::const_iterator i(host_content_settings_.find(key));
+ if (i != host_content_settings_.end()) {
+ ContentSettings output = i->second;
+ for (int j = 0; j < CONTENT_SETTINGS_NUM_TYPES; ++j) {
+ if (output.settings[j] == CONTENT_SETTING_DEFAULT)
+ output.settings[j] = default_content_settings_.settings[j];
+ }
+ return output;
+ }
+ const size_t next_dot = key.find('.', kDomainWildcardLength);
+ if (next_dot == std::string::npos)
+ break;
+ key.erase(kDomainWildcardLength, next_dot - kDomainWildcardLength + 1);
+ }
+ return default_content_settings_;
}
void HostContentSettingsMap::GetSettingsForOneType(
@@ -181,7 +285,7 @@ void HostContentSettingsMap::GetSettingsForOneType(
if (setting != CONTENT_SETTING_DEFAULT) {
// Use of push_back() relies on the map iterator traversing in order of
// ascending keys.
- settings->push_back(std::make_pair(i->first, setting));
+ settings->push_back(std::make_pair(Pattern(i->first), setting));
}
}
}
@@ -211,30 +315,31 @@ void HostContentSettingsMap::SetDefaultContentSetting(
}
}
- NotifyObservers(std::string());
+ NotifyObservers(ContentSettingsDetails(true));
}
-void HostContentSettingsMap::SetContentSetting(const std::string& host,
+void HostContentSettingsMap::SetContentSetting(const Pattern& pattern,
ContentSettingsType content_type,
ContentSetting setting) {
DCHECK(kTypeNames[content_type] != NULL); // Don't call this for Geolocation.
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
bool early_exit = false;
- std::wstring wide_host(UTF8ToWide(host));
+ std::wstring wide_pattern(UTF8ToWide(pattern.AsString()));
DictionaryValue* all_settings_dictionary =
profile_->GetPrefs()->GetMutableDictionary(
- prefs::kPerHostContentSettings);
+ prefs::kContentSettingsPatterns);
{
AutoLock auto_lock(lock_);
- if (!host_content_settings_.count(host))
- host_content_settings_[host] = ContentSettings();
- HostContentSettings::iterator i(host_content_settings_.find(host));
+ if (!host_content_settings_.count(pattern.AsString()))
+ host_content_settings_[pattern.AsString()] = ContentSettings();
+ HostContentSettings::iterator
+ i(host_content_settings_.find(pattern.AsString()));
ContentSettings& settings = i->second;
settings.settings[content_type] = setting;
if (AllDefault(settings)) {
host_content_settings_.erase(i);
- all_settings_dictionary->RemoveWithoutPathExpansion(wide_host, NULL);
+ all_settings_dictionary->RemoveWithoutPathExpansion(wide_pattern, NULL);
// We can't just return because |NotifyObservers()| needs to be called,
// without |lock_| being held.
@@ -245,11 +350,11 @@ void HostContentSettingsMap::SetContentSetting(const std::string& host,
if (!early_exit) {
DictionaryValue* host_settings_dictionary;
bool found = all_settings_dictionary->GetDictionaryWithoutPathExpansion(
- wide_host, &host_settings_dictionary);
+ wide_pattern, &host_settings_dictionary);
if (!found) {
host_settings_dictionary = new DictionaryValue;
all_settings_dictionary->SetWithoutPathExpansion(
- wide_host, host_settings_dictionary);
+ wide_pattern, host_settings_dictionary);
DCHECK_NE(setting, CONTENT_SETTING_DEFAULT);
}
std::wstring dictionary_path(kTypeNames[content_type]);
@@ -262,7 +367,7 @@ void HostContentSettingsMap::SetContentSetting(const std::string& host,
}
}
- NotifyObservers(host);
+ NotifyObservers(ContentSettingsDetails(pattern));
}
void HostContentSettingsMap::ClearSettingsForOneType(
@@ -277,7 +382,7 @@ void HostContentSettingsMap::ClearSettingsForOneType(
std::wstring wide_host(UTF8ToWide(i->first));
DictionaryValue* all_settings_dictionary =
profile_->GetPrefs()->GetMutableDictionary(
- prefs::kPerHostContentSettings);
+ prefs::kContentSettingsPatterns);
if (AllDefault(i->second)) {
all_settings_dictionary->RemoveWithoutPathExpansion(wide_host, NULL);
host_content_settings_.erase(i++);
@@ -297,7 +402,7 @@ void HostContentSettingsMap::ClearSettingsForOneType(
}
}
- NotifyObservers(std::string());
+ NotifyObservers(ContentSettingsDetails(true));
}
void HostContentSettingsMap::SetBlockThirdPartyCookies(bool block) {
@@ -328,10 +433,10 @@ void HostContentSettingsMap::ResetToDefaults() {
PrefService* prefs = profile_->GetPrefs();
prefs->ClearPref(prefs::kDefaultContentSettings);
- prefs->ClearPref(prefs::kPerHostContentSettings);
+ prefs->ClearPref(prefs::kContentSettingsPatterns);
prefs->ClearPref(prefs::kBlockThirdPartyCookies);
- NotifyObservers(std::string());
+ NotifyObservers(ContentSettingsDetails(true));
}
HostContentSettingsMap::~HostContentSettingsMap() {
@@ -384,10 +489,10 @@ bool HostContentSettingsMap::AllDefault(const ContentSettings& settings) const {
return true;
}
-void HostContentSettingsMap::NotifyObservers(const std::string& host) {
- ContentSettingsDetails details(host);
+void HostContentSettingsMap::NotifyObservers(
+ const ContentSettingsDetails& details) {
NotificationService::current()->Notify(
NotificationType::CONTENT_SETTINGS_CHANGED,
Source<HostContentSettingsMap>(this),
- Details<ContentSettingsDetails>(&details));
+ Details<const ContentSettingsDetails>(&details));
}
diff --git a/chrome/browser/host_content_settings_map.h b/chrome/browser/host_content_settings_map.h
index 4b4e141..babc769 100644
--- a/chrome/browser/host_content_settings_map.h
+++ b/chrome/browser/host_content_settings_map.h
@@ -17,33 +17,73 @@
#include "base/lock.h"
#include "base/ref_counted.h"
#include "chrome/common/content_settings.h"
-#include "googleurl/src/gurl.h"
class DictionaryValue;
+class GURL;
class PrefService;
class Profile;
class HostContentSettingsMap
: public base::RefCountedThreadSafe<HostContentSettingsMap> {
public:
+ // A hostname pattern. See |IsValid| for a description of possible patterns.
+ class Pattern {
+ public:
+ // Returns a pattern that matches the host of this URL and all subdomains.
+ static Pattern FromURL(const GURL& url);
+
+ Pattern() {}
+
+ explicit Pattern(const std::string& pattern) : pattern_(pattern) {}
+
+ // True if this is a valid pattern. Valid patterns are
+ // - [*.]domain.tld (matches domain.tld and all sub-domains)
+ // - host (matches an exact hostname)
+ // - a.b.c.d (matches an exact IPv4 ip)
+ // - [a:b:c:d:e:f:g:h] (matches an exact IPv6 ip)
+ bool IsValid() const;
+
+ // True if |url| matches this pattern.
+ bool Matches(const GURL& url) const;
+
+ // Returns a std::string representation of this pattern.
+ const std::string& AsString() const { return pattern_; }
+
+ bool operator==(const Pattern& other) const {
+ return pattern_ == other.pattern_;
+ }
+
+ private:
+ std::string pattern_;
+ };
+
// Details for the CONTENT_SETTINGS_CHANGED notification. This is sent when
// content settings change for at least one host. If settings change for more
- // than one host in one user interaction, this will usually send a single
- // notification with a wildcard host field instead of one notification for
- // each host.
+ // than one pattern in one user interaction, this will usually send a single
+ // notification with update_all() returning true instead of one notification
+ // for each pattern.
class ContentSettingsDetails {
public:
- explicit ContentSettingsDetails(const std::string& host) : host_(host) {}
- // The host whose settings have changed. Empty if many hosts are affected
- // (e.g. if the default settings have changed).
- const std::string& host() { return host_; }
+ explicit ContentSettingsDetails(const Pattern& pattern)
+ : pattern_(pattern), update_all_(false) {}
+
+ explicit ContentSettingsDetails(bool update_all)
+ : pattern_(), update_all_(update_all) {}
+
+ // The pattern whose settings have changed.
+ const Pattern& pattern() const { return pattern_; }
+
+ // True if many settings changed at once.
+ bool update_all() const { return update_all_; }
private:
- std::string host_;
+ Pattern pattern_;
+ bool update_all_;
};
- typedef std::pair<std::string, ContentSetting> HostSettingPair;
- typedef std::vector<HostSettingPair> SettingsForOneType;
+
+ typedef std::pair<Pattern, ContentSetting> PatternSettingPair;
+ typedef std::vector<PatternSettingPair> SettingsForOneType;
explicit HostContentSettingsMap(Profile* profile);
@@ -55,27 +95,19 @@ class HostContentSettingsMap
ContentSetting GetDefaultContentSetting(
ContentSettingsType content_type) const;
- // Returns a single ContentSetting which applies to a given host.
+ // Returns a single ContentSetting which applies to a given URL. Note that
+ // certain internal schemes are whitelisted.
//
// This may be called on any thread.
- ContentSetting GetContentSetting(const std::string& host,
- ContentSettingsType content_type) const;
-
- // Same as above, but for a URL instead of a host. The difference is that
- // URLs with particular internal schemes are whitelisted.
ContentSetting GetContentSetting(const GURL& url,
ContentSettingsType content_type) const;
- // Returns all ContentSettings which apply to a given host.
+ // Returns all ContentSettings which apply to a given URL.
//
// This may be called on any thread.
- ContentSettings GetContentSettings(const std::string& host) const;
-
- // Same as above, but for a URL instead of a host. The difference is that
- // URLs with particular internal schemes are whitelisted.
ContentSettings GetContentSettings(const GURL& url) const;
- // For a given content type, returns all hosts with a non-default setting,
+ // For a given content type, returns all patterns with a non-default setting,
// mapped to their actual settings, in lexicographical order. |settings| must
// be a non-NULL outparam.
//
@@ -89,12 +121,12 @@ class HostContentSettingsMap
void SetDefaultContentSetting(ContentSettingsType content_type,
ContentSetting setting);
- // Sets the blocking setting for a particular hostname and content type.
+ // Sets the blocking setting for a particular pattern and content type.
// Setting the value to CONTENT_SETTING_DEFAULT causes the default setting for
- // that type to be used when loading pages from this host.
+ // that type to be used when loading pages matching this pattern.
//
// This should only be called on the UI thread.
- void SetContentSetting(const std::string& host,
+ void SetContentSetting(const Pattern& pattern,
ContentSettingsType content_type,
ContentSetting setting);
@@ -149,7 +181,7 @@ class HostContentSettingsMap
// |lock_| is not held when calling this, as listeners will usually call one
// of the GetSettings functions in response, which would then lead to a
// mutex deadlock.
- void NotifyObservers(const std::string& host);
+ void NotifyObservers(const ContentSettingsDetails& details);
// The profile we're associated with.
Profile* profile_;
@@ -167,4 +199,11 @@ class HostContentSettingsMap
DISALLOW_COPY_AND_ASSIGN(HostContentSettingsMap);
};
+// Stream operator so HostContentSettingsMap::Pattern can be used in
+// assertion statements.
+inline std::ostream& operator<<(
+ std::ostream& out, const HostContentSettingsMap::Pattern& pattern) {
+ return out << pattern.AsString();
+}
+
#endif // CHROME_BROWSER_HOST_CONTENT_SETTINGS_MAP_H_
diff --git a/chrome/browser/host_content_settings_map_unittest.cc b/chrome/browser/host_content_settings_map_unittest.cc
index 164e7b9..363e9b5 100644
--- a/chrome/browser/host_content_settings_map_unittest.cc
+++ b/chrome/browser/host_content_settings_map_unittest.cc
@@ -8,6 +8,7 @@
#include "chrome/common/notification_service.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/testing_profile.h"
+#include "googleurl/src/gurl.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -37,14 +38,16 @@ class StubSettingsObserver : public NotificationObserver {
Details<HostContentSettingsMap::ContentSettingsDetails>
settings_details(details);
last_notifier = content_settings.ptr();
- last_host = settings_details.ptr()->host();
+ last_pattern = settings_details.ptr()->pattern();
+ last_update_all = settings_details.ptr()->update_all();
// This checks that calling a Get function from an observer doesn't
// deadlock.
- last_notifier->GetContentSettings("random-hostname");
+ last_notifier->GetContentSettings(GURL("http://random-hostname.com/"));
}
HostContentSettingsMap* last_notifier;
- std::string last_host;
+ HostContentSettingsMap::Pattern last_pattern;
+ bool last_update_all;
int counter;
private:
@@ -93,16 +96,17 @@ TEST_F(HostContentSettingsMapTest, DefaultValues) {
CONTENT_SETTINGS_TYPE_PLUGINS));
// Check returning individual settings.
- std::string host("example.com");
+ GURL host("http://example.com/");
+ HostContentSettingsMap::Pattern pattern("[*.]example.com");
EXPECT_EQ(CONTENT_SETTING_ALLOW,
host_content_settings_map->GetContentSetting(
host, CONTENT_SETTINGS_TYPE_IMAGES));
- host_content_settings_map->SetContentSetting(host,
+ host_content_settings_map->SetContentSetting(pattern,
CONTENT_SETTINGS_TYPE_IMAGES, CONTENT_SETTING_DEFAULT);
EXPECT_EQ(CONTENT_SETTING_ALLOW,
host_content_settings_map->GetContentSetting(
host, CONTENT_SETTINGS_TYPE_IMAGES));
- host_content_settings_map->SetContentSetting(host,
+ host_content_settings_map->SetContentSetting(pattern,
CONTENT_SETTINGS_TYPE_IMAGES, CONTENT_SETTING_BLOCK);
EXPECT_EQ(CONTENT_SETTING_BLOCK,
host_content_settings_map->GetContentSetting(
@@ -115,15 +119,15 @@ TEST_F(HostContentSettingsMapTest, DefaultValues) {
ContentSettings desired_settings;
desired_settings.settings[CONTENT_SETTINGS_TYPE_COOKIES] =
CONTENT_SETTING_ALLOW;
- host_content_settings_map->SetContentSetting(host,
+ host_content_settings_map->SetContentSetting(pattern,
CONTENT_SETTINGS_TYPE_IMAGES, CONTENT_SETTING_DEFAULT);
desired_settings.settings[CONTENT_SETTINGS_TYPE_IMAGES] =
CONTENT_SETTING_ALLOW;
- host_content_settings_map->SetContentSetting(host,
+ host_content_settings_map->SetContentSetting(pattern,
CONTENT_SETTINGS_TYPE_JAVASCRIPT, CONTENT_SETTING_BLOCK);
desired_settings.settings[CONTENT_SETTINGS_TYPE_JAVASCRIPT] =
CONTENT_SETTING_BLOCK;
- host_content_settings_map->SetContentSetting(host,
+ host_content_settings_map->SetContentSetting(pattern,
CONTENT_SETTINGS_TYPE_PLUGINS, CONTENT_SETTING_ALLOW);
desired_settings.settings[CONTENT_SETTINGS_TYPE_PLUGINS] =
CONTENT_SETTING_ALLOW;
@@ -136,10 +140,10 @@ TEST_F(HostContentSettingsMapTest, DefaultValues) {
EXPECT_TRUE(SettingsEqual(desired_settings, settings));
// Check returning all hosts for a setting.
- std::string host2("example.org");
- host_content_settings_map->SetContentSetting(host2,
+ HostContentSettingsMap::Pattern pattern2("[*.]example.org");
+ host_content_settings_map->SetContentSetting(pattern2,
CONTENT_SETTINGS_TYPE_IMAGES, CONTENT_SETTING_BLOCK);
- host_content_settings_map->SetContentSetting(host2,
+ host_content_settings_map->SetContentSetting(pattern2,
CONTENT_SETTINGS_TYPE_PLUGINS, CONTENT_SETTING_BLOCK);
HostContentSettingsMap::SettingsForOneType host_settings;
host_content_settings_map->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_IMAGES,
@@ -157,14 +161,14 @@ TEST_F(HostContentSettingsMapTest, DefaultValues) {
EXPECT_EQ(0U, host_settings.size());
// Check clearing one type.
- std::string host3("example.net");
- host_content_settings_map->SetContentSetting(host,
+ HostContentSettingsMap::Pattern pattern3("[*.]example.net");
+ host_content_settings_map->SetContentSetting(pattern,
CONTENT_SETTINGS_TYPE_IMAGES, CONTENT_SETTING_BLOCK);
- host_content_settings_map->SetContentSetting(host2,
+ host_content_settings_map->SetContentSetting(pattern2,
CONTENT_SETTINGS_TYPE_IMAGES, CONTENT_SETTING_BLOCK);
- host_content_settings_map->SetContentSetting(host2,
+ host_content_settings_map->SetContentSetting(pattern2,
CONTENT_SETTINGS_TYPE_PLUGINS, CONTENT_SETTING_BLOCK);
- host_content_settings_map->SetContentSetting(host3,
+ host_content_settings_map->SetContentSetting(pattern3,
CONTENT_SETTINGS_TYPE_IMAGES, CONTENT_SETTING_BLOCK);
host_content_settings_map->ClearSettingsForOneType(
CONTENT_SETTINGS_TYPE_IMAGES);
@@ -176,34 +180,89 @@ TEST_F(HostContentSettingsMapTest, DefaultValues) {
EXPECT_EQ(1U, host_settings.size());
}
+TEST_F(HostContentSettingsMapTest, Patterns) {
+ TestingProfile profile;
+ HostContentSettingsMap* host_content_settings_map =
+ profile.GetHostContentSettingsMap();
+
+ GURL host1("http://example.com/");
+ GURL host2("http://www.example.com/");
+ GURL host3("http://example.org/");
+ HostContentSettingsMap::Pattern pattern1("[*.]example.com");
+ HostContentSettingsMap::Pattern pattern2("example.org");
+ EXPECT_EQ(CONTENT_SETTING_ALLOW,
+ host_content_settings_map->GetContentSetting(
+ host1, CONTENT_SETTINGS_TYPE_IMAGES));
+ host_content_settings_map->SetContentSetting(pattern1,
+ CONTENT_SETTINGS_TYPE_IMAGES, CONTENT_SETTING_BLOCK);
+ EXPECT_EQ(CONTENT_SETTING_BLOCK,
+ host_content_settings_map->GetContentSetting(
+ host1, CONTENT_SETTINGS_TYPE_IMAGES));
+ EXPECT_EQ(CONTENT_SETTING_BLOCK,
+ host_content_settings_map->GetContentSetting(
+ host2, CONTENT_SETTINGS_TYPE_IMAGES));
+ EXPECT_EQ(CONTENT_SETTING_ALLOW,
+ host_content_settings_map->GetContentSetting(
+ host3, CONTENT_SETTINGS_TYPE_IMAGES));
+ host_content_settings_map->SetContentSetting(pattern2,
+ CONTENT_SETTINGS_TYPE_IMAGES, CONTENT_SETTING_BLOCK);
+ EXPECT_EQ(CONTENT_SETTING_BLOCK,
+ host_content_settings_map->GetContentSetting(
+ host3, CONTENT_SETTINGS_TYPE_IMAGES));
+}
+
+TEST_F(HostContentSettingsMapTest, PatternSupport) {
+ EXPECT_TRUE(HostContentSettingsMap::Pattern("[*.]example.com").IsValid());
+ EXPECT_TRUE(HostContentSettingsMap::Pattern("example.com").IsValid());
+ EXPECT_TRUE(HostContentSettingsMap::Pattern("192.168.0.1").IsValid());
+ EXPECT_TRUE(HostContentSettingsMap::Pattern("[::1]").IsValid());
+ EXPECT_FALSE(HostContentSettingsMap::Pattern("*example.com").IsValid());
+ EXPECT_FALSE(HostContentSettingsMap::Pattern("example.*").IsValid());
+ EXPECT_FALSE(HostContentSettingsMap::Pattern("http://example.com").IsValid());
+
+ EXPECT_TRUE(HostContentSettingsMap::Pattern("[*.]example.com").Matches(
+ GURL("http://example.com/")));
+ EXPECT_TRUE(HostContentSettingsMap::Pattern("[*.]example.com").Matches(
+ GURL("http://www.example.com/")));
+ EXPECT_TRUE(HostContentSettingsMap::Pattern("www.example.com").Matches(
+ GURL("http://www.example.com/")));
+ EXPECT_FALSE(HostContentSettingsMap::Pattern("").Matches(
+ GURL("http://www.example.com/")));
+ EXPECT_FALSE(HostContentSettingsMap::Pattern("[*.]example.com").Matches(
+ GURL("http://example.org/")));
+ EXPECT_FALSE(HostContentSettingsMap::Pattern("example.com").Matches(
+ GURL("http://example.org/")));
+}
+
TEST_F(HostContentSettingsMapTest, Observer) {
TestingProfile profile;
HostContentSettingsMap* host_content_settings_map =
profile.GetHostContentSettingsMap();
StubSettingsObserver observer;
- std::string host("example.com");
- host_content_settings_map->SetContentSetting(host,
+ HostContentSettingsMap::Pattern pattern("[*.]example.com");
+ host_content_settings_map->SetContentSetting(pattern,
CONTENT_SETTINGS_TYPE_IMAGES, CONTENT_SETTING_ALLOW);
EXPECT_EQ(host_content_settings_map, observer.last_notifier);
- EXPECT_EQ(host, observer.last_host);
+ EXPECT_EQ(pattern, observer.last_pattern);
+ EXPECT_FALSE(observer.last_update_all);
EXPECT_EQ(1, observer.counter);
host_content_settings_map->ClearSettingsForOneType(
CONTENT_SETTINGS_TYPE_IMAGES);
EXPECT_EQ(host_content_settings_map, observer.last_notifier);
- EXPECT_EQ(std::string(), observer.last_host);
+ EXPECT_TRUE(observer.last_update_all);
EXPECT_EQ(2, observer.counter);
host_content_settings_map->ResetToDefaults();
EXPECT_EQ(host_content_settings_map, observer.last_notifier);
- EXPECT_EQ(std::string(), observer.last_host);
+ EXPECT_TRUE(observer.last_update_all);
EXPECT_EQ(3, observer.counter);
host_content_settings_map->SetDefaultContentSetting(
CONTENT_SETTINGS_TYPE_IMAGES, CONTENT_SETTING_BLOCK);
EXPECT_EQ(host_content_settings_map, observer.last_notifier);
- EXPECT_EQ(std::string(), observer.last_host);
+ EXPECT_TRUE(observer.last_update_all);
EXPECT_EQ(4, observer.counter);
}
@@ -212,18 +271,18 @@ TEST_F(HostContentSettingsMapTest, HostTrimEndingDotCheck) {
HostContentSettingsMap* host_content_settings_map =
profile.GetHostContentSettingsMap();
- std::string host("example.com");
- std::string host_ending_with_dot("example.com.");
+ HostContentSettingsMap::Pattern pattern("[*.]example.com");
+ GURL host_ending_with_dot("http://example.com./");
EXPECT_EQ(CONTENT_SETTING_ALLOW,
host_content_settings_map->GetContentSetting(
host_ending_with_dot, CONTENT_SETTINGS_TYPE_IMAGES));
- host_content_settings_map->SetContentSetting(host,
+ host_content_settings_map->SetContentSetting(pattern,
CONTENT_SETTINGS_TYPE_IMAGES, CONTENT_SETTING_DEFAULT);
EXPECT_EQ(CONTENT_SETTING_ALLOW,
host_content_settings_map->GetContentSetting(
host_ending_with_dot, CONTENT_SETTINGS_TYPE_IMAGES));
- host_content_settings_map->SetContentSetting(host,
+ host_content_settings_map->SetContentSetting(pattern,
CONTENT_SETTINGS_TYPE_IMAGES, CONTENT_SETTING_BLOCK);
EXPECT_EQ(CONTENT_SETTING_BLOCK,
host_content_settings_map->GetContentSetting(
@@ -232,12 +291,12 @@ TEST_F(HostContentSettingsMapTest, HostTrimEndingDotCheck) {
EXPECT_EQ(CONTENT_SETTING_ALLOW,
host_content_settings_map->GetContentSetting(
host_ending_with_dot, CONTENT_SETTINGS_TYPE_COOKIES));
- host_content_settings_map->SetContentSetting(host,
+ host_content_settings_map->SetContentSetting(pattern,
CONTENT_SETTINGS_TYPE_COOKIES, CONTENT_SETTING_DEFAULT);
EXPECT_EQ(CONTENT_SETTING_ALLOW,
host_content_settings_map->GetContentSetting(
host_ending_with_dot, CONTENT_SETTINGS_TYPE_COOKIES));
- host_content_settings_map->SetContentSetting(host,
+ host_content_settings_map->SetContentSetting(pattern,
CONTENT_SETTINGS_TYPE_COOKIES, CONTENT_SETTING_BLOCK);
EXPECT_EQ(CONTENT_SETTING_BLOCK,
host_content_settings_map->GetContentSetting(
@@ -246,12 +305,12 @@ TEST_F(HostContentSettingsMapTest, HostTrimEndingDotCheck) {
EXPECT_EQ(CONTENT_SETTING_ALLOW,
host_content_settings_map->GetContentSetting(
host_ending_with_dot, CONTENT_SETTINGS_TYPE_JAVASCRIPT));
- host_content_settings_map->SetContentSetting(host,
+ host_content_settings_map->SetContentSetting(pattern,
CONTENT_SETTINGS_TYPE_JAVASCRIPT, CONTENT_SETTING_DEFAULT);
EXPECT_EQ(CONTENT_SETTING_ALLOW,
host_content_settings_map->GetContentSetting(
host_ending_with_dot, CONTENT_SETTINGS_TYPE_JAVASCRIPT));
- host_content_settings_map->SetContentSetting(host,
+ host_content_settings_map->SetContentSetting(pattern,
CONTENT_SETTINGS_TYPE_JAVASCRIPT, CONTENT_SETTING_BLOCK);
EXPECT_EQ(CONTENT_SETTING_BLOCK,
host_content_settings_map->GetContentSetting(
@@ -260,12 +319,12 @@ TEST_F(HostContentSettingsMapTest, HostTrimEndingDotCheck) {
EXPECT_EQ(CONTENT_SETTING_ALLOW,
host_content_settings_map->GetContentSetting(
host_ending_with_dot, CONTENT_SETTINGS_TYPE_PLUGINS));
- host_content_settings_map->SetContentSetting(host,
+ host_content_settings_map->SetContentSetting(pattern,
CONTENT_SETTINGS_TYPE_PLUGINS, CONTENT_SETTING_DEFAULT);
EXPECT_EQ(CONTENT_SETTING_ALLOW,
host_content_settings_map->GetContentSetting(
host_ending_with_dot, CONTENT_SETTINGS_TYPE_PLUGINS));
- host_content_settings_map->SetContentSetting(host,
+ host_content_settings_map->SetContentSetting(pattern,
CONTENT_SETTINGS_TYPE_PLUGINS, CONTENT_SETTING_BLOCK);
EXPECT_EQ(CONTENT_SETTING_BLOCK,
host_content_settings_map->GetContentSetting(
@@ -274,12 +333,12 @@ TEST_F(HostContentSettingsMapTest, HostTrimEndingDotCheck) {
EXPECT_EQ(CONTENT_SETTING_BLOCK,
host_content_settings_map->GetContentSetting(
host_ending_with_dot, CONTENT_SETTINGS_TYPE_POPUPS));
- host_content_settings_map->SetContentSetting(host,
+ host_content_settings_map->SetContentSetting(pattern,
CONTENT_SETTINGS_TYPE_POPUPS, CONTENT_SETTING_DEFAULT);
EXPECT_EQ(CONTENT_SETTING_BLOCK,
host_content_settings_map->GetContentSetting(
host_ending_with_dot, CONTENT_SETTINGS_TYPE_POPUPS));
- host_content_settings_map->SetContentSetting(host,
+ host_content_settings_map->SetContentSetting(pattern,
CONTENT_SETTINGS_TYPE_POPUPS, CONTENT_SETTING_ALLOW);
EXPECT_EQ(CONTENT_SETTING_ALLOW,
host_content_settings_map->GetContentSetting(
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc
index 0dfd106..91ffc97 100644
--- a/chrome/browser/renderer_host/render_view_host.cc
+++ b/chrome/browser/renderer_host/render_view_host.cc
@@ -1801,9 +1801,9 @@ void RenderViewHost::RevertTranslation(int page_id) {
Send(new ViewMsg_RevertTranslation(routing_id(), page_id));
}
-void RenderViewHost::SendContentSettings(const std::string& host,
+void RenderViewHost::SendContentSettings(const GURL& url,
const ContentSettings& settings) {
- Send(new ViewMsg_SetContentSettingsForCurrentHost(host, settings));
+ Send(new ViewMsg_SetContentSettingsForCurrentURL(url, settings));
}
void RenderViewHost::OnExtensionPostMessage(
diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h
index 37b9c46..83fd216 100644
--- a/chrome/browser/renderer_host/render_view_host.h
+++ b/chrome/browser/renderer_host/render_view_host.h
@@ -455,7 +455,7 @@ class RenderViewHost : public RenderWidgetHost {
void RevertTranslation(int page_id);
// Informs renderer of updated content settings.
- void SendContentSettings(const std::string& host,
+ void SendContentSettings(const GURL& url,
const ContentSettings& settings);
protected:
diff --git a/chrome/browser/tab_contents/tab_contents.cc b/chrome/browser/tab_contents/tab_contents.cc
index 683d63a..27d67ec 100644
--- a/chrome/browser/tab_contents/tab_contents.cc
+++ b/chrome/browser/tab_contents/tab_contents.cc
@@ -2875,19 +2875,16 @@ void TabContents::Observe(NotificationType type,
break;
case NotificationType::CONTENT_SETTINGS_CHANGED: {
- Details<HostContentSettingsMap::ContentSettingsDetails>
+ Details<const HostContentSettingsMap::ContentSettingsDetails>
settings_details(details);
NavigationEntry* entry = controller_.GetActiveEntry();
GURL entry_url;
- std::string host;
- if (entry) {
+ if (entry)
entry_url = entry->url();
- host = entry_url.host();
- }
Source<HostContentSettingsMap> content_settings(source);
- if (settings_details.ptr()->host().empty() ||
- settings_details.ptr()->host() == host) {
- render_view_host()->SendContentSettings(host,
+ if (settings_details.ptr()->update_all() ||
+ settings_details.ptr()->pattern().Matches(entry_url)) {
+ render_view_host()->SendContentSettings(entry_url,
content_settings.ptr()->GetContentSettings(entry_url));
}
break;
diff --git a/chrome/browser/views/options/exception_editor_view.cc b/chrome/browser/views/options/exception_editor_view.cc
index 49bc2ac..4e358bf 100644
--- a/chrome/browser/views/options/exception_editor_view.cc
+++ b/chrome/browser/views/options/exception_editor_view.cc
@@ -8,41 +8,27 @@
#include "app/resource_bundle.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/content_exceptions_table_model.h"
-#include "chrome/browser/host_content_settings_map.h"
#include "googleurl/src/url_canon.h"
#include "googleurl/src/url_parse.h"
#include "grit/app_resources.h"
#include "grit/generated_resources.h"
-#include "net/base/net_util.h"
#include "views/grid_layout.h"
#include "views/controls/image_view.h"
#include "views/controls/label.h"
#include "views/standard_layout.h"
#include "views/window/window.h"
-namespace {
-
-// Returns true if the host name is valid.
-bool ValidHost(const std::string& host) {
- if (host.empty())
- return false;
-
- url_canon::CanonHostInfo host_info;
- return !net::CanonicalizeHost(host, &host_info).empty();
-}
-
-} // namespace
-
-ExceptionEditorView::ExceptionEditorView(Delegate* delegate,
- ContentExceptionsTableModel* model,
- int index,
- const std::string& host,
- ContentSetting setting)
+ExceptionEditorView::ExceptionEditorView(
+ Delegate* delegate,
+ ContentExceptionsTableModel* model,
+ int index,
+ const HostContentSettingsMap::Pattern& pattern,
+ ContentSetting setting)
: delegate_(delegate),
model_(model),
cb_model_(model->content_type() == CONTENT_SETTINGS_TYPE_COOKIES),
index_(index),
- host_(host),
+ pattern_(pattern),
setting_(setting) {
Init();
}
@@ -52,8 +38,8 @@ void ExceptionEditorView::Show(gfx::NativeWindow parent) {
views::Window::CreateChromeWindow(parent, gfx::Rect(), this);
window->Show();
GetDialogClientView()->UpdateDialogButtons();
- host_tf_->SelectAll();
- host_tf_->RequestFocus();
+ pattern_tf_->SelectAll();
+ pattern_tf_->RequestFocus();
}
bool ExceptionEditorView::IsModal() const {
@@ -68,7 +54,8 @@ std::wstring ExceptionEditorView::GetWindowTitle() const {
bool ExceptionEditorView::IsDialogButtonEnabled(
MessageBoxFlags::DialogButton button) const {
if (button == MessageBoxFlags::DIALOGBUTTON_OK) {
- return IsHostValid(UTF16ToUTF8(host_tf_->text()));
+ return IsPatternValid(HostContentSettingsMap::Pattern(
+ UTF16ToUTF8(pattern_tf_->text())));
}
return true;
}
@@ -78,10 +65,10 @@ bool ExceptionEditorView::Cancel() {
}
bool ExceptionEditorView::Accept() {
- std::string new_host = UTF16ToUTF8(host_tf_->text());
+ HostContentSettingsMap::Pattern new_pattern(UTF16ToUTF8(pattern_tf_->text()));
ContentSetting setting =
cb_model_.SettingForIndex(action_cb_->selected_item());
- delegate_->AcceptExceptionEdit(new_host, setting, index_, is_new());
+ delegate_->AcceptExceptionEdit(new_pattern, setting, index_, is_new());
return true;
}
@@ -92,7 +79,8 @@ views::View* ExceptionEditorView::GetContentsView() {
void ExceptionEditorView::ContentsChanged(views::Textfield* sender,
const std::wstring& new_contents) {
GetDialogClientView()->UpdateDialogButtons();
- UpdateImageView(host_iv_, IsHostValid(UTF16ToUTF8(host_tf_->text())));
+ UpdateImageView(pattern_iv_, IsPatternValid(HostContentSettingsMap::Pattern(
+ UTF16ToUTF8(pattern_tf_->text()))));
}
bool ExceptionEditorView::HandleKeystroke(
@@ -104,13 +92,14 @@ bool ExceptionEditorView::HandleKeystroke(
void ExceptionEditorView::Init() {
using views::GridLayout;
- host_tf_ = new views::Textfield();
- host_tf_->SetText(UTF8ToUTF16(host_));
- host_tf_->SetController(this);
+ pattern_tf_ = new views::Textfield();
+ pattern_tf_->SetText(UTF8ToUTF16(pattern_.AsString()));
+ pattern_tf_->SetController(this);
- host_iv_ = new views::ImageView;
+ pattern_iv_ = new views::ImageView;
- UpdateImageView(host_iv_, IsHostValid(UTF16ToUTF8(host_tf_->text())));
+ UpdateImageView(pattern_iv_, IsPatternValid(HostContentSettingsMap::Pattern(
+ UTF16ToUTF8(pattern_tf_->text()))));
action_cb_ = new views::Combobox(&cb_model_);
if (!is_new())
@@ -132,9 +121,9 @@ void ExceptionEditorView::Init() {
// Add the contents.
layout->StartRow(0, 1);
- layout->AddView(CreateLabel(IDS_EXCEPTION_EDITOR_HOST_TITLE));
- layout->AddView(host_tf_);
- layout->AddView(host_iv_);
+ layout->AddView(CreateLabel(IDS_EXCEPTION_EDITOR_PATTERN_TITLE));
+ layout->AddView(pattern_tf_);
+ layout->AddView(pattern_iv_);
layout->StartRowWithPadding(0, 1, 0, kRelatedControlVerticalSpacing);
layout->AddView(CreateLabel(IDS_EXCEPTION_EDITOR_ACTION_TITLE));
@@ -147,12 +136,13 @@ views::Label* ExceptionEditorView::CreateLabel(int message_id) {
return label;
}
-bool ExceptionEditorView::IsHostValid(const std::string& host) const {
- bool is_valid_host = ValidHost(host) &&
- (model_->IndexOfExceptionByHost(host) == -1);
+bool ExceptionEditorView::IsPatternValid(
+ const HostContentSettingsMap::Pattern& pattern) const {
+ bool is_valid_pattern = pattern.IsValid() &&
+ (model_->IndexOfExceptionByPattern(pattern) == -1);
- return is_new() ? is_valid_host : (!host.empty() &&
- ((host_ == host) || is_valid_host));
+ return is_new() ? is_valid_pattern : (!pattern.AsString().empty() &&
+ ((pattern_ == pattern) || is_valid_pattern));
}
void ExceptionEditorView::UpdateImageView(views::ImageView* image_view,
diff --git a/chrome/browser/views/options/exception_editor_view.h b/chrome/browser/views/options/exception_editor_view.h
index d542e99..4c73141 100644
--- a/chrome/browser/views/options/exception_editor_view.h
+++ b/chrome/browser/views/options/exception_editor_view.h
@@ -8,6 +8,7 @@
#include <string>
#include "chrome/browser/content_setting_combo_model.h"
+#include "chrome/browser/host_content_settings_map.h"
#include "chrome/common/content_settings.h"
#include "chrome/common/content_settings_types.h"
#include "views/window/dialog_delegate.h"
@@ -34,10 +35,11 @@ class ExceptionEditorView : public views::View,
class Delegate {
public:
// Invoked when the user accepts the edit.
- virtual void AcceptExceptionEdit(const std::string& host,
- ContentSetting setting,
- int index,
- bool is_new) = 0;
+ virtual void AcceptExceptionEdit(
+ const HostContentSettingsMap::Pattern& pattern,
+ ContentSetting setting,
+ int index,
+ bool is_new) = 0;
protected:
virtual ~Delegate() {}
@@ -49,7 +51,7 @@ class ExceptionEditorView : public views::View,
ExceptionEditorView(Delegate* delegate,
ContentExceptionsTableModel* model,
int index,
- const std::string& host,
+ const HostContentSettingsMap::Pattern& pattern,
ContentSetting setting);
virtual ~ExceptionEditorView() {}
@@ -80,7 +82,7 @@ class ExceptionEditorView : public views::View,
// Returns true if we're adding a new item.
bool is_new() const { return index_ == -1; }
- bool IsHostValid(const std::string& host) const;
+ bool IsPatternValid(const HostContentSettingsMap::Pattern& pattern) const;
void UpdateImageView(views::ImageView* image_view, bool is_valid);
@@ -90,11 +92,11 @@ class ExceptionEditorView : public views::View,
// Index of the item being edited. If -1, indices this is a new entry.
const int index_;
- const std::string host_;
+ const HostContentSettingsMap::Pattern pattern_;
const ContentSetting setting_;
- views::Textfield* host_tf_;
- views::ImageView* host_iv_;
+ views::Textfield* pattern_tf_;
+ views::ImageView* pattern_iv_;
views::Combobox* action_cb_;
DISALLOW_COPY_AND_ASSIGN(ExceptionEditorView);
diff --git a/chrome/browser/views/options/exceptions_view.cc b/chrome/browser/views/options/exceptions_view.cc
index a879444..8d7fc76 100644
--- a/chrome/browser/views/options/exceptions_view.cc
+++ b/chrome/browser/views/options/exceptions_view.cc
@@ -122,15 +122,16 @@ std::wstring ExceptionsView::GetWindowTitle() const {
return std::wstring();
}
-void ExceptionsView::AcceptExceptionEdit(const std::string& host,
- ContentSetting setting,
- int index,
- bool is_new) {
+void ExceptionsView::AcceptExceptionEdit(
+ const HostContentSettingsMap::Pattern& pattern,
+ ContentSetting setting,
+ int index,
+ bool is_new) {
if (!is_new)
model_.RemoveException(index);
- model_.AddException(host, setting);
+ model_.AddException(pattern, setting);
- int new_index = model_.IndexOfExceptionByHost(host);
+ int new_index = model_.IndexOfExceptionByPattern(pattern);
DCHECK(new_index != -1);
table_->Select(new_index);
}
@@ -153,7 +154,7 @@ void ExceptionsView::Init() {
std::vector<TableColumn> columns;
columns.push_back(
- TableColumn(IDS_EXCEPTIONS_HOSTNAME_HEADER, TableColumn::LEFT, -1, .75));
+ TableColumn(IDS_EXCEPTIONS_PATTERN_HEADER, TableColumn::LEFT, -1, .75));
columns.back().sortable = true;
columns.push_back(
TableColumn(IDS_EXCEPTIONS_ACTION_HEADER, TableColumn::LEFT, -1, .25));
@@ -162,7 +163,7 @@ void ExceptionsView::Init() {
false);
views::TableView::SortDescriptors sort;
sort.push_back(
- views::TableView::SortDescriptor(IDS_EXCEPTIONS_HOSTNAME_HEADER, true));
+ views::TableView::SortDescriptor(IDS_EXCEPTIONS_PATTERN_HEADER, true));
table_->SetSortDescriptors(sort);
table_->SetObserver(this);
@@ -214,7 +215,8 @@ void ExceptionsView::UpdateButtonState() {
void ExceptionsView::Add() {
ExceptionEditorView* view =
- new ExceptionEditorView(this, &model_, -1, std::string(),
+ new ExceptionEditorView(this, &model_, -1,
+ HostContentSettingsMap::Pattern(),
CONTENT_SETTING_BLOCK);
view->Show(window()->GetNativeWindow());
@@ -224,7 +226,7 @@ void ExceptionsView::Add() {
void ExceptionsView::Edit() {
DCHECK(table_->FirstSelectedRow() != -1);
int index = table_->FirstSelectedRow();
- const HostContentSettingsMap::HostSettingPair& entry =
+ const HostContentSettingsMap::PatternSettingPair& entry =
model_.entry_at(index);
ExceptionEditorView* view =
new ExceptionEditorView(this, &model_, index, entry.first, entry.second);
diff --git a/chrome/browser/views/options/exceptions_view.h b/chrome/browser/views/options/exceptions_view.h
index bc33564..241d055 100644
--- a/chrome/browser/views/options/exceptions_view.h
+++ b/chrome/browser/views/options/exceptions_view.h
@@ -66,10 +66,11 @@ class ExceptionsView : public ExceptionEditorView::Delegate,
virtual views::View* GetContentsView() { return this; }
// ExceptionEditorView::Delegate implementation.
- virtual void AcceptExceptionEdit(const std::string& host,
- ContentSetting setting,
- int index,
- bool is_new);
+ virtual void AcceptExceptionEdit(
+ const HostContentSettingsMap::Pattern& pattern,
+ ContentSetting setting,
+ int index,
+ bool is_new);
private:
ExceptionsView(HostContentSettingsMap* map, ContentSettingsType type);
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index 79afae1..2833173 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -324,10 +324,21 @@ const wchar_t kDesktopNotificationDeniedOrigins[] =
// Dictionary of content settings applied to all hosts by default.
const wchar_t kDefaultContentSettings[] = L"profile.default_content_settings";
-// Dictionary that maps hostnames to content related settings. Default
-// settings will be applied to hosts not in this pref.
+// OBSOLETE. Dictionary that maps hostnames to content related settings.
+// Default settings will be applied to hosts not in this pref.
const wchar_t kPerHostContentSettings[] = L"profile.per_host_content_settings";
+// Version of the pattern format used to define content settings.
+const wchar_t kContentSettingsVersion[] =
+ L"profile.content_settings.pref_version";
+
+// Patterns for mapping hostnames to content related settings. Default settings
+// will be applied to hosts that don't match any of the patterns. Replaces
+// kPerHostContentSettings. The pattern format used is defined by
+// kContentSettingsVersion.
+const wchar_t kContentSettingsPatterns[] =
+ L"profile.content_settings.patterns";
+
// Boolean that is true if we should unconditionally block third-party cookies,
// regardless of other content settings.
const wchar_t kBlockThirdPartyCookies[] = L"profile.block_third_party_cookies";
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index cbbb603..5436aaa 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -126,7 +126,9 @@ extern const wchar_t kNTPPromoImageRemaining[];
extern const wchar_t kDesktopNotificationAllowedOrigins[];
extern const wchar_t kDesktopNotificationDeniedOrigins[];
extern const wchar_t kDefaultContentSettings[];
-extern const wchar_t kPerHostContentSettings[];
+extern const wchar_t kPerHostContentSettings[]; // OBSOLETE
+extern const wchar_t kContentSettingsVersion[];
+extern const wchar_t kContentSettingsPatterns[];
extern const wchar_t kBlockThirdPartyCookies[];
extern const wchar_t kClearSiteDataOnExit[];
extern const wchar_t kPerHostZoomLevels[];
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index eb84df0..3f7b047 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -378,10 +378,10 @@ IPC_BEGIN_MESSAGES(View)
std::string /* host */,
ContentSettings /* content_settings */)
- // Set the content settings for a particular hostname, so all render views
- // displaying this host can update their content settings to match.
- IPC_MESSAGE_CONTROL2(ViewMsg_SetContentSettingsForCurrentHost,
- std::string /* host */,
+ // Set the content settings for a particular url, so all render views
+ // displaying this host url update their content settings to match.
+ IPC_MESSAGE_CONTROL2(ViewMsg_SetContentSettingsForCurrentURL,
+ GURL /* url */,
ContentSettings /* content_settings */)
// Change encoding of page in the renderer.
diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc
index a1e3a28..3a0385a 100644
--- a/chrome/renderer/render_thread.cc
+++ b/chrome/renderer/render_thread.cc
@@ -150,20 +150,20 @@ class SuicideOnChannelErrorFilter : public IPC::ChannelProxy::MessageFilter {
class RenderViewContentSettingsSetter : public RenderViewVisitor {
public:
- RenderViewContentSettingsSetter(const std::string& host,
+ RenderViewContentSettingsSetter(const GURL& url,
const ContentSettings& content_settings)
- : host_(host),
+ : url_(url),
content_settings_(content_settings) {
}
virtual bool Visit(RenderView* render_view) {
- if (GURL(render_view->webview()->mainFrame()->url()).host() == host_)
+ if (GURL(render_view->webview()->mainFrame()->url()) == url_)
render_view->SetContentSettings(content_settings_);
return true;
}
private:
- std::string host_;
+ GURL url_;
ContentSettings content_settings_;
DISALLOW_COPY_AND_ASSIGN(RenderViewContentSettingsSetter);
@@ -448,10 +448,10 @@ void RenderThread::OnResetVisitedLinks() {
WebView::resetVisitedLinkState();
}
-void RenderThread::OnSetContentSettingsForCurrentHost(
- const std::string& host,
+void RenderThread::OnSetContentSettingsForCurrentURL(
+ const GURL& url,
const ContentSettings& content_settings) {
- RenderViewContentSettingsSetter setter(host, content_settings);
+ RenderViewContentSettingsSetter setter(url, content_settings);
RenderView::ForEach(&setter);
}
@@ -518,8 +518,8 @@ void RenderThread::OnControlMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(ViewMsg_VisitedLink_NewTable, OnUpdateVisitedLinks)
IPC_MESSAGE_HANDLER(ViewMsg_VisitedLink_Add, OnAddVisitedLinks)
IPC_MESSAGE_HANDLER(ViewMsg_VisitedLink_Reset, OnResetVisitedLinks)
- IPC_MESSAGE_HANDLER(ViewMsg_SetContentSettingsForCurrentHost,
- OnSetContentSettingsForCurrentHost)
+ IPC_MESSAGE_HANDLER(ViewMsg_SetContentSettingsForCurrentURL,
+ OnSetContentSettingsForCurrentURL)
IPC_MESSAGE_HANDLER(ViewMsg_SetZoomLevelForCurrentHost,
OnSetZoomLevelForCurrentHost)
IPC_MESSAGE_HANDLER(ViewMsg_SetIsIncognitoProcess, OnSetIsIncognitoProcess)
diff --git a/chrome/renderer/render_thread.h b/chrome/renderer/render_thread.h
index af0eefe..2294e05 100644
--- a/chrome/renderer/render_thread.h
+++ b/chrome/renderer/render_thread.h
@@ -191,8 +191,8 @@ class RenderThread : public RenderThreadBase,
void OnAddVisitedLinks(const VisitedLinkSlave::Fingerprints& fingerprints);
void OnResetVisitedLinks();
void OnSetZoomLevelForCurrentHost(const std::string& host, int zoom_level);
- void OnSetContentSettingsForCurrentHost(
- const std::string& host, const ContentSettings& content_settings);
+ void OnSetContentSettingsForCurrentURL(
+ const GURL& url, const ContentSettings& content_settings);
void OnUpdateUserScripts(base::SharedMemoryHandle table);
void OnSetExtensionFunctionNames(const std::vector<std::string>& names);
void OnPageActionsUpdated(const std::string& extension_id,