diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-18 17:00:15 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-18 17:00:15 +0000 |
commit | 5e56df8fb10f7aca72c51184ea66e4d5462d31e3 (patch) | |
tree | d49606d0e1af4ec568dfa8f03c778c7ae0780d06 | |
parent | f3f4d7fc63d2e686208de341e01c559a2f0a4487 (diff) | |
download | chromium_src-5e56df8fb10f7aca72c51184ea66e4d5462d31e3.zip chromium_src-5e56df8fb10f7aca72c51184ea66e4d5462d31e3.tar.gz chromium_src-5e56df8fb10f7aca72c51184ea66e4d5462d31e3.tar.bz2 |
Move the content settings code out of RenderView, since it belongs in the Chrome layer.
BUG=76793
Review URL: http://codereview.chromium.org/6873040
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@81955 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/chrome_renderer.gypi | 2 | ||||
-rw-r--r-- | chrome/renderer/chrome_content_renderer_client.cc | 9 | ||||
-rw-r--r-- | chrome/renderer/chrome_render_process_observer.cc | 7 | ||||
-rw-r--r-- | chrome/renderer/content_settings_observer.cc | 184 | ||||
-rw-r--r-- | chrome/renderer/content_settings_observer.h | 74 | ||||
-rw-r--r-- | chrome/renderer/content_settings_observer_browsertest.cc | 61 | ||||
-rw-r--r-- | content/renderer/render_view.cc | 137 | ||||
-rw-r--r-- | content/renderer/render_view.h | 47 | ||||
-rw-r--r-- | content/renderer/render_view_browsertest.cc | 50 | ||||
-rw-r--r-- | content/renderer/render_view_observer.cc | 17 | ||||
-rw-r--r-- | content/renderer/render_view_observer.h | 6 |
11 files changed, 399 insertions, 195 deletions
diff --git a/chrome/chrome_renderer.gypi b/chrome/chrome_renderer.gypi index 9bd1bac..dd3929e 100644 --- a/chrome/chrome_renderer.gypi +++ b/chrome/chrome_renderer.gypi @@ -99,6 +99,8 @@ 'renderer/chrome_render_process_observer.h', 'renderer/chrome_render_view_observer.cc', 'renderer/chrome_render_view_observer.h', + 'renderer/content_settings_observer.cc', + 'renderer/content_settings_observer.h', 'renderer/devtools_agent.cc', 'renderer/devtools_agent.h', 'renderer/devtools_agent_filter.cc', diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index 1bdf1b5..76bd2da 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc @@ -30,6 +30,7 @@ #include "chrome/renderer/blocked_plugin.h" #include "chrome/renderer/chrome_render_process_observer.h" #include "chrome/renderer/chrome_render_view_observer.h" +#include "chrome/renderer/content_settings_observer.h" #include "chrome/renderer/devtools_agent.h" #include "chrome/renderer/devtools_agent_filter.h" #include "chrome/renderer/extensions/bindings_utils.h" @@ -281,6 +282,7 @@ void ChromeContentRendererClient::RenderViewCreated(RenderView* render_view) { } #endif + new ContentSettingsObserver(render_view); new DevToolsAgent(render_view); new ExtensionHelper(render_view, extension_dispatcher_.get()); new PageLoadHistograms(render_view, histogram_snapshots_.get()); @@ -381,8 +383,9 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin( } } - ContentSetting host_setting = render_view->current_content_settings_. - settings[CONTENT_SETTINGS_TYPE_PLUGINS]; + ContentSettingsObserver* observer = ContentSettingsObserver::Get(render_view); + ContentSetting host_setting = + observer->GetContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS); if (group->RequiresAuthorization() && !cmd->HasSwitch(switches::kAlwaysAuthorizePlugins) && @@ -425,7 +428,7 @@ WebPlugin* ChromeContentRendererClient::CreatePlugin( std::string resource; if (cmd->HasSwitch(switches::kEnableResourceContentSettings)) resource = group->identifier(); - render_view->DidBlockContentType(CONTENT_SETTINGS_TYPE_PLUGINS, resource); + observer->DidBlockContentType(CONTENT_SETTINGS_TYPE_PLUGINS, resource); if (plugin_setting == CONTENT_SETTING_ASK) { return CreatePluginPlaceholder( render_view, frame, params, *group, IDR_CLICK_TO_PLAY_PLUGIN_HTML, diff --git a/chrome/renderer/chrome_render_process_observer.cc b/chrome/renderer/chrome_render_process_observer.cc index 5a3d89a..4d7672b 100644 --- a/chrome/renderer/chrome_render_process_observer.cc +++ b/chrome/renderer/chrome_render_process_observer.cc @@ -12,6 +12,7 @@ #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/render_messages.h" +#include "chrome/renderer/content_settings_observer.h" #include "content/common/view_messages.h" #include "content/renderer/render_thread.h" #include "content/renderer/render_view.h" @@ -83,8 +84,10 @@ class RenderViewContentSettingsSetter : public RenderViewVisitor { } virtual bool Visit(RenderView* render_view) { - if (GURL(render_view->webview()->mainFrame()->url()) == url_) - render_view->SetContentSettings(content_settings_); + if (GURL(render_view->webview()->mainFrame()->url()) == url_) { + ContentSettingsObserver::Get(render_view)->SetContentSettings( + content_settings_); + } return true; } diff --git a/chrome/renderer/content_settings_observer.cc b/chrome/renderer/content_settings_observer.cc new file mode 100644 index 0000000..b752f9b --- /dev/null +++ b/chrome/renderer/content_settings_observer.cc @@ -0,0 +1,184 @@ +// 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. + +#include "chrome/renderer/content_settings_observer.h" + +#include "chrome/common/render_messages.h" +#include "chrome/common/url_constants.h" +#include "content/renderer/render_view.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebDataSource.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrameClient.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h" +#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" + +using WebKit::WebDataSource; +using WebKit::WebFrame; +using WebKit::WebFrameClient; +using WebKit::WebSecurityOrigin; +using WebKit::WebURLRequest; +using WebKit::WebView; + +namespace { + +// True if |frame| contains content that is white-listed for content settings. +static bool IsWhitelistedForContentSettings(WebFrame* frame) { + WebSecurityOrigin origin = frame->securityOrigin(); + if (origin.isEmpty()) + return false; // Uninitialized document? + + if (EqualsASCII(origin.protocol(), chrome::kChromeUIScheme)) + return true; // Browser UI elements should still work. + + // If the scheme is ftp: or file:, an empty file name indicates a directory + // listing, which requires JavaScript to function properly. + GURL frame_url = frame->url(); + const char* kDirProtocols[] = { "ftp", "file" }; + for (size_t i = 0; i < arraysize(kDirProtocols); ++i) { + if (EqualsASCII(origin.protocol(), kDirProtocols[i])) { + return frame_url.SchemeIs(kDirProtocols[i]) && + frame_url.ExtractFileName().empty(); + } + } + + return false; +} + +} // namespace + +ContentSettingsObserver::ContentSettingsObserver(RenderView* render_view) + : RenderViewObserver(render_view), + RenderViewObserverTracker<ContentSettingsObserver>(render_view) { + ClearBlockedContentSettings(); +} + +ContentSettingsObserver::~ContentSettingsObserver() { +} + + +void ContentSettingsObserver::SetContentSettings( + const ContentSettings& settings) { + current_content_settings_ = settings; +} + +ContentSetting ContentSettingsObserver::GetContentSetting( + ContentSettingsType type) { + return current_content_settings_.settings[type]; +} + +void ContentSettingsObserver::DidBlockContentType( + ContentSettingsType settings_type, + const std::string& resource_identifier) { + if (!content_blocked_[settings_type]) { + content_blocked_[settings_type] = true; + Send(new ViewHostMsg_ContentBlocked(routing_id(), settings_type, + resource_identifier)); + } +} + +bool ContentSettingsObserver::OnMessageReceived(const IPC::Message& message) { + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(ContentSettingsObserver, message) + IPC_MESSAGE_HANDLER(ViewMsg_SetContentSettingsForLoadingURL, + OnSetContentSettingsForLoadingURL) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; +} + +void ContentSettingsObserver::DidCommitProvisionalLoad( + WebFrame* frame, bool is_new_navigation) { + if (frame->parent()) + return; // Not a top-level navigation. + + WebDataSource* ds = frame->dataSource(); + const WebURLRequest& request = ds->request(); + + // Clear "block" flags for the new page. This needs to happen before any of + // allowScripts(), allowImages(), 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(); + + // Set content settings. Default them from the parent window if one exists. + // This makes sure about:blank windows work as expected. + HostContentSettings::iterator host_content_settings = + host_content_settings_.find(GURL(request.url())); + if (host_content_settings != host_content_settings_.end()) { + SetContentSettings(host_content_settings->second); + + // These content settings were merely recorded transiently for this load. + // We can erase them now. If at some point we reload this page, the + // browser will send us new, up-to-date content settings. + host_content_settings_.erase(host_content_settings); + } else if (frame->opener()) { + // The opener's view is not guaranteed to be non-null (it could be + // detached from its page but not yet destructed). + if (WebView* opener_view = frame->opener()->view()) { + RenderView* opener = RenderView::FromWebView(opener_view); + ContentSettingsObserver* observer = ContentSettingsObserver::Get(opener); + SetContentSettings(observer->current_content_settings_); + } + } +} + +bool ContentSettingsObserver::AllowImages(WebFrame* frame, + bool enabled_per_settings) { + 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 ContentSettingsObserver::AllowPlugins(WebFrame* frame, + bool enabled_per_settings) { + return render_view()->WebFrameClient::allowPlugins( + frame, enabled_per_settings); +} + +bool ContentSettingsObserver::AllowScript(WebFrame* frame, + bool enabled_per_settings) { + if (enabled_per_settings && + AllowContentType(CONTENT_SETTINGS_TYPE_JAVASCRIPT)) { + return true; + } + + if (IsWhitelistedForContentSettings(frame)) + return true; + + return false; // Other protocols fall through here. +} + +void ContentSettingsObserver::DidNotAllowPlugins(WebFrame* frame) { + DidBlockContentType(CONTENT_SETTINGS_TYPE_PLUGINS, std::string()); +} + +void ContentSettingsObserver::DidNotAllowScript(WebFrame* frame) { + DidBlockContentType(CONTENT_SETTINGS_TYPE_JAVASCRIPT, std::string()); +} + +void ContentSettingsObserver::OnSetContentSettingsForLoadingURL( + const GURL& url, + const ContentSettings& content_settings) { + host_content_settings_[url] = content_settings; +} + +bool ContentSettingsObserver::AllowContentType( + ContentSettingsType settings_type) { + // CONTENT_SETTING_ASK is only valid for cookies. + return current_content_settings_.settings[settings_type] != + CONTENT_SETTING_BLOCK; +} + +void ContentSettingsObserver::ClearBlockedContentSettings() { + for (size_t i = 0; i < arraysize(content_blocked_); ++i) + content_blocked_[i] = false; +} diff --git a/chrome/renderer/content_settings_observer.h b/chrome/renderer/content_settings_observer.h new file mode 100644 index 0000000..52d89f5 --- /dev/null +++ b/chrome/renderer/content_settings_observer.h @@ -0,0 +1,74 @@ +// 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. + +#ifndef CHROME_RENDERER_CONTENT_SETTINGS_OBSERVER_H_ +#define CHROME_RENDERER_CONTENT_SETTINGS_OBSERVER_H_ +#pragma once + +#include <map> + +#include "chrome/common/content_settings.h" +#include "content/renderer/render_view_observer.h" +#include "content/renderer/render_view_observer_tracker.h" + +class GURL; + +// Handles blocking content per content settings for each RenderView. +class ContentSettingsObserver + : public RenderViewObserver, + public RenderViewObserverTracker<ContentSettingsObserver> { + public: + explicit ContentSettingsObserver(RenderView* render_view); + virtual ~ContentSettingsObserver(); + + // Sets the content settings that back allowScripts(), allowImages(), and + // allowPlugins(). + void SetContentSettings(const ContentSettings& settings); + + // Returns the setting for the given type. + ContentSetting GetContentSetting(ContentSettingsType type); + + // Sends an IPC notification that the specified content type was blocked. + // If the content type requires it, |resource_identifier| names the specific + // resource that was blocked (the plugin path in the case of plugins), + // otherwise it's the empty string. + void DidBlockContentType(ContentSettingsType settings_type, + const std::string& resource_identifier); + + private: + // RenderViewObserver implementation. + virtual bool OnMessageReceived(const IPC::Message& message); + virtual void DidCommitProvisionalLoad(WebKit::WebFrame* frame, + bool is_new_navigation); + virtual bool AllowImages(WebKit::WebFrame* frame, bool enabled_per_settings); + virtual bool AllowPlugins(WebKit::WebFrame* frame, bool enabled_per_settings); + virtual bool AllowScript(WebKit::WebFrame* frame, bool enabled_per_settings); + virtual void DidNotAllowPlugins(WebKit::WebFrame* frame); + virtual void DidNotAllowScript(WebKit::WebFrame* frame); + + // Message handlers. + void OnSetContentSettingsForLoadingURL( + const GURL& url, + const ContentSettings& content_settings); + + // Helper method that returns if the user wants to block content of type + // |content_type|. + bool AllowContentType(ContentSettingsType settings_type); + + // Resets the |content_blocked_| array. + void ClearBlockedContentSettings(); + + typedef std::map<GURL, ContentSettings> HostContentSettings; + HostContentSettings host_content_settings_; + + // Stores if loading of images, scripts, and plugins is allowed. + ContentSettings current_content_settings_; + + // Stores if images, scripts, and plugins have actually been blocked. + bool content_blocked_[CONTENT_SETTINGS_NUM_TYPES]; + + DISALLOW_COPY_AND_ASSIGN(ContentSettingsObserver); +}; + +#endif // CHROME_RENDERER_CONTENT_SETTINGS_OBSERVER_H_ diff --git a/chrome/renderer/content_settings_observer_browsertest.cc b/chrome/renderer/content_settings_observer_browsertest.cc new file mode 100644 index 0000000..c65592d --- /dev/null +++ b/chrome/renderer/content_settings_observer_browsertest.cc @@ -0,0 +1,61 @@ +// 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. + +#include "chrome/common/content_settings.h" +#include "chrome/common/render_messages.h" +#include "chrome/renderer/content_settings_observer.h" +#include "chrome/test/render_view_test.h" +#include "content/common/view_messages.h" +#include "testing/gtest/include/gtest/gtest.h" + +// Regression test for http://crbug.com/35011 +TEST_F(RenderViewTest, JSBlockSentAfterPageLoad) { + // 1. Load page with JS. + std::string html = "<html>" + "<head>" + "<script>document.createElement('div');</script>" + "</head>" + "<body>" + "</body>" + "</html>"; + render_thread_.sink().ClearMessages(); + LoadHTML(html.c_str()); + + // 2. Block JavaScript. + ContentSettings settings; + for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) + settings.settings[i] = CONTENT_SETTING_ALLOW; + settings.settings[CONTENT_SETTINGS_TYPE_JAVASCRIPT] = CONTENT_SETTING_BLOCK; + ContentSettingsObserver* observer = ContentSettingsObserver::Get(view_); + observer->SetContentSettings(settings); + + // Make sure no pending messages are in the queue. + ProcessPendingMessages(); + render_thread_.sink().ClearMessages(); + + // 3. Reload page. + ViewMsg_Navigate_Params params; + std::string url_str = "data:text/html;charset=utf-8,"; + url_str.append(html); + GURL url(url_str); + params.url = url; + params.navigation_type = ViewMsg_Navigate_Type::RELOAD; + view_->OnNavigate(params); + ProcessPendingMessages(); + + // 4. Verify that the notification that javascript was blocked is sent after + // the navigation notifiction is sent. + int navigation_index = -1; + int block_index = -1; + for (size_t i = 0; i < render_thread_.sink().message_count(); ++i) { + const IPC::Message* msg = render_thread_.sink().GetMessageAt(i); + if (msg->type() == ViewHostMsg_FrameNavigate::ID) + navigation_index = i; + if (msg->type() == ViewHostMsg_ContentBlocked::ID) + block_index = i; + } + EXPECT_NE(-1, navigation_index); + EXPECT_NE(-1, block_index); + EXPECT_LT(navigation_index, block_index); +} diff --git a/content/renderer/render_view.cc b/content/renderer/render_view.cc index 58f5cfc..a8c30e5 100644 --- a/content/renderer/render_view.cc +++ b/content/renderer/render_view.cc @@ -261,29 +261,6 @@ static void GetRedirectChain(WebDataSource* ds, std::vector<GURL>* result) { result->push_back(urls[i]); } -// True if |frame| contains content that is white-listed for content settings. -static bool IsWhitelistedForContentSettings(WebFrame* frame) { - WebSecurityOrigin origin = frame->securityOrigin(); - if (origin.isEmpty()) - return false; // Uninitialized document? - - if (EqualsASCII(origin.protocol(), chrome::kChromeUIScheme)) - return true; // Browser UI elements should still work. - - // If the scheme is ftp: or file:, an empty file name indicates a directory - // listing, which requires JavaScript to function properly. - GURL frame_url = frame->url(); - const char* kDirProtocols[] = { "ftp", "file" }; - for (size_t i = 0; i < arraysize(kDirProtocols); ++i) { - if (EqualsASCII(origin.protocol(), kDirProtocols[i])) { - return frame_url.SchemeIs(kDirProtocols[i]) && - frame_url.ExtractFileName().empty(); - } - } - - return false; -} - static bool WebAccessibilityNotificationToViewHostMsg( WebAccessibilityNotification notification, ViewHostMsg_AccessibilityNotification_Type::Value* type) { @@ -400,9 +377,6 @@ RenderView::RenderView(RenderThreadBase* render_thread, accessibility_ack_pending_(false), p2p_socket_dispatcher_(NULL), session_storage_namespace_id_(session_storage_namespace_id) { - - ClearBlockedContentSettings(); - routing_id_ = routing_id; if (opener_id != MSG_ROUTING_NONE) opener_id_ = opener_id; @@ -655,8 +629,6 @@ bool RenderView::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(ViewMsg_StopFinding, OnStopFinding) IPC_MESSAGE_HANDLER(ViewMsg_FindReplyACK, OnFindReplyAck) IPC_MESSAGE_HANDLER(ViewMsg_Zoom, OnZoom) - IPC_MESSAGE_HANDLER(ViewMsg_SetContentSettingsForLoadingURL, - OnSetContentSettingsForLoadingURL) IPC_MESSAGE_HANDLER(ViewMsg_SetZoomLevel, OnSetZoomLevel) IPC_MESSAGE_HANDLER(ViewMsg_SetZoomLevelForLoadingURL, OnSetZoomLevelForLoadingURL) @@ -971,10 +943,6 @@ void RenderView::OnScrollFocusedEditableNodeIntoView() { /////////////////////////////////////////////////////////////////////////////// -void RenderView::SetContentSettings(const ContentSettings& settings) { - current_content_settings_ = settings; -} - // Tell the embedding application that the URL of the active page has changed void RenderView::UpdateURL(WebFrame* frame) { WebDataSource* ds = frame->dataSource(); @@ -1043,32 +1011,6 @@ void RenderView::UpdateURL(WebFrame* frame) { if (!frame->parent()) { // Top-level navigation. - // Clear "block" flags for the new page. This needs to happen before any of - // allowScripts(), allowImages(), 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(); - - // Set content settings. Default them from the parent window if one exists. - // This makes sure about:blank windows work as expected. - HostContentSettings::iterator host_content_settings = - host_content_settings_.find(GURL(request.url())); - if (host_content_settings != host_content_settings_.end()) { - SetContentSettings(host_content_settings->second); - - // These content settings were merely recorded transiently for this load. - // We can erase them now. If at some point we reload this page, the - // browser will send us new, up-to-date content settings. - host_content_settings_.erase(host_content_settings); - } else if (frame->opener()) { - // The opener's view is not guaranteed to be non-null (it could be - // detached from its page but not yet destructed). - if (WebView* opener_view = frame->opener()->view()) { - RenderView* opener = FromWebView(opener_view); - SetContentSettings(opener->current_content_settings_); - } - } - // Set zoom level, but don't do it for full-page plugin since they don't use // the same zoom settings. HostZoomLevels::iterator host_zoom = @@ -1992,22 +1934,6 @@ void RenderView::willClose(WebFrame* frame) { FOR_EACH_OBSERVER(RenderViewObserver, observers_, FrameWillClose(frame)); } -bool RenderView::allowImages(WebFrame* frame, bool enabled_per_settings) { - 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 RenderView::allowPlugins(WebFrame* frame, bool enabled_per_settings) { - return WebFrameClient::allowPlugins(frame, enabled_per_settings); -} - void RenderView::loadURLExternally( WebFrame* frame, const WebURLRequest& request, WebNavigationPolicy policy) { @@ -2749,15 +2675,34 @@ void RenderView::didRunInsecureContent( target)); } -bool RenderView::allowScript(WebFrame* frame, bool enabled_per_settings) { - if (enabled_per_settings && - AllowContentType(CONTENT_SETTINGS_TYPE_JAVASCRIPT)) - return true; +bool RenderView::allowImages(WebFrame* frame, bool enabled_per_settings) { + ObserverListBase<RenderViewObserver>::Iterator it(observers_); + RenderViewObserver* observer; + while ((observer = it.GetNext()) != NULL) + if (!observer->AllowImages(frame, enabled_per_settings)) + return false; - if (IsWhitelistedForContentSettings(frame)) - return true; + return true; +} + +bool RenderView::allowPlugins(WebFrame* frame, bool enabled_per_settings) { + ObserverListBase<RenderViewObserver>::Iterator it(observers_); + RenderViewObserver* observer; + while ((observer = it.GetNext()) != NULL) + if (!observer->AllowPlugins(frame, enabled_per_settings)) + return false; + + return true; +} - return false; // Other protocols fall through here. +bool RenderView::allowScript(WebFrame* frame, bool enabled_per_settings) { + ObserverListBase<RenderViewObserver>::Iterator it(observers_); + RenderViewObserver* observer; + while ((observer = it.GetNext()) != NULL) + if (!observer->AllowScript(frame, enabled_per_settings)) + return false; + + return true; } bool RenderView::allowDatabase( @@ -2780,11 +2725,11 @@ bool RenderView::allowDatabase( return result; } void RenderView::didNotAllowScript(WebKit::WebFrame* frame) { - DidBlockContentType(CONTENT_SETTINGS_TYPE_JAVASCRIPT, std::string()); + FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidNotAllowScript(frame)); } void RenderView::didNotAllowPlugins(WebKit::WebFrame* frame) { - DidBlockContentType(CONTENT_SETTINGS_TYPE_PLUGINS, std::string()); + FOR_EACH_OBSERVER(RenderViewObserver, observers_, DidNotAllowPlugins(frame)); } void RenderView::didExhaustMemoryAvailableForScript(WebFrame* frame) { @@ -3260,26 +3205,6 @@ void RenderView::OnFindReplyAck() { } } -bool RenderView::AllowContentType(ContentSettingsType settings_type) { - // CONTENT_SETTING_ASK is only valid for cookies. - return current_content_settings_.settings[settings_type] != - CONTENT_SETTING_BLOCK; -} - -void RenderView::DidBlockContentType(ContentSettingsType settings_type, - const std::string& resource_identifier) { - if (!content_blocked_[settings_type]) { - content_blocked_[settings_type] = true; - Send(new ViewHostMsg_ContentBlocked(routing_id_, settings_type, - resource_identifier)); - } -} - -void RenderView::ClearBlockedContentSettings() { - for (size_t i = 0; i < arraysize(content_blocked_); ++i) - content_blocked_[i] = false; -} - WebPlugin* RenderView::CreatePepperPlugin( WebFrame* frame, const WebPluginParams& params, @@ -3340,12 +3265,6 @@ void RenderView::OnSetZoomLevel(double zoom_level) { zoomLevelChanged(); } -void RenderView::OnSetContentSettingsForLoadingURL( - const GURL& url, - const ContentSettings& content_settings) { - host_content_settings_[url] = content_settings; -} - void RenderView::OnSetZoomLevelForLoadingURL(const GURL& url, double zoom_level) { host_zoom_levels_[url] = zoom_level; diff --git a/content/renderer/render_view.h b/content/renderer/render_view.h index 8d846468..3292a37 100644 --- a/content/renderer/render_view.h +++ b/content/renderer/render_view.h @@ -21,7 +21,6 @@ #include "base/observer_list.h" #include "base/timer.h" #include "build/build_config.h" -#include "chrome/common/content_settings.h" #include "content/renderer/renderer_webcookiejar_impl.h" #include "content/common/edit_command.h" #include "content/common/navigation_gesture.h" @@ -251,10 +250,6 @@ class RenderView : public RenderWidget, bool ScheduleFileChooser(const ViewHostMsg_RunFileChooser_Params& params, WebKit::WebFileChooserCompletion* completion); - // Sets the content settings that back allowScripts(), allowImages(), and - // allowPlugins(). - void SetContentSettings(const ContentSettings& settings); - // Sets whether the renderer should report load progress to the browser. void SetReportLoadProgressEnabled(bool enabled); @@ -446,8 +441,6 @@ class RenderView : public RenderWidget, virtual WebKit::WebCookieJar* cookieJar(WebKit::WebFrame* frame); virtual void frameDetached(WebKit::WebFrame* frame); virtual void willClose(WebKit::WebFrame* frame); - virtual bool allowImages(WebKit::WebFrame* frame, bool enabled_per_settings); - virtual bool allowPlugins(WebKit::WebFrame* frame, bool enabled_per_settings); virtual void loadURLExternally(WebKit::WebFrame* frame, const WebKit::WebURLRequest& request, WebKit::WebNavigationPolicy policy); @@ -531,6 +524,8 @@ class RenderView : public RenderWidget, const WebKit::WebSecurityOrigin& origin, const WebKit::WebURL& target); + virtual bool allowImages(WebKit::WebFrame* frame, bool enabled_per_settings); + virtual bool allowPlugins(WebKit::WebFrame* frame, bool enabled_per_settings); virtual bool allowScript(WebKit::WebFrame* frame, bool enabled_per_settings); virtual bool allowDatabase(WebKit::WebFrame* frame, const WebKit::WebString& name, @@ -644,7 +639,6 @@ class RenderView : public RenderWidget, FRIEND_TEST_ALL_PREFIXES(RenderViewTest, MacTestCmdUp); #endif - typedef std::map<GURL, ContentSettings> HostContentSettings; typedef std::map<GURL, double> HostZoomLevels; // Identifies an accessibility notification from webkit. @@ -803,9 +797,6 @@ class RenderView : public RenderWidget, void OnSetActive(bool active); void OnSetAltErrorPageURL(const GURL& gurl); void OnSetBackground(const SkBitmap& background); - void OnSetContentSettingsForLoadingURL( - const GURL& url, - const ContentSettings& content_settings); void OnSetWebUIProperty(const std::string& name, const std::string& value); void OnSetEditCommandsForNextKeyEvent(const EditCommands& edit_commands); void OnSetInitialFocus(bool reverse); @@ -836,10 +827,6 @@ class RenderView : public RenderWidget, // Misc private functions ---------------------------------------------------- - // Helper method that returns if the user wants to block content of type - // |content_type|. - bool AllowContentType(ContentSettingsType settings_type); - void AltErrorPageFinished(WebKit::WebFrame* frame, const WebKit::WebURLError& original_error, const std::string& html); @@ -848,15 +835,20 @@ class RenderView : public RenderWidget, // by preferred_size_change_timer_. void CheckPreferredSize(); - // Resets the |content_blocked_| array. - void ClearBlockedContentSettings(); - - // Sends an IPC notification that the specified content type was blocked. - // If the content type requires it, |resource_identifier| names the specific - // resource that was blocked (the plugin path in the case of plugins), - // otherwise it's the empty string. - void DidBlockContentType(ContentSettingsType settings_type, - const std::string& resource_identifier); + // This callback is triggered when DownloadFavicon completes, either + // succesfully or with a failure. See DownloadFavicon for more + // details. + void DidDownloadFavicon(webkit_glue::ImageResourceFetcher* fetcher, + const SkBitmap& image); + + // Requests to download a favicon image. When done, the RenderView + // is notified by way of DidDownloadFavicon. Returns true if the + // request was successfully started, false otherwise. id is used to + // uniquely identify the request and passed back to the + // DidDownloadFavicon method. If the image has multiple frames, the + // frame whose size is image_size is returned. If the image doesn't + // have a frame at the specified size, the first is returned. + bool DownloadFavicon(int id, const GURL& image_url, int image_size); GURL GetAlternateErrorPageURL(const GURL& failed_url, ErrorPageType error_type); @@ -912,7 +904,6 @@ class RenderView : public RenderWidget, WebPreferences webkit_preferences_; RendererPreferences renderer_preferences_; - HostContentSettings host_content_settings_; HostZoomLevels host_zoom_levels_; // Whether content state (such as form state, scroll position and page @@ -920,9 +911,6 @@ class RenderView : public RenderWidget, // false, but set to true by some tests. bool send_content_state_immediately_; - // Stores if loading of images, scripts, and plugins is allowed. - ContentSettings current_content_settings_; - // Bitwise-ORed set of extra bindings that have been enabled. See // BindingsPolicy for details. int enabled_bindings_; @@ -967,9 +955,6 @@ class RenderView : public RenderWidget, // It is empty if there is no top-level client-side redirect. GURL completed_client_redirect_src_; - // Stores if images, scripts, and plugins have actually been blocked. - bool content_blocked_[CONTENT_SETTINGS_NUM_TYPES]; - // Holds state pertaining to a navigation that we initiated. This is held by // the WebDataSource::ExtraData attribute. We use pending_navigation_state_ // as a temporary holder for the state until the WebDataSource corresponding diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc index afce5c3..3f8eb92 100644 --- a/content/renderer/render_view_browsertest.cc +++ b/content/renderer/render_view_browsertest.cc @@ -771,56 +771,6 @@ TEST_F(RenderViewTest, DidFailProvisionalLoadWithErrorForCancellation) { EXPECT_TRUE(web_frame->isViewSourceModeEnabled()); } -// Regression test for http://crbug.com/35011 -TEST_F(RenderViewTest, JSBlockSentAfterPageLoad) { - // 1. Load page with JS. - std::string html = "<html>" - "<head>" - "<script>document.createElement('div');</script>" - "</head>" - "<body>" - "</body>" - "</html>"; - render_thread_.sink().ClearMessages(); - LoadHTML(html.c_str()); - - // 2. Block JavaScript. - ContentSettings settings; - for (int i = 0; i < CONTENT_SETTINGS_NUM_TYPES; ++i) - settings.settings[i] = CONTENT_SETTING_ALLOW; - settings.settings[CONTENT_SETTINGS_TYPE_JAVASCRIPT] = CONTENT_SETTING_BLOCK; - view_->SetContentSettings(settings); - - // Make sure no pending messages are in the queue. - ProcessPendingMessages(); - render_thread_.sink().ClearMessages(); - - // 3. Reload page. - ViewMsg_Navigate_Params params; - std::string url_str = "data:text/html;charset=utf-8,"; - url_str.append(html); - GURL url(url_str); - params.url = url; - params.navigation_type = ViewMsg_Navigate_Type::RELOAD; - view_->OnNavigate(params); - ProcessPendingMessages(); - - // 4. Verify that the notification that javascript was blocked is sent after - // the navigation notifiction is sent. - int navigation_index = -1; - int block_index = -1; - for (size_t i = 0; i < render_thread_.sink().message_count(); ++i) { - const IPC::Message* msg = render_thread_.sink().GetMessageAt(i); - if (msg->type() == ViewHostMsg_FrameNavigate::ID) - navigation_index = i; - if (msg->type() == ViewHostMsg_ContentBlocked::ID) - block_index = i; - } - EXPECT_NE(-1, navigation_index); - EXPECT_NE(-1, block_index); - EXPECT_LT(navigation_index, block_index); -} - // Regression test for http://crbug.com/41562 TEST_F(RenderViewTest, UpdateTargetURLWithInvalidURL) { const GURL invalid_gurl("http://"); diff --git a/content/renderer/render_view_observer.cc b/content/renderer/render_view_observer.cc index b13f4c2..e74c503 100644 --- a/content/renderer/render_view_observer.cc +++ b/content/renderer/render_view_observer.cc @@ -6,6 +6,8 @@ #include "content/renderer/render_view.h" +using WebKit::WebFrame; + RenderViewObserver::RenderViewObserver(RenderView* render_view) : render_view_(render_view), routing_id_(render_view ? render_view->routing_id() : 0) { @@ -34,3 +36,18 @@ bool RenderViewObserver::Send(IPC::Message* message) { delete message; return false; } + +bool RenderViewObserver::AllowImages(WebFrame* frame, + bool enabled_per_settings) { + return true; +} + +bool RenderViewObserver::AllowPlugins(WebFrame* frame, + bool enabled_per_settings) { + return true; +} + +bool RenderViewObserver::AllowScript(WebFrame* frame, + bool enabled_per_settings) { + return true; +} diff --git a/content/renderer/render_view_observer.h b/content/renderer/render_view_observer.h index cdb0b51..a5c0130 100644 --- a/content/renderer/render_view_observer.h +++ b/content/renderer/render_view_observer.h @@ -66,6 +66,12 @@ class RenderViewObserver : public IPC::Channel::Listener, const WebKit::WebString& property_name, unsigned long long event_id) {} virtual void FocusedNodeChanged(const WebKit::WebNode& node) {} + // If any observer returns false, then the request will be denied. + virtual bool AllowImages(WebKit::WebFrame* frame, bool enabled_per_settings); + virtual bool AllowPlugins(WebKit::WebFrame* frame, bool enabled_per_settings); + virtual bool AllowScript(WebKit::WebFrame* frame, bool enabled_per_settings); + virtual void DidNotAllowPlugins(WebKit::WebFrame* frame) {} + virtual void DidNotAllowScript(WebKit::WebFrame* frame) {} // These match the RenderView methods. virtual void DidHandleMouseEvent(const WebKit::WebMouseEvent& event) {} |