diff options
author | marja@chromium.org <marja@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-27 13:43:42 +0000 |
---|---|---|
committer | marja@chromium.org <marja@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-27 13:43:42 +0000 |
commit | c144060968bce7873e4079bd2293272fe03b520f (patch) | |
tree | 6d1f7cc551e53d2626ff522ec46adb18da6c991c | |
parent | 78d4939cf2732a79ff823a0b00938e6aef77cf97 (diff) | |
download | chromium_src-c144060968bce7873e4079bd2293272fe03b520f.zip chromium_src-c144060968bce7873e4079bd2293272fe03b520f.tar.gz chromium_src-c144060968bce7873e4079bd2293272fe03b520f.tar.bz2 |
Delegating the "are images allowed" decision to renderer.
This enables making the decision based on both image url and the page url. E.g., blocking third-party images.
BUG=81179
TEST=RenderViewTest.ImagesBlockedByDefault, RenderViewTest.ImagesAllowedByDefault
Review URL: http://codereview.chromium.org/7831075
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@107562 0039d316-1c4b-4281-b951-d872f2087c98
21 files changed, 277 insertions, 85 deletions
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index d1651a8..388a27c 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc @@ -286,6 +286,10 @@ void ChromeContentBrowserClient::BrowserRenderProcessHostCreated( profile->IsOffTheRecord())); SendExtensionWebRequestStatusToHost(host); + ContentSettingsForOneType settings; + HostContentSettingsMap* map = profile->GetHostContentSettingsMap(); + map->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_IMAGES, "", &settings); + host->Send(new ChromeViewMsg_SetImageSettingRules(settings)); } void ChromeContentBrowserClient::PluginProcessHostCreated( diff --git a/chrome/browser/content_settings/host_content_settings_map.cc b/chrome/browser/content_settings/host_content_settings_map.cc index 5d76b92..c345ae2 100644 --- a/chrome/browser/content_settings/host_content_settings_map.cc +++ b/chrome/browser/content_settings/host_content_settings_map.cc @@ -316,7 +316,7 @@ ContentSettings HostContentSettingsMap::GetContentSettings( void HostContentSettingsMap::GetSettingsForOneType( ContentSettingsType content_type, const std::string& resource_identifier, - SettingsForOneType* settings) const { + ContentSettingsForOneType* settings) const { DCHECK(content_settings::SupportsResourceIdentifier(content_type) || resource_identifier.empty()); DCHECK(settings); @@ -552,7 +552,7 @@ void HostContentSettingsMap::AddSettingsForOneType( ProviderType provider_type, ContentSettingsType content_type, const std::string& resource_identifier, - SettingsForOneType* settings, + ContentSettingsForOneType* settings, bool incognito) const { scoped_ptr<content_settings::RuleIterator> rule_iterator( provider->GetRuleIterator(content_type, @@ -561,7 +561,7 @@ void HostContentSettingsMap::AddSettingsForOneType( ContentSettingsPattern wildcard = ContentSettingsPattern::Wildcard(); while (rule_iterator->HasNext()) { const content_settings::Rule& rule = rule_iterator->Next(); - settings->push_back(PatternSettingSourceTuple( + settings->push_back(ContentSettingPatternSource( rule.primary_pattern, rule.secondary_pattern, content_settings::ValueToContentSetting(rule.value.get()), kProviderNames[provider_type], diff --git a/chrome/browser/content_settings/host_content_settings_map.h b/chrome/browser/content_settings/host_content_settings_map.h index 4c167b9..4980656 100644 --- a/chrome/browser/content_settings/host_content_settings_map.h +++ b/chrome/browser/content_settings/host_content_settings_map.h @@ -49,15 +49,6 @@ class HostContentSettingsMap NUM_PROVIDER_TYPES, }; - // TODO(markusheintz): I sold my soul to the devil on order to add this tuple. - // I really want my soul back, so I really will change this ASAP. - typedef Tuple5<ContentSettingsPattern, - ContentSettingsPattern, - ContentSetting, - std::string, - bool> PatternSettingSourceTuple; - typedef std::vector<PatternSettingSourceTuple> SettingsForOneType; - HostContentSettingsMap(PrefService* prefs, ExtensionService* extension_service, bool incognito); @@ -126,16 +117,13 @@ class HostContentSettingsMap const GURL& secondary_url) const; // 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. If this map was created for the - // incognito profile, it will only return those settings differing from - // the main map. For ContentSettingsTypes that require an resource identifier - // to be specified, the |resource_identifier| must be non-empty. + // mapped to their actual settings, in the precedence order of the rules. + // |settings| must be a non-NULL outparam. // // This may be called on any thread. void GetSettingsForOneType(ContentSettingsType content_type, const std::string& resource_identifier, - SettingsForOneType* settings) const; + ContentSettingsForOneType* settings) const; // Sets the default setting for a particular content type. This method must // not be invoked on an incognito map. @@ -236,7 +224,7 @@ class HostContentSettingsMap ProviderType provider_type, ContentSettingsType content_type, const std::string& resource_identifier, - SettingsForOneType* settings, + ContentSettingsForOneType* settings, bool incognito) const; // Weak; owned by the Profile. diff --git a/chrome/browser/content_settings/host_content_settings_map_unittest.cc b/chrome/browser/content_settings/host_content_settings_map_unittest.cc index 208b8ba..6cd7e7c9 100644 --- a/chrome/browser/content_settings/host_content_settings_map_unittest.cc +++ b/chrome/browser/content_settings/host_content_settings_map_unittest.cc @@ -180,7 +180,7 @@ TEST_F(HostContentSettingsMapTest, IndividualSettings) { CONTENT_SETTINGS_TYPE_PLUGINS, std::string(), CONTENT_SETTING_BLOCK); - HostContentSettingsMap::SettingsForOneType host_settings; + ContentSettingsForOneType host_settings; host_content_settings_map->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_IMAGES, "", &host_settings); @@ -233,7 +233,7 @@ TEST_F(HostContentSettingsMapTest, Clear) { CONTENT_SETTING_BLOCK); host_content_settings_map->ClearSettingsForOneType( CONTENT_SETTINGS_TYPE_IMAGES); - HostContentSettingsMap::SettingsForOneType host_settings; + ContentSettingsForOneType host_settings; host_content_settings_map->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_IMAGES, "", &host_settings); diff --git a/chrome/browser/content_settings/tab_specific_content_settings.cc b/chrome/browser/content_settings/tab_specific_content_settings.cc index 4e1a5c0..b15e1f7 100644 --- a/chrome/browser/content_settings/tab_specific_content_settings.cc +++ b/chrome/browser/content_settings/tab_specific_content_settings.cc @@ -489,6 +489,9 @@ void TabSpecificContentSettings::Observe( map->GetDefaultContentSettings())); Send(new ChromeViewMsg_SetContentSettingsForCurrentURL( entry_url, map->GetContentSettings(entry_url, entry_url))); + ContentSettingsForOneType settings; + map->GetSettingsForOneType(CONTENT_SETTINGS_TYPE_IMAGES, "", &settings); + Send(new ChromeViewMsg_SetImageSettingRules(settings)); } } diff --git a/chrome/browser/extensions/extension_special_storage_policy.cc b/chrome/browser/extensions/extension_special_storage_policy.cc index 2064f37..eddaedf 100644 --- a/chrome/browser/extensions/extension_special_storage_policy.cc +++ b/chrome/browser/extensions/extension_special_storage_policy.cc @@ -45,11 +45,11 @@ bool ExtensionSpecialStoragePolicy::HasSessionOnlyOrigins() { if (host_content_settings_map_->GetDefaultContentSetting( CONTENT_SETTINGS_TYPE_COOKIES, NULL) == CONTENT_SETTING_SESSION_ONLY) return true; - HostContentSettingsMap::SettingsForOneType entries; + ContentSettingsForOneType entries; host_content_settings_map_->GetSettingsForOneType( CONTENT_SETTINGS_TYPE_COOKIES, "", &entries); for (size_t i = 0; i < entries.size(); ++i) { - if (entries[i].c == CONTENT_SETTING_SESSION_ONLY) + if (entries[i].setting == CONTENT_SETTING_SESSION_ONLY) return true; } return false; diff --git a/chrome/browser/notifications/desktop_notification_service.cc b/chrome/browser/notifications/desktop_notification_service.cc index ca4857d..4a43f94 100644 --- a/chrome/browser/notifications/desktop_notification_service.cc +++ b/chrome/browser/notifications/desktop_notification_service.cc @@ -23,6 +23,7 @@ #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" #include "chrome/common/chrome_notification_types.h" +#include "chrome/common/content_settings.h" #include "chrome/common/content_settings_pattern.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" @@ -292,7 +293,7 @@ void DesktopNotificationService::ResetToDefaultContentSetting() { } void DesktopNotificationService::GetNotificationsSettings( - HostContentSettingsMap::SettingsForOneType* settings) { + ContentSettingsForOneType* settings) { profile_->GetHostContentSettingsMap()->GetSettingsForOneType( CONTENT_SETTINGS_TYPE_NOTIFICATIONS, NO_RESOURCE_IDENTIFIER, diff --git a/chrome/browser/notifications/desktop_notification_service.h b/chrome/browser/notifications/desktop_notification_service.h index 8ab6b4c..eed1167 100644 --- a/chrome/browser/notifications/desktop_notification_service.h +++ b/chrome/browser/notifications/desktop_notification_service.h @@ -14,7 +14,6 @@ #include "base/memory/scoped_ptr.h" #include "base/string16.h" #include "chrome/browser/content_settings/content_settings_provider.h" -#include "chrome/browser/content_settings/host_content_settings_map.h" #include "chrome/browser/profiles/profile_keyed_service.h" #include "chrome/common/content_settings.h" #include "content/public/browser/notification_observer.h" @@ -107,8 +106,7 @@ class DesktopNotificationService : public content::NotificationObserver, // Returns all notifications settings. |settings| is cleared before // notifications setting are passed to it. - void GetNotificationsSettings( - HostContentSettingsMap::SettingsForOneType* settings); + void GetNotificationsSettings(ContentSettingsForOneType* settings); // Clears the notifications setting for the given pattern. void ClearSetting(const ContentSettingsPattern& pattern); diff --git a/chrome/browser/notifications/desktop_notification_service_unittest.cc b/chrome/browser/notifications/desktop_notification_service_unittest.cc index c60e627..008589f 100644 --- a/chrome/browser/notifications/desktop_notification_service_unittest.cc +++ b/chrome/browser/notifications/desktop_notification_service_unittest.cc @@ -8,7 +8,6 @@ #include "base/memory/scoped_ptr.h" #include "base/message_loop.h" #include "base/synchronization/waitable_event.h" -#include "chrome/browser/content_settings/host_content_settings_map.h" #include "chrome/browser/notifications/desktop_notification_service_factory.h" #include "chrome/test/base/chrome_render_view_host_test_harness.h" #include "chrome/test/base/testing_profile.h" @@ -162,33 +161,33 @@ TEST_F(DesktopNotificationServiceTest, GetNotificationsSettings) { service_->DenyPermission(GURL("http://denied2.com")); service_->DenyPermission(GURL("http://denied.com")); - HostContentSettingsMap::SettingsForOneType settings; + ContentSettingsForOneType settings; service_->GetNotificationsSettings(&settings); // |settings| contains the default setting and 4 exceptions. ASSERT_EQ(5u, settings.size()); EXPECT_EQ(ContentSettingsPattern::FromURLNoWildcard( GURL("http://allowed.com")), - settings[0].a); + settings[0].primary_pattern); EXPECT_EQ(CONTENT_SETTING_ALLOW, - settings[0].c); + settings[0].setting); EXPECT_EQ(ContentSettingsPattern::FromURLNoWildcard( GURL("http://allowed2.com")), - settings[1].a); + settings[1].primary_pattern); EXPECT_EQ(CONTENT_SETTING_ALLOW, - settings[1].c); + settings[1].setting); EXPECT_EQ(ContentSettingsPattern::FromURLNoWildcard( GURL("http://denied.com")), - settings[2].a); + settings[2].primary_pattern); EXPECT_EQ(CONTENT_SETTING_BLOCK, - settings[2].c); + settings[2].setting); EXPECT_EQ(ContentSettingsPattern::FromURLNoWildcard( GURL("http://denied2.com")), - settings[3].a); + settings[3].primary_pattern); EXPECT_EQ(CONTENT_SETTING_BLOCK, - settings[3].c); + settings[3].setting); EXPECT_EQ(ContentSettingsPattern::Wildcard(), - settings[4].a); + settings[4].primary_pattern); EXPECT_EQ(CONTENT_SETTING_ASK, - settings[4].c); + settings[4].setting); } diff --git a/chrome/browser/ui/webui/options/content_settings_handler.cc b/chrome/browser/ui/webui/options/content_settings_handler.cc index 3ccff843..7f6b9e09 100644 --- a/chrome/browser/ui/webui/options/content_settings_handler.cc +++ b/chrome/browser/ui/webui/options/content_settings_handler.cc @@ -24,6 +24,7 @@ #include "chrome/browser/ui/browser_list.h" #include "chrome/common/chrome_notification_types.h" #include "chrome/common/chrome_switches.h" +#include "chrome/common/content_settings.h" #include "chrome/common/content_settings_pattern.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" @@ -468,7 +469,7 @@ void ContentSettingsHandler::UpdateGeolocationExceptionsView() { Profile* profile = Profile::FromWebUI(web_ui_); HostContentSettingsMap* map = profile->GetHostContentSettingsMap(); - HostContentSettingsMap::SettingsForOneType all_settings; + ContentSettingsForOneType all_settings; map->GetSettingsForOneType( CONTENT_SETTINGS_TYPE_GEOLOCATION, std::string(), @@ -476,11 +477,12 @@ void ContentSettingsHandler::UpdateGeolocationExceptionsView() { // Group geolocation settings by primary_pattern. AllPatternsSettings all_patterns_settings; - for (HostContentSettingsMap::SettingsForOneType::iterator i = + for (ContentSettingsForOneType::iterator i = all_settings.begin(); i != all_settings.end(); ++i) { - all_patterns_settings[i->a][i->b] = i->c; + all_patterns_settings[i->primary_pattern][i->secondary_pattern] = + i->setting; } ListValue exceptions; @@ -528,17 +530,17 @@ void ContentSettingsHandler::UpdateNotificationExceptionsView() { DesktopNotificationService* service = DesktopNotificationServiceFactory::GetForProfile(profile); - HostContentSettingsMap::SettingsForOneType settings; + ContentSettingsForOneType settings; service->GetNotificationsSettings(&settings); ListValue exceptions; - for (HostContentSettingsMap::SettingsForOneType::const_iterator i = + for (ContentSettingsForOneType::const_iterator i = settings.begin(); i != settings.end(); ++i) { - const HostContentSettingsMap::PatternSettingSourceTuple& tuple(*i); exceptions.Append( - GetNotificationExceptionForPage(tuple.a, tuple.c, tuple.d)); + GetNotificationExceptionForPage(i->primary_pattern, i->setting, + i->source)); } StringValue type_string( @@ -553,16 +555,16 @@ void ContentSettingsHandler::UpdateNotificationExceptionsView() { void ContentSettingsHandler::UpdateExceptionsViewFromHostContentSettingsMap( ContentSettingsType type) { - HostContentSettingsMap::SettingsForOneType entries; + ContentSettingsForOneType entries; GetContentSettingsMap()->GetSettingsForOneType(type, "", &entries); ListValue exceptions; for (size_t i = 0; i < entries.size(); ++i) { // Skip default settings from extensions and policy, and the default content // settings; all of them will affect the default setting UI. - if (entries[i].a == ContentSettingsPattern::Wildcard() && - entries[i].b == ContentSettingsPattern::Wildcard() && - entries[i].d != "preference") { + if (entries[i].primary_pattern == ContentSettingsPattern::Wildcard() && + entries[i].secondary_pattern == ContentSettingsPattern::Wildcard() && + entries[i].source != "preference") { continue; } // The content settings UI does not support secondary content settings @@ -571,9 +573,10 @@ void ContentSettingsHandler::UpdateExceptionsViewFromHostContentSettingsMap( // able to modify content settings with a secondary pattern other than the // wildcard pattern. So only show settings that the user is able to modify. // TODO(bauerb): Support a read-only view for those patterns. - if (entries[i].b == ContentSettingsPattern::Wildcard()) { + if (entries[i].secondary_pattern == ContentSettingsPattern::Wildcard()) { exceptions.Append( - GetExceptionForPage(entries[i].a, entries[i].c, entries[i].d)); + GetExceptionForPage(entries[i].primary_pattern, entries[i].setting, + entries[i].source)); } else { LOG(ERROR) << "Secondary content settings patterns are not " << "supported by the content settings UI"; @@ -597,7 +600,7 @@ void ContentSettingsHandler::UpdateExceptionsViewFromOTRHostContentSettingsMap( if (!otr_settings_map) return; - HostContentSettingsMap::SettingsForOneType otr_entries; + ContentSettingsForOneType otr_entries; otr_settings_map->GetSettingsForOneType(type, "", &otr_entries); ListValue otr_exceptions; @@ -605,7 +608,7 @@ void ContentSettingsHandler::UpdateExceptionsViewFromOTRHostContentSettingsMap( // Off-the-record HostContentSettingsMap contains incognito content settings // as well as normal content settings. Here, we use the incongnito settings // only. - if (!otr_entries[i].e) + if (!otr_entries[i].incognito) continue; // The content settings UI does not support secondary content settings // pattern yet. For content settings set through the content settings UI the @@ -613,11 +616,12 @@ void ContentSettingsHandler::UpdateExceptionsViewFromOTRHostContentSettingsMap( // able to modify content settings with a secondary pattern other than the // wildcard pattern. So only show settings that the user is able to modify. // TODO(bauerb): Support a read-only view for those patterns. - if (otr_entries[i].b == ContentSettingsPattern::Wildcard()) { + if (otr_entries[i].secondary_pattern == + ContentSettingsPattern::Wildcard()) { otr_exceptions.Append( - GetExceptionForPage(otr_entries[i].a, - otr_entries[i].c, - otr_entries[i].d)); + GetExceptionForPage(otr_entries[i].primary_pattern, + otr_entries[i].setting, + otr_entries[i].source)); } else { LOG(ERROR) << "Secondary content settings patterns are not " << "supported by the content settings UI"; diff --git a/chrome/common/content_settings.cc b/chrome/common/content_settings.cc index 89eaa59..ecf26f8 100644 --- a/chrome/common/content_settings.cc +++ b/chrome/common/content_settings.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -9,3 +9,27 @@ ContentSetting IntToContentSetting(int content_setting) { (content_setting >= CONTENT_SETTING_NUM_SETTINGS)) ? CONTENT_SETTING_DEFAULT : static_cast<ContentSetting>(content_setting); } + +ContentSettings::ContentSettings() { + for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) + settings[i] = CONTENT_SETTING_DEFAULT; +} + +ContentSettings::ContentSettings(ContentSetting default_setting) { + for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) + settings[i] = default_setting; +} + +ContentSettingPatternSource::ContentSettingPatternSource( + const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_pattern, + ContentSetting setting, + const std::string& source, + bool incognito) + : primary_pattern(primary_pattern), + secondary_pattern(secondary_pattern), + setting(setting), + source(source), + incognito(incognito) {} + +ContentSettingPatternSource::ContentSettingPatternSource() {} diff --git a/chrome/common/content_settings.h b/chrome/common/content_settings.h index 4731263..2c7e5c2 100644 --- a/chrome/common/content_settings.h +++ b/chrome/common/content_settings.h @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -6,6 +6,10 @@ #define CHROME_COMMON_CONTENT_SETTINGS_H_ #pragma once +#include <string> +#include <vector> + +#include "chrome/common/content_settings_pattern.h" #include "chrome/common/content_settings_types.h" // Different settings that can be assigned for a particular content type. We @@ -25,17 +29,26 @@ ContentSetting IntToContentSetting(int content_setting); // Aggregates the permissions for the different content types. struct ContentSettings { - ContentSettings() { - for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) - settings[i] = CONTENT_SETTING_DEFAULT; - } - - explicit ContentSettings(ContentSetting default_setting) { - for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) - settings[i] = default_setting; - } + ContentSettings(); + explicit ContentSettings(ContentSetting default_setting); ContentSetting settings[CONTENT_SETTINGS_NUM_TYPES]; }; +struct ContentSettingPatternSource { + ContentSettingPatternSource(const ContentSettingsPattern& primary_pattern, + const ContentSettingsPattern& secondary_patttern, + ContentSetting setting, + const std::string& source, + bool incognito); + ContentSettingPatternSource(); + ContentSettingsPattern primary_pattern; + ContentSettingsPattern secondary_pattern; + ContentSetting setting; + std::string source; + bool incognito; +}; + +typedef std::vector<ContentSettingPatternSource> ContentSettingsForOneType; + #endif // CHROME_COMMON_CONTENT_SETTINGS_H_ diff --git a/chrome/common/extensions/api/extension_api.json b/chrome/common/extensions/api/extension_api.json index 7745b84..9202df4 100644 --- a/chrome/common/extensions/api/extension_api.json +++ b/chrome/common/extensions/api/extension_api.json @@ -8380,7 +8380,7 @@ }, "images": { "$ref": "ContentSetting", - "description": "Whether to show images. One of<br><var>allow</var>: Show images,<br><var>block</var>: Don't show images. <br>Default is <var>allow</var>.<br>The primary URL is the main-frame URL. The secondary URL is not used.", + "description": "Whether to show images. One of<br><var>allow</var>: Show images,<br><var>block</var>: Don't show images. <br>Default is <var>allow</var>.<br>The primary URL is the main-frame URL. The secondary URL is the URL of the image.", "value": [ "images", {"type":"string", "enum": ["allow", "block"]} diff --git a/chrome/common/extensions/docs/contentSettings.html b/chrome/common/extensions/docs/contentSettings.html index ba82881..86ea6df 100644 --- a/chrome/common/extensions/docs/contentSettings.html +++ b/chrome/common/extensions/docs/contentSettings.html @@ -628,7 +628,7 @@ You can find samples of this API on the <dd class="todo" style="display: none; "> Undocumented. </dd> - <dd>Whether to show images. One of<br><var>allow</var>: Show images,<br><var>block</var>: Don't show images. <br>Default is <var>allow</var>.<br>The primary URL is the main-frame URL. The secondary URL is not used.</dd> + <dd>Whether to show images. One of<br><var>allow</var>: Show images,<br><var>block</var>: Don't show images. <br>Default is <var>allow</var>.<br>The primary URL is the main-frame URL. The secondary URL is the URL of the image.</dd> <dd style="display: none; "> This parameter was added in version <b><span></span></b>. diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h index b7af0d1..87822fb 100644 --- a/chrome/common/render_messages.h +++ b/chrome/common/render_messages.h @@ -17,6 +17,7 @@ #include "base/values.h" #include "build/build_config.h" #include "chrome/common/common_param_traits.h" +#include "chrome/common/content_settings.h" #include "chrome/common/content_settings_pattern.h" #include "chrome/common/instant_types.h" #include "chrome/common/nacl_types.h" @@ -136,6 +137,14 @@ IPC_STRUCT_TRAITS_BEGIN(ContentSettingsPattern::PatternParts) IPC_STRUCT_TRAITS_MEMBER(path) IPC_STRUCT_TRAITS_END() +IPC_STRUCT_TRAITS_BEGIN(ContentSettingPatternSource) + IPC_STRUCT_TRAITS_MEMBER(primary_pattern) + IPC_STRUCT_TRAITS_MEMBER(secondary_pattern) + IPC_STRUCT_TRAITS_MEMBER(setting) + IPC_STRUCT_TRAITS_MEMBER(source) + IPC_STRUCT_TRAITS_MEMBER(incognito) +IPC_STRUCT_TRAITS_END() + IPC_STRUCT_TRAITS_BEGIN(ThumbnailScore) IPC_STRUCT_TRAITS_MEMBER(boring_score) IPC_STRUCT_TRAITS_MEMBER(good_clipping) @@ -233,6 +242,10 @@ IPC_MESSAGE_CONTROL2(ChromeViewMsg_SetContentSettingsForCurrentURL, IPC_MESSAGE_CONTROL1(ChromeViewMsg_SetDefaultContentSettings, ContentSettings /* content_settings */) +// Set the content settings for images. +IPC_MESSAGE_CONTROL1(ChromeViewMsg_SetImageSettingRules, + ContentSettingsForOneType /* rules */) + // Tells the render view to load all blocked plugins. IPC_MESSAGE_ROUTED0(ChromeViewMsg_LoadBlockedPlugins) diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index ec598ef..5c461a7 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc @@ -225,6 +225,10 @@ void ChromeContentRendererClient::RenderViewCreated( content::RenderView* render_view) { ContentSettingsObserver* content_settings = new ContentSettingsObserver(render_view); + if (chrome_observer_.get()) { + content_settings->SetImageSettingRules( + chrome_observer_->image_setting_rules()); + } new ExtensionHelper(render_view, extension_dispatcher_.get()); new PageLoadHistograms(render_view, histogram_snapshots_.get()); new PrintWebViewHelper(render_view); diff --git a/chrome/renderer/chrome_render_process_observer.cc b/chrome/renderer/chrome_render_process_observer.cc index b642d61..41e6f97 100644 --- a/chrome/renderer/chrome_render_process_observer.cc +++ b/chrome/renderer/chrome_render_process_observer.cc @@ -267,6 +267,8 @@ bool ChromeRenderProcessObserver::OnControlMessageReceived( OnSetDefaultContentSettings) IPC_MESSAGE_HANDLER(ChromeViewMsg_SetContentSettingsForCurrentURL, OnSetContentSettingsForCurrentURL) + IPC_MESSAGE_HANDLER(ChromeViewMsg_SetImageSettingRules, + OnSetImageSettingRules) IPC_MESSAGE_HANDLER(ChromeViewMsg_SetCacheCapacities, OnSetCacheCapacities) IPC_MESSAGE_HANDLER(ChromeViewMsg_ClearCache, OnClearCache) IPC_MESSAGE_HANDLER(ChromeViewMsg_SetFieldTrialGroup, OnSetFieldTrialGroup) @@ -308,6 +310,11 @@ void ChromeRenderProcessObserver::OnSetDefaultContentSettings( ContentSettingsObserver::SetDefaultContentSettings(content_settings); } +void ChromeRenderProcessObserver::OnSetImageSettingRules( + const ContentSettingsForOneType& settings) { + image_setting_rules_ = settings; +} + void ChromeRenderProcessObserver::OnSetCacheCapacities(size_t min_dead_capacity, size_t max_dead_capacity, size_t capacity) { @@ -422,3 +429,8 @@ void ChromeRenderProcessObserver::ExecutePendingClearCache() { WebCache::clear(); } } + +const ContentSettingsForOneType* +ChromeRenderProcessObserver::image_setting_rules() const { + return &image_setting_rules_; +} diff --git a/chrome/renderer/chrome_render_process_observer.h b/chrome/renderer/chrome_render_process_observer.h index 7c14c24..44477b8 100644 --- a/chrome/renderer/chrome_render_process_observer.h +++ b/chrome/renderer/chrome_render_process_observer.h @@ -11,6 +11,7 @@ #include "base/compiler_specific.h" #include "base/file_path.h" #include "base/memory/scoped_ptr.h" +#include "chrome/common/content_settings.h" #include "content/public/renderer/render_process_observer.h" class GURL; @@ -40,6 +41,10 @@ class ChromeRenderProcessObserver : public content::RenderProcessObserver { // any 'clear cache' commands that were delayed until the next navigation. void ExecutePendingClearCache(); + // Returns a pointer to the image setting rules owned by + // |ChromeRenderProcessObserver|. + const ContentSettingsForOneType* image_setting_rules() const; + private: // RenderProcessObserver implementation. virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE; @@ -49,6 +54,7 @@ class ChromeRenderProcessObserver : public content::RenderProcessObserver { void OnSetContentSettingsForCurrentURL( const GURL& url, const ContentSettings& content_settings); void OnSetDefaultContentSettings(const ContentSettings& content_settings); + void OnSetImageSettingRules(const ContentSettingsForOneType& settings); void OnSetCacheCapacities(size_t min_dead_capacity, size_t max_dead_capacity, size_t capacity); @@ -69,6 +75,7 @@ class ChromeRenderProcessObserver : public content::RenderProcessObserver { chrome::ChromeContentRendererClient* client_; // If true, the web cache shall be cleared before the next navigation event. bool clear_cache_pending_; + ContentSettingsForOneType image_setting_rules_; DISALLOW_COPY_AND_ASSIGN(ChromeRenderProcessObserver); }; diff --git a/chrome/renderer/content_settings_observer.cc b/chrome/renderer/content_settings_observer.cc index 94150e6..525159f 100644 --- a/chrome/renderer/content_settings_observer.cc +++ b/chrome/renderer/content_settings_observer.cc @@ -50,6 +50,15 @@ static bool IsWhitelistedForContentSettings(WebFrame* frame) { return false; } +GURL GetOriginOrURL(const WebFrame* frame) { + WebString top_origin = frame->top()->document().securityOrigin().toString(); + // The the |top_origin| is unique ("null") e.g., for file:// URLs. Use the + // document URL as the primary URL in those cases. + if (top_origin == "null") + return frame->document().url(); + return GURL(top_origin); +} + } // namespace ContentSettings ContentSettingsObserver::default_settings_; @@ -75,6 +84,11 @@ void ContentSettingsObserver::SetDefaultContentSettings( default_settings_ = settings; } +void ContentSettingsObserver::SetImageSettingRules( + const ContentSettingsForOneType* image_setting_rules) { + image_setting_rules_ = image_setting_rules; +} + ContentSetting ContentSettingsObserver::GetContentSetting( ContentSettingsType type) { // Don't call this for plug-ins. @@ -118,7 +132,7 @@ void ContentSettingsObserver::DidCommitProvisionalLoad( NavigationState* state = NavigationState::FromDataSource(frame->dataSource()); if (!state->was_within_same_page()) { // Clear "block" flags for the new page. This needs to happen before any of - // allowScripts(), allowImages(), allowPlugins() is called for the new page + // allowScripts(), allowImage(), allowPlugins() is called for the new page // so that these functions can correctly detect that a piece of content // flipped from "not blocked" to "blocked". ClearBlockedContentSettings(); @@ -198,16 +212,28 @@ bool ContentSettingsObserver::AllowFileSystem(WebFrame* frame) { bool ContentSettingsObserver::AllowImage(WebFrame* frame, bool enabled_per_settings, const WebURL& image_url) { - if (enabled_per_settings && - AllowContentType(CONTENT_SETTINGS_TYPE_IMAGES)) { - return true; - } - if (IsWhitelistedForContentSettings(frame)) return true; - DidBlockContentType(CONTENT_SETTINGS_TYPE_IMAGES, std::string()); - return false; // Other protocols fall through here. + bool allow = enabled_per_settings; + const GURL& primary_url = GetOriginOrURL(frame); + GURL secondary_url(image_url); + if (image_setting_rules_ && + enabled_per_settings) { + ContentSettingsForOneType::const_iterator it; + for (it = image_setting_rules_->begin(); + it != image_setting_rules_->end(); ++it) { + if (it->primary_pattern.Matches(primary_url) && + it->secondary_pattern.Matches(secondary_url)) { + allow = (it->setting != CONTENT_SETTING_BLOCK); + break; + } + } + } + + if (!allow) + DidBlockContentType(CONTENT_SETTINGS_TYPE_IMAGES, std::string()); + return allow; } bool ContentSettingsObserver::AllowIndexedDB(WebFrame* frame, diff --git a/chrome/renderer/content_settings_observer.h b/chrome/renderer/content_settings_observer.h index 45f2125..3055caa 100644 --- a/chrome/renderer/content_settings_observer.h +++ b/chrome/renderer/content_settings_observer.h @@ -27,14 +27,19 @@ class ContentSettingsObserver explicit ContentSettingsObserver(content::RenderView* render_view); virtual ~ContentSettingsObserver(); - // Sets the content settings that back allowScripts(), allowImages(), and - // allowPlugins(). + // Sets the content settings that back allowScripts() and allowPlugins(). void SetContentSettings(const ContentSettings& settings); - // Sets the default content settings that back allowScripts(), - // allowImages(), and allowPlugins(). + // Sets the default content settings that back allowScripts() and + // allowPlugins(). static void SetDefaultContentSettings(const ContentSettings& settings); + // Sets the image setting rules which back |allowImage()|. The + // |ContentSettingsForOneType| object must outlive this + // |ContentSettingsObserver|. + void SetImageSettingRules( + const ContentSettingsForOneType* image_setting_rules); + // Returns the setting for the given type. ContentSetting GetContentSetting(ContentSettingsType type); @@ -90,11 +95,17 @@ class ContentSettingsObserver HostContentSettings host_content_settings_; // Stores our most up-to-date view of the default content settings. + // TODO(marja): Store default settings in |ChromeRenderProcessObserver|. static ContentSettings default_settings_; - // Stores if loading of images, scripts, and plugins is allowed. + // Stores if loading of scripts and plugins is allowed. ContentSettings current_content_settings_; + // Stores the rules for image content settings. Normally, they are owned by + // |ChromeRenderProcessObserver|; in the tests they are owned by the caller of + // |SetImageSettingRules|. + const ContentSettingsForOneType* image_setting_rules_; + // Stores if images, scripts, and plugins have actually been blocked. bool content_blocked_[CONTENT_SETTINGS_NUM_TYPES]; diff --git a/chrome/renderer/content_settings_observer_browsertest.cc b/chrome/renderer/content_settings_observer_browsertest.cc index ceaaee1..9326407 100644 --- a/chrome/renderer/content_settings_observer_browsertest.cc +++ b/chrome/renderer/content_settings_observer_browsertest.cc @@ -28,11 +28,15 @@ class MockContentSettingsObserver : public ContentSettingsObserver { MOCK_METHOD5(OnAllowDOMStorage, void(int, const GURL&, const GURL&, bool, IPC::Message*)); + GURL image_url_; + std::string image_origin_; }; MockContentSettingsObserver::MockContentSettingsObserver( content::RenderView* render_view) - : ContentSettingsObserver(render_view) { + : ContentSettingsObserver(render_view), + image_url_("http://www.foo.com/image.jpg"), + image_origin_("http://www.foo.com") { } bool MockContentSettingsObserver::Send(IPC::Message* message) { @@ -162,3 +166,84 @@ TEST_F(ChromeRenderViewTest, PluginsTemporarilyAllowed) { LoadHTML("<html>Bar</html>"); EXPECT_FALSE(observer->plugins_temporarily_allowed()); } + +TEST_F(ChromeRenderViewTest, ImagesBlockedByDefault) { + MockContentSettingsObserver mock_observer(view_); + + // Load some HTML. + LoadHTML("<html>Foo</html>"); + + // Set the default image blocking setting. + ContentSettingsForOneType image_setting_rules; + image_setting_rules.push_back( + ContentSettingPatternSource(ContentSettingsPattern::Wildcard(), + ContentSettingsPattern::Wildcard(), + CONTENT_SETTING_BLOCK, + "", + false)); + + ContentSettingsObserver* observer = ContentSettingsObserver::Get(view_); + observer->SetImageSettingRules(&image_setting_rules); + EXPECT_CALL(mock_observer, + OnContentBlocked(CONTENT_SETTINGS_TYPE_IMAGES, std::string())); + EXPECT_FALSE(observer->AllowImage(GetMainFrame(), + true, mock_observer.image_url_)); + ::testing::Mock::VerifyAndClearExpectations(&observer); + + // Create an exception which allows the image. + image_setting_rules.insert( + image_setting_rules.begin(), + ContentSettingPatternSource( + ContentSettingsPattern::Wildcard(), + ContentSettingsPattern::FromString(mock_observer.image_origin_), + CONTENT_SETTING_ALLOW, + "", + false)); + + EXPECT_CALL( + mock_observer, + OnContentBlocked(CONTENT_SETTINGS_TYPE_IMAGES, std::string())).Times(0); + EXPECT_TRUE(observer->AllowImage(GetMainFrame(), true, + mock_observer.image_url_)); + ::testing::Mock::VerifyAndClearExpectations(&observer); +} + +TEST_F(ChromeRenderViewTest, ImagesAllowedByDefault) { + MockContentSettingsObserver mock_observer(view_); + + // Load some HTML. + LoadHTML("<html>Foo</html>"); + + // Set the default image blocking setting. + ContentSettingsForOneType image_setting_rules; + image_setting_rules.push_back( + ContentSettingPatternSource(ContentSettingsPattern::Wildcard(), + ContentSettingsPattern::Wildcard(), + CONTENT_SETTING_ALLOW, + "", + false)); + + ContentSettingsObserver* observer = ContentSettingsObserver::Get(view_); + observer->SetImageSettingRules(&image_setting_rules); + EXPECT_CALL( + mock_observer, + OnContentBlocked(CONTENT_SETTINGS_TYPE_IMAGES, std::string())).Times(0); + EXPECT_TRUE(observer->AllowImage(GetMainFrame(), true, + mock_observer.image_url_)); + ::testing::Mock::VerifyAndClearExpectations(&observer); + + // Create an exception which blocks the image. + image_setting_rules.insert( + image_setting_rules.begin(), + ContentSettingPatternSource( + ContentSettingsPattern::Wildcard(), + ContentSettingsPattern::FromString(mock_observer.image_origin_), + CONTENT_SETTING_BLOCK, + "", + false)); + EXPECT_CALL(mock_observer, + OnContentBlocked(CONTENT_SETTINGS_TYPE_IMAGES, std::string())); + EXPECT_FALSE(observer->AllowImage(GetMainFrame(), + true, mock_observer.image_url_)); + ::testing::Mock::VerifyAndClearExpectations(&observer); +} |