diff options
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, |