diff options
Diffstat (limited to 'chrome/renderer/content_settings_observer.cc')
-rw-r--r-- | chrome/renderer/content_settings_observer.cc | 184 |
1 files changed, 184 insertions, 0 deletions
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; +} |