diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-12 18:21:48 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-12 18:21:48 +0000 |
commit | b39eb5931f369c016344cb227b24d95193339099 (patch) | |
tree | b60d80410d1080cf38f69d3a53316c8f068620d4 | |
parent | 713c3e2a8c880a5f7331221c223640bf3672a4ef (diff) | |
download | chromium_src-b39eb5931f369c016344cb227b24d95193339099.zip chromium_src-b39eb5931f369c016344cb227b24d95193339099.tar.gz chromium_src-b39eb5931f369c016344cb227b24d95193339099.tar.bz2 |
Move WebPermissionContent implementation to ContentSettingsObserver instead of routing the callbacks from ChromeRenderViewObserver.
BUG=304341
R=jochen@chromium.org
Review URL: https://codereview.chromium.org/108873009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@240361 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/renderer/chrome_content_renderer_client.cc | 6 | ||||
-rw-r--r-- | chrome/renderer/chrome_render_view_observer.cc | 393 | ||||
-rw-r--r-- | chrome/renderer/chrome_render_view_observer.h | 77 | ||||
-rw-r--r-- | chrome/renderer/content_settings_observer.cc | 364 | ||||
-rw-r--r-- | chrome/renderer/content_settings_observer.h | 103 | ||||
-rw-r--r-- | chrome/renderer/content_settings_observer_browsertest.cc | 16 |
6 files changed, 434 insertions, 525 deletions
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index c41dcaf..5c02f3a 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc @@ -362,7 +362,7 @@ void ChromeContentRendererClient::RenderFrameCreated( void ChromeContentRendererClient::RenderViewCreated( content::RenderView* render_view) { ContentSettingsObserver* content_settings = - new ContentSettingsObserver(render_view); + new ContentSettingsObserver(render_view, extension_dispatcher_.get()); if (chrome_observer_.get()) { content_settings->SetContentSettingRules( chrome_observer_->content_setting_rules()); @@ -391,9 +391,7 @@ void ChromeContentRendererClient::RenderViewCreated( if (command_line->HasSwitch(switches::kInstantProcess)) new SearchBox(render_view); - new ChromeRenderViewObserver( - render_view, content_settings, chrome_observer_.get(), - extension_dispatcher_.get()); + new ChromeRenderViewObserver(render_view, chrome_observer_.get()); new NetErrorHelper(render_view); } diff --git a/chrome/renderer/chrome_render_view_observer.cc b/chrome/renderer/chrome_render_view_observer.cc index 9c604cf..e26a2c7 100644 --- a/chrome/renderer/chrome_render_view_observer.cc +++ b/chrome/renderer/chrome_render_view_observer.cc @@ -19,8 +19,6 @@ #include "chrome/common/render_messages.h" #include "chrome/common/url_constants.h" #include "chrome/renderer/chrome_render_process_observer.h" -#include "chrome/renderer/content_settings_observer.h" -#include "chrome/renderer/extensions/dispatcher.h" #include "chrome/renderer/external_host_bindings.h" #include "chrome/renderer/prerender/prerender_helper.h" #include "chrome/renderer/safe_browsing/phishing_classifier_delegate.h" @@ -57,7 +55,6 @@ #include "ui/gfx/skbitmap_operations.h" #include "v8/include/v8-testing.h" -using extensions::APIPermission; using blink::WebAXObject; using blink::WebCString; using blink::WebDataSource; @@ -98,74 +95,7 @@ static const int kDelayForForcedCaptureMs = 6000; static const size_t kMaxIndexChars = 65535; // Constants for UMA statistic collection. -static const char kWWWDotGoogleDotCom[] = "www.google.com"; -static const char kMailDotGoogleDotCom[] = "mail.google.com"; -static const char kPlusDotGoogleDotCom[] = "plus.google.com"; -static const char kDocsDotGoogleDotCom[] = "docs.google.com"; -static const char kSitesDotGoogleDotCom[] = "sites.google.com"; -static const char kPicasawebDotGoogleDotCom[] = "picasaweb.google.com"; -static const char kCodeDotGoogleDotCom[] = "code.google.com"; -static const char kGroupsDotGoogleDotCom[] = "groups.google.com"; -static const char kMapsDotGoogleDotCom[] = "maps.google.com"; -static const char kWWWDotYoutubeDotCom[] = "www.youtube.com"; -static const char kDotGoogleUserContentDotCom[] = ".googleusercontent.com"; -static const char kGoogleReaderPathPrefix[] = "/reader/"; -static const char kGoogleSupportPathPrefix[] = "/support/"; -static const char kGoogleIntlPathPrefix[] = "/intl/"; -static const char kDotJS[] = ".js"; -static const char kDotCSS[] = ".css"; -static const char kDotSWF[] = ".swf"; -static const char kDotHTML[] = ".html"; static const char kTranslateCaptureText[] = "Translate.CaptureText"; -enum { - INSECURE_CONTENT_DISPLAY = 0, - INSECURE_CONTENT_DISPLAY_HOST_GOOGLE, - INSECURE_CONTENT_DISPLAY_HOST_WWW_GOOGLE, - INSECURE_CONTENT_DISPLAY_HTML, - INSECURE_CONTENT_RUN, - INSECURE_CONTENT_RUN_HOST_GOOGLE, - INSECURE_CONTENT_RUN_HOST_WWW_GOOGLE, - INSECURE_CONTENT_RUN_TARGET_YOUTUBE, - INSECURE_CONTENT_RUN_JS, - INSECURE_CONTENT_RUN_CSS, - INSECURE_CONTENT_RUN_SWF, - INSECURE_CONTENT_DISPLAY_HOST_YOUTUBE, - INSECURE_CONTENT_RUN_HOST_YOUTUBE, - INSECURE_CONTENT_RUN_HOST_GOOGLEUSERCONTENT, - INSECURE_CONTENT_DISPLAY_HOST_MAIL_GOOGLE, - INSECURE_CONTENT_RUN_HOST_MAIL_GOOGLE, - INSECURE_CONTENT_DISPLAY_HOST_PLUS_GOOGLE, - INSECURE_CONTENT_RUN_HOST_PLUS_GOOGLE, - INSECURE_CONTENT_DISPLAY_HOST_DOCS_GOOGLE, - INSECURE_CONTENT_RUN_HOST_DOCS_GOOGLE, - INSECURE_CONTENT_DISPLAY_HOST_SITES_GOOGLE, - INSECURE_CONTENT_RUN_HOST_SITES_GOOGLE, - INSECURE_CONTENT_DISPLAY_HOST_PICASAWEB_GOOGLE, - INSECURE_CONTENT_RUN_HOST_PICASAWEB_GOOGLE, - INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_READER, - INSECURE_CONTENT_RUN_HOST_GOOGLE_READER, - INSECURE_CONTENT_DISPLAY_HOST_CODE_GOOGLE, - INSECURE_CONTENT_RUN_HOST_CODE_GOOGLE, - INSECURE_CONTENT_DISPLAY_HOST_GROUPS_GOOGLE, - INSECURE_CONTENT_RUN_HOST_GROUPS_GOOGLE, - INSECURE_CONTENT_DISPLAY_HOST_MAPS_GOOGLE, - INSECURE_CONTENT_RUN_HOST_MAPS_GOOGLE, - INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_SUPPORT, - INSECURE_CONTENT_RUN_HOST_GOOGLE_SUPPORT, - INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_INTL, - INSECURE_CONTENT_RUN_HOST_GOOGLE_INTL, - INSECURE_CONTENT_NUM_EVENTS -}; - -// Constants for mixed-content blocking. -static const char kGoogleDotCom[] = "google.com"; - -static bool isHostInDomain(const std::string& host, const std::string& domain) { - return (EndsWith(host, domain, false) && - (host.length() == domain.length() || - (host.length() > domain.length() && - host[host.length() - domain.length() - 1] == '.'))); -} namespace { @@ -271,21 +201,14 @@ extensions::StackTrace GetStackTraceFromMessage( ChromeRenderViewObserver::ChromeRenderViewObserver( content::RenderView* render_view, - ContentSettingsObserver* content_settings, - ChromeRenderProcessObserver* chrome_render_process_observer, - extensions::Dispatcher* extension_dispatcher) + ChromeRenderProcessObserver* chrome_render_process_observer) : content::RenderViewObserver(render_view), chrome_render_process_observer_(chrome_render_process_observer), - extension_dispatcher_(extension_dispatcher), - content_settings_(content_settings), translate_helper_(new TranslateHelper(render_view)), phishing_classifier_(NULL), last_indexed_page_id_(-1), - allow_displaying_insecure_content_(false), - allow_running_insecure_content_(false), capture_timer_(false, false) { const CommandLine& command_line = *CommandLine::ForCurrentProcess(); - render_view->GetWebView()->setPermissionClient(this); if (!command_line.HasSwitch(switches::kDisableClientSidePhishingDetection)) OnSetClientSidePhishingDetection(true); } @@ -301,10 +224,6 @@ bool ChromeRenderViewObserver::OnMessageReceived(const IPC::Message& message) { OnHandleMessageFromExternalHost) IPC_MESSAGE_HANDLER(ChromeViewMsg_JavaScriptStressTestControl, OnJavaScriptStressTestControl) - IPC_MESSAGE_HANDLER(ChromeViewMsg_SetAllowDisplayingInsecureContent, - OnSetAllowDisplayingInsecureContent) - IPC_MESSAGE_HANDLER(ChromeViewMsg_SetAllowRunningInsecureContent, - OnSetAllowRunningInsecureContent) IPC_MESSAGE_HANDLER(ChromeViewMsg_SetClientSidePhishingDetection, OnSetClientSidePhishingDetection) IPC_MESSAGE_HANDLER(ChromeViewMsg_SetVisuallyDeemphasized, @@ -312,7 +231,6 @@ bool ChromeRenderViewObserver::OnMessageReceived(const IPC::Message& message) { IPC_MESSAGE_HANDLER(ChromeViewMsg_RequestThumbnailForContextNode, OnRequestThumbnailForContextNode) IPC_MESSAGE_HANDLER(ChromeViewMsg_GetFPS, OnGetFPS) - IPC_MESSAGE_HANDLER(ChromeViewMsg_NPAPINotSupported, OnNPAPINotSupported) #if defined(OS_ANDROID) IPC_MESSAGE_HANDLER(ChromeViewMsg_UpdateTopControlsState, OnUpdateTopControlsState) @@ -357,26 +275,6 @@ void ChromeRenderViewObserver::OnJavaScriptStressTestControl(int cmd, } } -void ChromeRenderViewObserver::OnSetAllowDisplayingInsecureContent(bool allow) { - allow_displaying_insecure_content_ = allow; - WebFrame* main_frame = render_view()->GetWebView()->mainFrame(); - if (main_frame) - main_frame->reload(); -} - -void ChromeRenderViewObserver::OnSetAllowRunningInsecureContent(bool allow) { - allow_running_insecure_content_ = allow; - OnSetAllowDisplayingInsecureContent(allow); -} - -void ChromeRenderViewObserver::OnNPAPINotSupported() { -#if defined(USE_AURA) && defined(OS_WIN) - content_settings_->BlockNPAPIPlugins(); -#else - NOTREACHED(); -#endif -} - #if defined(OS_ANDROID) void ChromeRenderViewObserver::OnUpdateTopControlsState( content::TopControlsState constraints, @@ -505,283 +403,6 @@ void ChromeRenderViewObserver::OnGetFPS() { Send(new ChromeViewHostMsg_FPS(routing_id(), fps)); } -bool ChromeRenderViewObserver::allowDatabase( - WebFrame* frame, - const WebString& name, - const WebString& display_name, - unsigned long estimated_size) { - return content_settings_->AllowDatabase( - frame, name, display_name, estimated_size); -} - -bool ChromeRenderViewObserver::allowFileSystem(WebFrame* frame) { - return content_settings_->AllowFileSystem(frame); -} - -bool ChromeRenderViewObserver::allowImage(WebFrame* frame, - bool enabled_per_settings, - const WebURL& image_url) { - return content_settings_->AllowImage(frame, enabled_per_settings, image_url); -} - -bool ChromeRenderViewObserver::allowIndexedDB(WebFrame* frame, - const WebString& name, - const WebSecurityOrigin& origin) { - return content_settings_->AllowIndexedDB(frame, name, origin); -} - -bool ChromeRenderViewObserver::allowPlugins(WebFrame* frame, - bool enabled_per_settings) { - return content_settings_->AllowPlugins(frame, enabled_per_settings); -} - -bool ChromeRenderViewObserver::allowScript(WebFrame* frame, - bool enabled_per_settings) { - return content_settings_->AllowScript(frame, enabled_per_settings); -} - -bool ChromeRenderViewObserver::allowScriptFromSource( - WebFrame* frame, - bool enabled_per_settings, - const WebURL& script_url) { - return content_settings_->AllowScriptFromSource(frame, - enabled_per_settings, - script_url); -} - -bool ChromeRenderViewObserver::allowStorage(WebFrame* frame, bool local) { - return content_settings_->AllowStorage(frame, local); -} - -bool ChromeRenderViewObserver::allowReadFromClipboard(WebFrame* frame, - bool default_value) { - bool allowed = false; - // TODO(dcheng): Should we consider a toURL() method on WebSecurityOrigin? - Send(new ChromeViewHostMsg_CanTriggerClipboardRead( - routing_id(), GURL(frame->document().securityOrigin().toString().utf8()), - &allowed)); - return allowed; -} - -bool ChromeRenderViewObserver::allowWriteToClipboard(WebFrame* frame, - bool default_value) { - bool allowed = false; - Send(new ChromeViewHostMsg_CanTriggerClipboardWrite( - routing_id(), GURL(frame->document().securityOrigin().toString().utf8()), - &allowed)); - return allowed; -} - -#if defined(WEBPERMISSIONCLIENT_USES_FRAME_FOR_ALL_METHODS) -bool ChromeRenderViewObserver::allowWebComponents(WebFrame* frame, - bool defaultValue) { - if (defaultValue) - return true; - - WebSecurityOrigin origin = frame->document().securityOrigin(); - if (EqualsASCII(origin.protocol(), chrome::kChromeUIScheme)) - return true; - - if (const extensions::Extension* extension = GetExtension(origin)) { - if (extension->HasAPIPermission(APIPermission::kExperimental)) - return true; - } - - return false; -} - -bool ChromeRenderViewObserver::allowMutationEvents(WebFrame* frame, - bool default_value) { - WebSecurityOrigin origin = frame->document().securityOrigin(); - const extensions::Extension* extension = GetExtension(origin); - if (extension && extension->is_platform_app()) - return false; - return default_value; -} - -bool ChromeRenderViewObserver::allowPushState(WebFrame* frame) { - WebSecurityOrigin origin = frame->document().securityOrigin(); - const extensions::Extension* extension = GetExtension(origin); - return !extension || !extension->is_platform_app(); -} -#else -bool ChromeRenderViewObserver::allowWebComponents(const WebDocument& document, - bool defaultValue) { - if (defaultValue) - return true; - - WebSecurityOrigin origin = document.securityOrigin(); - if (EqualsASCII(origin.protocol(), chrome::kChromeUIScheme)) - return true; - - if (const extensions::Extension* extension = GetExtension(origin)) { - if (extension->HasAPIPermission(APIPermission::kExperimental)) - return true; - } - - return false; -} - -bool ChromeRenderViewObserver::allowMutationEvents(const WebDocument& document, - bool default_value) { - WebSecurityOrigin origin = document.securityOrigin(); - const extensions::Extension* extension = GetExtension(origin); - if (extension && extension->is_platform_app()) - return false; - return default_value; -} - -bool ChromeRenderViewObserver::allowPushState(const WebDocument& document) { - WebSecurityOrigin origin = document.securityOrigin(); - const extensions::Extension* extension = GetExtension(origin); - return !extension || !extension->is_platform_app(); -} -#endif - -static void SendInsecureContentSignal(int signal) { - UMA_HISTOGRAM_ENUMERATION("SSL.InsecureContent", signal, - INSECURE_CONTENT_NUM_EVENTS); -} - -bool ChromeRenderViewObserver::allowDisplayingInsecureContent( - blink::WebFrame* frame, - bool allowed_per_settings, - const blink::WebSecurityOrigin& origin, - const blink::WebURL& resource_url) { - SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY); - - std::string origin_host(origin.host().utf8()); - GURL frame_gurl(frame->document().url()); - if (isHostInDomain(origin_host, kGoogleDotCom)) { - SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE); - if (StartsWithASCII(frame_gurl.path(), kGoogleSupportPathPrefix, false)) { - SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_SUPPORT); - } else if (StartsWithASCII(frame_gurl.path(), - kGoogleIntlPathPrefix, - false)) { - SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_INTL); - } - } - - if (origin_host == kWWWDotGoogleDotCom) { - SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_WWW_GOOGLE); - if (StartsWithASCII(frame_gurl.path(), kGoogleReaderPathPrefix, false)) - SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_READER); - } else if (origin_host == kMailDotGoogleDotCom) { - SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_MAIL_GOOGLE); - } else if (origin_host == kPlusDotGoogleDotCom) { - SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_PLUS_GOOGLE); - } else if (origin_host == kDocsDotGoogleDotCom) { - SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_DOCS_GOOGLE); - } else if (origin_host == kSitesDotGoogleDotCom) { - SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_SITES_GOOGLE); - } else if (origin_host == kPicasawebDotGoogleDotCom) { - SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_PICASAWEB_GOOGLE); - } else if (origin_host == kCodeDotGoogleDotCom) { - SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_CODE_GOOGLE); - } else if (origin_host == kGroupsDotGoogleDotCom) { - SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GROUPS_GOOGLE); - } else if (origin_host == kMapsDotGoogleDotCom) { - SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_MAPS_GOOGLE); - } else if (origin_host == kWWWDotYoutubeDotCom) { - SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_YOUTUBE); - } - - GURL resource_gurl(resource_url); - if (EndsWith(resource_gurl.path(), kDotHTML, false)) - SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HTML); - - if (allowed_per_settings || allow_displaying_insecure_content_) - return true; - - Send(new ChromeViewHostMsg_DidBlockDisplayingInsecureContent(routing_id())); - - return false; -} - -bool ChromeRenderViewObserver::allowRunningInsecureContent( - blink::WebFrame* frame, - bool allowed_per_settings, - const blink::WebSecurityOrigin& origin, - const blink::WebURL& resource_url) { - std::string origin_host(origin.host().utf8()); - GURL frame_gurl(frame->document().url()); - DCHECK_EQ(frame_gurl.host(), origin_host); - - bool is_google = isHostInDomain(origin_host, kGoogleDotCom); - if (is_google) { - SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE); - if (StartsWithASCII(frame_gurl.path(), kGoogleSupportPathPrefix, false)) { - SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE_SUPPORT); - } else if (StartsWithASCII(frame_gurl.path(), - kGoogleIntlPathPrefix, - false)) { - SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE_INTL); - } - } - - if (origin_host == kWWWDotGoogleDotCom) { - SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_WWW_GOOGLE); - if (StartsWithASCII(frame_gurl.path(), kGoogleReaderPathPrefix, false)) - SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE_READER); - } else if (origin_host == kMailDotGoogleDotCom) { - SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_MAIL_GOOGLE); - } else if (origin_host == kPlusDotGoogleDotCom) { - SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_PLUS_GOOGLE); - } else if (origin_host == kDocsDotGoogleDotCom) { - SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_DOCS_GOOGLE); - } else if (origin_host == kSitesDotGoogleDotCom) { - SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_SITES_GOOGLE); - } else if (origin_host == kPicasawebDotGoogleDotCom) { - SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_PICASAWEB_GOOGLE); - } else if (origin_host == kCodeDotGoogleDotCom) { - SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_CODE_GOOGLE); - } else if (origin_host == kGroupsDotGoogleDotCom) { - SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GROUPS_GOOGLE); - } else if (origin_host == kMapsDotGoogleDotCom) { - SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_MAPS_GOOGLE); - } else if (origin_host == kWWWDotYoutubeDotCom) { - SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_YOUTUBE); - } else if (EndsWith(origin_host, kDotGoogleUserContentDotCom, false)) { - SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLEUSERCONTENT); - } - - GURL resource_gurl(resource_url); - if (resource_gurl.host() == kWWWDotYoutubeDotCom) - SendInsecureContentSignal(INSECURE_CONTENT_RUN_TARGET_YOUTUBE); - - if (EndsWith(resource_gurl.path(), kDotJS, false)) - SendInsecureContentSignal(INSECURE_CONTENT_RUN_JS); - else if (EndsWith(resource_gurl.path(), kDotCSS, false)) - SendInsecureContentSignal(INSECURE_CONTENT_RUN_CSS); - else if (EndsWith(resource_gurl.path(), kDotSWF, false)) - SendInsecureContentSignal(INSECURE_CONTENT_RUN_SWF); - - if (!allow_running_insecure_content_ && !allowed_per_settings) { - content_settings_->DidNotAllowMixedScript(); - return false; - } - - return true; -} - -bool ChromeRenderViewObserver::allowWebGLDebugRendererInfo(WebFrame* frame) { - bool allowed = false; - Send(new ChromeViewHostMsg_IsWebGLDebugRendererInfoAllowed( - routing_id(), - GURL(frame->top()->document().securityOrigin().toString().utf8()), - &allowed)); - return allowed; -} - -void ChromeRenderViewObserver::didNotAllowPlugins(WebFrame* frame) { - content_settings_->DidNotAllowPlugins(); -} - -void ChromeRenderViewObserver::didNotAllowScript(WebFrame* frame) { - content_settings_->DidNotAllowScript(); -} - void ChromeRenderViewObserver::DidStartLoading() { if ((render_view()->GetEnabledBindings() & content::BINDINGS_POLICY_WEB_UI) && webui_javascript_.get()) { @@ -985,18 +606,6 @@ ExternalHostBindings* ChromeRenderViewObserver::GetExternalHostBindings() { return external_host_bindings_.get(); } -const extensions::Extension* ChromeRenderViewObserver::GetExtension( - const WebSecurityOrigin& origin) const { - if (!EqualsASCII(origin.protocol(), extensions::kExtensionScheme)) - return NULL; - - const std::string extension_id = origin.host().utf8().data(); - if (!extension_dispatcher_->IsExtensionActive(extension_id)) - return NULL; - - return extension_dispatcher_->extensions()->GetByID(extension_id); -} - bool ChromeRenderViewObserver::HasRefreshMetaTag(WebFrame* frame) { if (!frame) return false; diff --git a/chrome/renderer/chrome_render_view_observer.h b/chrome/renderer/chrome_render_view_observer.h index f615a37..03e820b 100644 --- a/chrome/renderer/chrome_render_view_observer.h +++ b/chrome/renderer/chrome_render_view_observer.h @@ -15,8 +15,6 @@ #include "base/timer/timer.h" #include "content/public/common/top_controls_state.h" #include "content/public/renderer/render_view_observer.h" -#include "extensions/common/permissions/api_permission.h" -#include "third_party/WebKit/public/web/WebPermissionClient.h" #include "ui/gfx/size.h" #include "url/gurl.h" @@ -28,11 +26,6 @@ class TranslateHelper; class WebViewColorOverlay; class WebViewAnimatingOverlay; -namespace extensions { -class Dispatcher; -class Extension; -} - namespace blink { class WebView; struct WebWindowFeatures; @@ -44,15 +37,12 @@ class PhishingClassifierDelegate; // This class holds the Chrome specific parts of RenderView, and has the same // lifetime. -class ChromeRenderViewObserver : public content::RenderViewObserver, - public blink::WebPermissionClient { +class ChromeRenderViewObserver : public content::RenderViewObserver { public: // translate_helper can be NULL. ChromeRenderViewObserver( content::RenderView* render_view, - ContentSettingsObserver* content_settings, - ChromeRenderProcessObserver* chrome_render_process_observer, - extensions::Dispatcher* extension_dispatcher); + ChromeRenderProcessObserver* chrome_render_process_observer); virtual ~ChromeRenderViewObserver(); private: @@ -77,55 +67,6 @@ class ChromeRenderViewObserver : public content::RenderViewObserver, const base::string16& stack_trace, int32 line_number, int32 severity_level) OVERRIDE; - - // blink::WebPermissionClient implementation. - virtual bool allowDatabase(blink::WebFrame* frame, - const blink::WebString& name, - const blink::WebString& display_name, - unsigned long estimated_size); - virtual bool allowFileSystem(blink::WebFrame* frame); - virtual bool allowImage(blink::WebFrame* frame, - bool enabled_per_settings, - const blink::WebURL& image_url); - virtual bool allowIndexedDB(blink::WebFrame* frame, - const blink::WebString& name, - const blink::WebSecurityOrigin& origin); - virtual bool allowPlugins(blink::WebFrame* frame, - bool enabled_per_settings); - virtual bool allowScript(blink::WebFrame* frame, - bool enabled_per_settings); - virtual bool allowScriptFromSource(blink::WebFrame* frame, - bool enabled_per_settings, - const blink::WebURL& script_url); - virtual bool allowStorage(blink::WebFrame* frame, bool local); - virtual bool allowReadFromClipboard(blink::WebFrame* frame, - bool default_value); - virtual bool allowWriteToClipboard(blink::WebFrame* frame, - bool default_value); -#if defined(WEBPERMISSIONCLIENT_USES_FRAME_FOR_ALL_METHODS) - virtual bool allowWebComponents(blink::WebFrame* frame, bool); - virtual bool allowMutationEvents(blink::WebFrame* frame, - bool default_value); - virtual bool allowPushState(blink::WebFrame* frame); -#else - virtual bool allowWebComponents(const blink::WebDocument&, bool); - virtual bool allowMutationEvents(const blink::WebDocument&, - bool default_value); - virtual bool allowPushState(const blink::WebDocument&); -#endif - virtual bool allowWebGLDebugRendererInfo(blink::WebFrame* frame); - virtual void didNotAllowPlugins(blink::WebFrame* frame); - virtual void didNotAllowScript(blink::WebFrame* frame); - virtual bool allowDisplayingInsecureContent( - blink::WebFrame* frame, - bool allowed_per_settings, - const blink::WebSecurityOrigin& context, - const blink::WebURL& url); - virtual bool allowRunningInsecureContent( - blink::WebFrame* frame, - bool allowed_per_settings, - const blink::WebSecurityOrigin& context, - const blink::WebURL& url); virtual void Navigate(const GURL& url) OVERRIDE; void OnWebUIJavaScript(const base::string16& frame_xpath, @@ -136,14 +77,11 @@ class ChromeRenderViewObserver : public content::RenderViewObserver, const std::string& origin, const std::string& target); void OnJavaScriptStressTestControl(int cmd, int param); - void OnSetAllowDisplayingInsecureContent(bool allow); - void OnSetAllowRunningInsecureContent(bool allow); void OnSetClientSidePhishingDetection(bool enable_phishing_detection); void OnSetVisuallyDeemphasized(bool deemphasized); void OnRequestThumbnailForContextNode(int thumbnail_min_area_pixels, gfx::Size thumbnail_max_size_pixels); void OnGetFPS(); - void OnNPAPINotSupported(); #if defined(OS_ANDROID) void OnUpdateTopControlsState(content::TopControlsState constraints, content::TopControlsState current, @@ -169,11 +107,6 @@ class ChromeRenderViewObserver : public content::RenderViewObserver, // Determines if a host is in the strict security host set. bool IsStrictSecurityHost(const std::string& host); - // If |origin| corresponds to an installed extension, returns that extension. - // Otherwise returns NULL. - const extensions::Extension* GetExtension( - const blink::WebSecurityOrigin& origin) const; - // Checks if a page contains <meta http-equiv="refresh" ...> tag. bool HasRefreshMetaTag(blink::WebFrame* frame); @@ -182,10 +115,8 @@ class ChromeRenderViewObserver : public content::RenderViewObserver, // Owned by ChromeContentRendererClient and outlive us. ChromeRenderProcessObserver* chrome_render_process_observer_; - extensions::Dispatcher* extension_dispatcher_; // Have the same lifetime as us. - ContentSettingsObserver* content_settings_; TranslateHelper* translate_helper_; safe_browsing::PhishingClassifierDelegate* phishing_classifier_; @@ -197,10 +128,6 @@ class ChromeRenderViewObserver : public content::RenderViewObserver, // replacement. GURL last_indexed_url_; - // Insecure content may be permitted for the duration of this render view. - bool allow_displaying_insecure_content_; - bool allow_running_insecure_content_; - // External host exposed through automation controller. scoped_ptr<ExternalHostBindings> external_host_bindings_; diff --git a/chrome/renderer/content_settings_observer.cc b/chrome/renderer/content_settings_observer.cc index 0127b9b..c396153 100644 --- a/chrome/renderer/content_settings_observer.cc +++ b/chrome/renderer/content_settings_observer.cc @@ -5,9 +5,11 @@ #include "chrome/renderer/content_settings_observer.h" #include "base/command_line.h" +#include "base/metrics/histogram.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/render_messages.h" #include "chrome/common/url_constants.h" +#include "chrome/renderer/extensions/dispatcher.h" #include "content/public/renderer/document_state.h" #include "content/public/renderer/navigation_state.h" #include "content/public/renderer/render_view.h" @@ -22,6 +24,7 @@ #include "webkit/child/weburlresponse_extradata_impl.h" using blink::WebDataSource; +using blink::WebDocument; using blink::WebFrame; using blink::WebFrameClient; using blink::WebSecurityOrigin; @@ -30,9 +33,80 @@ using blink::WebURL; using blink::WebView; using content::DocumentState; using content::NavigationState; +using extensions::APIPermission; namespace { +enum { + INSECURE_CONTENT_DISPLAY = 0, + INSECURE_CONTENT_DISPLAY_HOST_GOOGLE, + INSECURE_CONTENT_DISPLAY_HOST_WWW_GOOGLE, + INSECURE_CONTENT_DISPLAY_HTML, + INSECURE_CONTENT_RUN, + INSECURE_CONTENT_RUN_HOST_GOOGLE, + INSECURE_CONTENT_RUN_HOST_WWW_GOOGLE, + INSECURE_CONTENT_RUN_TARGET_YOUTUBE, + INSECURE_CONTENT_RUN_JS, + INSECURE_CONTENT_RUN_CSS, + INSECURE_CONTENT_RUN_SWF, + INSECURE_CONTENT_DISPLAY_HOST_YOUTUBE, + INSECURE_CONTENT_RUN_HOST_YOUTUBE, + INSECURE_CONTENT_RUN_HOST_GOOGLEUSERCONTENT, + INSECURE_CONTENT_DISPLAY_HOST_MAIL_GOOGLE, + INSECURE_CONTENT_RUN_HOST_MAIL_GOOGLE, + INSECURE_CONTENT_DISPLAY_HOST_PLUS_GOOGLE, + INSECURE_CONTENT_RUN_HOST_PLUS_GOOGLE, + INSECURE_CONTENT_DISPLAY_HOST_DOCS_GOOGLE, + INSECURE_CONTENT_RUN_HOST_DOCS_GOOGLE, + INSECURE_CONTENT_DISPLAY_HOST_SITES_GOOGLE, + INSECURE_CONTENT_RUN_HOST_SITES_GOOGLE, + INSECURE_CONTENT_DISPLAY_HOST_PICASAWEB_GOOGLE, + INSECURE_CONTENT_RUN_HOST_PICASAWEB_GOOGLE, + INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_READER, + INSECURE_CONTENT_RUN_HOST_GOOGLE_READER, + INSECURE_CONTENT_DISPLAY_HOST_CODE_GOOGLE, + INSECURE_CONTENT_RUN_HOST_CODE_GOOGLE, + INSECURE_CONTENT_DISPLAY_HOST_GROUPS_GOOGLE, + INSECURE_CONTENT_RUN_HOST_GROUPS_GOOGLE, + INSECURE_CONTENT_DISPLAY_HOST_MAPS_GOOGLE, + INSECURE_CONTENT_RUN_HOST_MAPS_GOOGLE, + INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_SUPPORT, + INSECURE_CONTENT_RUN_HOST_GOOGLE_SUPPORT, + INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_INTL, + INSECURE_CONTENT_RUN_HOST_GOOGLE_INTL, + INSECURE_CONTENT_NUM_EVENTS +}; + +// Constants for UMA statistic collection. +static const char kWWWDotGoogleDotCom[] = "www.google.com"; +static const char kMailDotGoogleDotCom[] = "mail.google.com"; +static const char kPlusDotGoogleDotCom[] = "plus.google.com"; +static const char kDocsDotGoogleDotCom[] = "docs.google.com"; +static const char kSitesDotGoogleDotCom[] = "sites.google.com"; +static const char kPicasawebDotGoogleDotCom[] = "picasaweb.google.com"; +static const char kCodeDotGoogleDotCom[] = "code.google.com"; +static const char kGroupsDotGoogleDotCom[] = "groups.google.com"; +static const char kMapsDotGoogleDotCom[] = "maps.google.com"; +static const char kWWWDotYoutubeDotCom[] = "www.youtube.com"; +static const char kDotGoogleUserContentDotCom[] = ".googleusercontent.com"; +static const char kGoogleReaderPathPrefix[] = "/reader/"; +static const char kGoogleSupportPathPrefix[] = "/support/"; +static const char kGoogleIntlPathPrefix[] = "/intl/"; +static const char kDotJS[] = ".js"; +static const char kDotCSS[] = ".css"; +static const char kDotSWF[] = ".swf"; +static const char kDotHTML[] = ".html"; + +// Constants for mixed-content blocking. +static const char kGoogleDotCom[] = "google.com"; + +static bool IsHostInDomain(const std::string& host, const std::string& domain) { + return (EndsWith(host, domain, false) && + (host.length() == domain.length() || + (host.length() > domain.length() && + host[host.length() - domain.length() - 1] == '.'))); +} + 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 @@ -68,13 +142,18 @@ ContentSetting GetContentSettingFromRules( } // namespace ContentSettingsObserver::ContentSettingsObserver( - content::RenderView* render_view) + content::RenderView* render_view, + extensions::Dispatcher* extension_dispatcher) : content::RenderViewObserver(render_view), content::RenderViewObserverTracker<ContentSettingsObserver>(render_view), + extension_dispatcher_(extension_dispatcher), + allow_displaying_insecure_content_(false), + allow_running_insecure_content_(false), content_setting_rules_(NULL), is_interstitial_page_(false), npapi_plugins_blocked_(false) { ClearBlockedContentSettings(); + render_view->GetWebView()->setPermissionClient(this); } ContentSettingsObserver::~ContentSettingsObserver() { @@ -107,6 +186,11 @@ bool ContentSettingsObserver::OnMessageReceived(const IPC::Message& message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(ContentSettingsObserver, message) IPC_MESSAGE_HANDLER(ChromeViewMsg_SetAsInterstitial, OnSetAsInterstitial) + IPC_MESSAGE_HANDLER(ChromeViewMsg_NPAPINotSupported, OnNPAPINotSupported) + IPC_MESSAGE_HANDLER(ChromeViewMsg_SetAllowDisplayingInsecureContent, + OnSetAllowDisplayingInsecureContent) + IPC_MESSAGE_HANDLER(ChromeViewMsg_SetAllowRunningInsecureContent, + OnSetAllowRunningInsecureContent) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() if (handled) @@ -131,8 +215,8 @@ void ContentSettingsObserver::DidCommitProvisionalLoad( NavigationState* navigation_state = document_state->navigation_state(); if (!navigation_state->was_within_same_page()) { // Clear "block" flags for the new page. This needs to happen before any of - // |AllowScript()|, |AllowScriptFromSource()|, |AllowImage()|, or - // |AllowPlugins()| is called for the new page so that these functions can + // |allowScript()|, |allowScriptFromSource()|, |allowImage()|, or + // |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(); @@ -146,7 +230,7 @@ void ContentSettingsObserver::DidCommitProvisionalLoad( !url.SchemeIs(chrome::kDataScheme)); } -bool ContentSettingsObserver::AllowDatabase(WebFrame* frame, +bool ContentSettingsObserver::allowDatabase(WebFrame* frame, const WebString& name, const WebString& display_name, unsigned long estimated_size) { @@ -162,7 +246,7 @@ bool ContentSettingsObserver::AllowDatabase(WebFrame* frame, return result; } -bool ContentSettingsObserver::AllowFileSystem(WebFrame* frame) { +bool ContentSettingsObserver::allowFileSystem(WebFrame* frame) { if (frame->document().securityOrigin().isUnique() || frame->top()->document().securityOrigin().isUnique()) return false; @@ -174,7 +258,7 @@ bool ContentSettingsObserver::AllowFileSystem(WebFrame* frame) { return result; } -bool ContentSettingsObserver::AllowImage(WebFrame* frame, +bool ContentSettingsObserver::allowImage(WebFrame* frame, bool enabled_per_settings, const WebURL& image_url) { bool allow = enabled_per_settings; @@ -196,7 +280,7 @@ bool ContentSettingsObserver::AllowImage(WebFrame* frame, return allow; } -bool ContentSettingsObserver::AllowIndexedDB(WebFrame* frame, +bool ContentSettingsObserver::allowIndexedDB(WebFrame* frame, const WebString& name, const WebSecurityOrigin& origin) { if (frame->document().securityOrigin().isUnique() || @@ -211,12 +295,12 @@ bool ContentSettingsObserver::AllowIndexedDB(WebFrame* frame, return result; } -bool ContentSettingsObserver::AllowPlugins(WebFrame* frame, +bool ContentSettingsObserver::allowPlugins(WebFrame* frame, bool enabled_per_settings) { return enabled_per_settings; } -bool ContentSettingsObserver::AllowScript(WebFrame* frame, +bool ContentSettingsObserver::allowScript(WebFrame* frame, bool enabled_per_settings) { if (!enabled_per_settings) return false; @@ -245,7 +329,7 @@ bool ContentSettingsObserver::AllowScript(WebFrame* frame, return allow; } -bool ContentSettingsObserver::AllowScriptFromSource( +bool ContentSettingsObserver::allowScriptFromSource( WebFrame* frame, bool enabled_per_settings, const blink::WebURL& script_url) { @@ -265,7 +349,7 @@ bool ContentSettingsObserver::AllowScriptFromSource( return allow || IsWhitelistedForContentSettings(frame); } -bool ContentSettingsObserver::AllowStorage(WebFrame* frame, bool local) { +bool ContentSettingsObserver::allowStorage(WebFrame* frame, bool local) { if (frame->document().securityOrigin().isUnique() || frame->top()->document().securityOrigin().isUnique()) return false; @@ -286,20 +370,233 @@ bool ContentSettingsObserver::AllowStorage(WebFrame* frame, bool local) { return result; } -void ContentSettingsObserver::DidNotAllowPlugins() { - DidBlockContentType(CONTENT_SETTINGS_TYPE_PLUGINS); +bool ContentSettingsObserver::allowReadFromClipboard(WebFrame* frame, + bool default_value) { + bool allowed = false; + // TODO(dcheng): Should we consider a toURL() method on WebSecurityOrigin? + Send(new ChromeViewHostMsg_CanTriggerClipboardRead( + routing_id(), GURL(frame->document().securityOrigin().toString().utf8()), + &allowed)); + return allowed; } -void ContentSettingsObserver::DidNotAllowScript() { - DidBlockContentType(CONTENT_SETTINGS_TYPE_JAVASCRIPT); +bool ContentSettingsObserver::allowWriteToClipboard(WebFrame* frame, + bool default_value) { + bool allowed = false; + Send(new ChromeViewHostMsg_CanTriggerClipboardWrite( + routing_id(), GURL(frame->document().securityOrigin().toString().utf8()), + &allowed)); + return allowed; +} + +#if defined(WEBPERMISSIONCLIENT_USES_FRAME_FOR_ALL_METHODS) +bool ContentSettingsObserver::allowWebComponents(WebFrame* frame, + bool defaultValue) { + if (defaultValue) + return true; + + WebSecurityOrigin origin = frame->document().securityOrigin(); + if (EqualsASCII(origin.protocol(), chrome::kChromeUIScheme)) + return true; + + if (const extensions::Extension* extension = GetExtension(origin)) { + if (extension->HasAPIPermission(APIPermission::kExperimental)) + return true; + } + + return false; } -void ContentSettingsObserver::DidNotAllowMixedScript() { - DidBlockContentType(CONTENT_SETTINGS_TYPE_MIXEDSCRIPT); +bool ContentSettingsObserver::allowMutationEvents(WebFrame* frame, + bool default_value) { + WebSecurityOrigin origin = frame->document().securityOrigin(); + const extensions::Extension* extension = GetExtension(origin); + if (extension && extension->is_platform_app()) + return false; + return default_value; } -void ContentSettingsObserver::BlockNPAPIPlugins() { - npapi_plugins_blocked_ = true; +bool ContentSettingsObserver::allowPushState(WebFrame* frame) { + WebSecurityOrigin origin = frame->document().securityOrigin(); + const extensions::Extension* extension = GetExtension(origin); + return !extension || !extension->is_platform_app(); +} +#else +bool ContentSettingsObserver::allowWebComponents(const WebDocument& document, + bool defaultValue) { + if (defaultValue) + return true; + + WebSecurityOrigin origin = document.securityOrigin(); + if (EqualsASCII(origin.protocol(), chrome::kChromeUIScheme)) + return true; + + if (const extensions::Extension* extension = GetExtension(origin)) { + if (extension->HasAPIPermission(APIPermission::kExperimental)) + return true; + } + + return false; +} + +bool ContentSettingsObserver::allowMutationEvents(const WebDocument& document, + bool default_value) { + WebSecurityOrigin origin = document.securityOrigin(); + const extensions::Extension* extension = GetExtension(origin); + if (extension && extension->is_platform_app()) + return false; + return default_value; +} + +bool ContentSettingsObserver::allowPushState(const WebDocument& document) { + WebSecurityOrigin origin = document.securityOrigin(); + const extensions::Extension* extension = GetExtension(origin); + return !extension || !extension->is_platform_app(); +} +#endif + +static void SendInsecureContentSignal(int signal) { + UMA_HISTOGRAM_ENUMERATION("SSL.InsecureContent", signal, + INSECURE_CONTENT_NUM_EVENTS); +} + +bool ContentSettingsObserver::allowDisplayingInsecureContent( + blink::WebFrame* frame, + bool allowed_per_settings, + const blink::WebSecurityOrigin& origin, + const blink::WebURL& resource_url) { + SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY); + + std::string origin_host(origin.host().utf8()); + GURL frame_gurl(frame->document().url()); + if (IsHostInDomain(origin_host, kGoogleDotCom)) { + SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE); + if (StartsWithASCII(frame_gurl.path(), kGoogleSupportPathPrefix, false)) { + SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_SUPPORT); + } else if (StartsWithASCII(frame_gurl.path(), + kGoogleIntlPathPrefix, + false)) { + SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_INTL); + } + } + + if (origin_host == kWWWDotGoogleDotCom) { + SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_WWW_GOOGLE); + if (StartsWithASCII(frame_gurl.path(), kGoogleReaderPathPrefix, false)) + SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GOOGLE_READER); + } else if (origin_host == kMailDotGoogleDotCom) { + SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_MAIL_GOOGLE); + } else if (origin_host == kPlusDotGoogleDotCom) { + SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_PLUS_GOOGLE); + } else if (origin_host == kDocsDotGoogleDotCom) { + SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_DOCS_GOOGLE); + } else if (origin_host == kSitesDotGoogleDotCom) { + SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_SITES_GOOGLE); + } else if (origin_host == kPicasawebDotGoogleDotCom) { + SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_PICASAWEB_GOOGLE); + } else if (origin_host == kCodeDotGoogleDotCom) { + SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_CODE_GOOGLE); + } else if (origin_host == kGroupsDotGoogleDotCom) { + SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_GROUPS_GOOGLE); + } else if (origin_host == kMapsDotGoogleDotCom) { + SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_MAPS_GOOGLE); + } else if (origin_host == kWWWDotYoutubeDotCom) { + SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HOST_YOUTUBE); + } + + GURL resource_gurl(resource_url); + if (EndsWith(resource_gurl.path(), kDotHTML, false)) + SendInsecureContentSignal(INSECURE_CONTENT_DISPLAY_HTML); + + if (allowed_per_settings || allow_displaying_insecure_content_) + return true; + + Send(new ChromeViewHostMsg_DidBlockDisplayingInsecureContent(routing_id())); + + return false; +} + +bool ContentSettingsObserver::allowRunningInsecureContent( + blink::WebFrame* frame, + bool allowed_per_settings, + const blink::WebSecurityOrigin& origin, + const blink::WebURL& resource_url) { + std::string origin_host(origin.host().utf8()); + GURL frame_gurl(frame->document().url()); + DCHECK_EQ(frame_gurl.host(), origin_host); + + bool is_google = IsHostInDomain(origin_host, kGoogleDotCom); + if (is_google) { + SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE); + if (StartsWithASCII(frame_gurl.path(), kGoogleSupportPathPrefix, false)) { + SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE_SUPPORT); + } else if (StartsWithASCII(frame_gurl.path(), + kGoogleIntlPathPrefix, + false)) { + SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE_INTL); + } + } + + if (origin_host == kWWWDotGoogleDotCom) { + SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_WWW_GOOGLE); + if (StartsWithASCII(frame_gurl.path(), kGoogleReaderPathPrefix, false)) + SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLE_READER); + } else if (origin_host == kMailDotGoogleDotCom) { + SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_MAIL_GOOGLE); + } else if (origin_host == kPlusDotGoogleDotCom) { + SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_PLUS_GOOGLE); + } else if (origin_host == kDocsDotGoogleDotCom) { + SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_DOCS_GOOGLE); + } else if (origin_host == kSitesDotGoogleDotCom) { + SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_SITES_GOOGLE); + } else if (origin_host == kPicasawebDotGoogleDotCom) { + SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_PICASAWEB_GOOGLE); + } else if (origin_host == kCodeDotGoogleDotCom) { + SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_CODE_GOOGLE); + } else if (origin_host == kGroupsDotGoogleDotCom) { + SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GROUPS_GOOGLE); + } else if (origin_host == kMapsDotGoogleDotCom) { + SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_MAPS_GOOGLE); + } else if (origin_host == kWWWDotYoutubeDotCom) { + SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_YOUTUBE); + } else if (EndsWith(origin_host, kDotGoogleUserContentDotCom, false)) { + SendInsecureContentSignal(INSECURE_CONTENT_RUN_HOST_GOOGLEUSERCONTENT); + } + + GURL resource_gurl(resource_url); + if (resource_gurl.host() == kWWWDotYoutubeDotCom) + SendInsecureContentSignal(INSECURE_CONTENT_RUN_TARGET_YOUTUBE); + + if (EndsWith(resource_gurl.path(), kDotJS, false)) + SendInsecureContentSignal(INSECURE_CONTENT_RUN_JS); + else if (EndsWith(resource_gurl.path(), kDotCSS, false)) + SendInsecureContentSignal(INSECURE_CONTENT_RUN_CSS); + else if (EndsWith(resource_gurl.path(), kDotSWF, false)) + SendInsecureContentSignal(INSECURE_CONTENT_RUN_SWF); + + if (!allow_running_insecure_content_ && !allowed_per_settings) { + DidBlockContentType(CONTENT_SETTINGS_TYPE_MIXEDSCRIPT); + return false; + } + + return true; +} + +bool ContentSettingsObserver::allowWebGLDebugRendererInfo(WebFrame* frame) { + bool allowed = false; + Send(new ChromeViewHostMsg_IsWebGLDebugRendererInfoAllowed( + routing_id(), + GURL(frame->top()->document().securityOrigin().toString().utf8()), + &allowed)); + return allowed; +} + +void ContentSettingsObserver::didNotAllowPlugins(WebFrame* frame) { + DidBlockContentType(CONTENT_SETTINGS_TYPE_PLUGINS); +} + +void ContentSettingsObserver::didNotAllowScript(WebFrame* frame) { + DidBlockContentType(CONTENT_SETTINGS_TYPE_JAVASCRIPT); } bool ContentSettingsObserver::AreNPAPIPluginsBlocked() const { @@ -315,6 +612,23 @@ void ContentSettingsObserver::OnSetAsInterstitial() { is_interstitial_page_ = true; } +void ContentSettingsObserver::OnNPAPINotSupported() { + npapi_plugins_blocked_ = true; +} + +void ContentSettingsObserver::OnSetAllowDisplayingInsecureContent(bool allow) { + allow_displaying_insecure_content_ = allow; + WebFrame* main_frame = render_view()->GetWebView()->mainFrame(); + if (main_frame) + main_frame->reload(); +} + +void ContentSettingsObserver::OnSetAllowRunningInsecureContent(bool allow) { + allow_running_insecure_content_ = allow; + OnSetAllowDisplayingInsecureContent(allow); +} + + void ContentSettingsObserver::ClearBlockedContentSettings() { for (size_t i = 0; i < arraysize(content_blocked_); ++i) content_blocked_[i] = false; @@ -322,6 +636,18 @@ void ContentSettingsObserver::ClearBlockedContentSettings() { cached_script_permissions_.clear(); } +const extensions::Extension* ContentSettingsObserver::GetExtension( + const WebSecurityOrigin& origin) const { + if (!EqualsASCII(origin.protocol(), extensions::kExtensionScheme)) + return NULL; + + const std::string extension_id = origin.host().utf8().data(); + if (!extension_dispatcher_->IsExtensionActive(extension_id)) + return NULL; + + return extension_dispatcher_->extensions()->GetByID(extension_id); +} + bool ContentSettingsObserver::IsWhitelistedForContentSettings(WebFrame* frame) { // Whitelist Instant processes. if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kInstantProcess)) diff --git a/chrome/renderer/content_settings_observer.h b/chrome/renderer/content_settings_observer.h index ed579ae..d342564 100644 --- a/chrome/renderer/content_settings_observer.h +++ b/chrome/renderer/content_settings_observer.h @@ -11,6 +11,8 @@ #include "chrome/common/content_settings.h" #include "content/public/renderer/render_view_observer.h" #include "content/public/renderer/render_view_observer_tracker.h" +#include "extensions/common/permissions/api_permission.h" +#include "third_party/WebKit/public/web/WebPermissionClient.h" class GURL; @@ -20,12 +22,19 @@ class WebSecurityOrigin; class WebURL; } +namespace extensions { +class Dispatcher; +class Extension; +} + // Handles blocking content per content settings for each RenderView. class ContentSettingsObserver : public content::RenderViewObserver, - public content::RenderViewObserverTracker<ContentSettingsObserver> { + public content::RenderViewObserverTracker<ContentSettingsObserver>, + public blink::WebPermissionClient { public: - explicit ContentSettingsObserver(content::RenderView* render_view); + ContentSettingsObserver(content::RenderView* render_view, + extensions::Dispatcher* extension_dispatcher); virtual ~ContentSettingsObserver(); // Sets the content setting rules which back |AllowImage()|, |AllowScript()|, @@ -39,31 +48,56 @@ class ContentSettingsObserver // Sends an IPC notification that the specified content type was blocked. void DidBlockContentType(ContentSettingsType settings_type); - // These correspond to blink::WebPermissionClient methods. - bool AllowDatabase(blink::WebFrame* frame, - const blink::WebString& name, - const blink::WebString& display_name, - unsigned long estimated_size); - bool AllowFileSystem(blink::WebFrame* frame); - bool AllowImage(blink::WebFrame* frame, - bool enabled_per_settings, - const blink::WebURL& image_url); - bool AllowIndexedDB(blink::WebFrame* frame, - const blink::WebString& name, - const blink::WebSecurityOrigin& origin); - bool AllowPlugins(blink::WebFrame* frame, bool enabled_per_settings); - bool AllowScript(blink::WebFrame* frame, bool enabled_per_settings); - bool AllowScriptFromSource(blink::WebFrame* frame, bool enabled_per_settings, - const blink::WebURL& script_url); - bool AllowStorage(blink::WebFrame* frame, bool local); - - void DidNotAllowPlugins(); - void DidNotAllowScript(); - void DidNotAllowMixedScript(); - - // These two methods are not related to content settings, they are used - // for cases when the NPAPI plugins malfunction if used. - void BlockNPAPIPlugins(); + // blink::WebPermissionClient implementation. + virtual bool allowDatabase(blink::WebFrame* frame, + const blink::WebString& name, + const blink::WebString& display_name, + unsigned long estimated_size); + virtual bool allowFileSystem(blink::WebFrame* frame); + virtual bool allowImage(blink::WebFrame* frame, + bool enabled_per_settings, + const blink::WebURL& image_url); + virtual bool allowIndexedDB(blink::WebFrame* frame, + const blink::WebString& name, + const blink::WebSecurityOrigin& origin); + virtual bool allowPlugins(blink::WebFrame* frame, + bool enabled_per_settings); + virtual bool allowScript(blink::WebFrame* frame, + bool enabled_per_settings); + virtual bool allowScriptFromSource(blink::WebFrame* frame, + bool enabled_per_settings, + const blink::WebURL& script_url); + virtual bool allowStorage(blink::WebFrame* frame, bool local); + virtual bool allowReadFromClipboard(blink::WebFrame* frame, + bool default_value); + virtual bool allowWriteToClipboard(blink::WebFrame* frame, + bool default_value); +#if defined(WEBPERMISSIONCLIENT_USES_FRAME_FOR_ALL_METHODS) + virtual bool allowWebComponents(blink::WebFrame* frame, bool); + virtual bool allowMutationEvents(blink::WebFrame* frame, + bool default_value); + virtual bool allowPushState(blink::WebFrame* frame); +#else + virtual bool allowWebComponents(const blink::WebDocument&, bool); + virtual bool allowMutationEvents(const blink::WebDocument&, + bool default_value); + virtual bool allowPushState(const blink::WebDocument&); +#endif + virtual bool allowWebGLDebugRendererInfo(blink::WebFrame* frame); + virtual void didNotAllowPlugins(blink::WebFrame* frame); + virtual void didNotAllowScript(blink::WebFrame* frame); + virtual bool allowDisplayingInsecureContent( + blink::WebFrame* frame, + bool allowed_per_settings, + const blink::WebSecurityOrigin& context, + const blink::WebURL& url); + virtual bool allowRunningInsecureContent( + blink::WebFrame* frame, + bool allowed_per_settings, + const blink::WebSecurityOrigin& context, + const blink::WebURL& url); + + // This is used for cases when the NPAPI plugins malfunction if used. bool AreNPAPIPluginsBlocked() const; private: @@ -79,10 +113,18 @@ class ContentSettingsObserver // Message handlers. void OnLoadBlockedPlugins(const std::string& identifier); void OnSetAsInterstitial(); + void OnNPAPINotSupported(); + void OnSetAllowDisplayingInsecureContent(bool allow); + void OnSetAllowRunningInsecureContent(bool allow); // Resets the |content_blocked_| array. void ClearBlockedContentSettings(); + // If |origin| corresponds to an installed extension, returns that extension. + // Otherwise returns NULL. + const extensions::Extension* GetExtension( + const blink::WebSecurityOrigin& origin) const; + // Helpers. // True if |frame| contains content that is white-listed for content settings. static bool IsWhitelistedForContentSettings(blink::WebFrame* frame); @@ -90,6 +132,13 @@ class ContentSettingsObserver const blink::WebSecurityOrigin& origin, const GURL& document_url); + // Owned by ChromeContentRendererClient and outlive us. + extensions::Dispatcher* extension_dispatcher_; + + // Insecure content may be permitted for the duration of this render view. + bool allow_displaying_insecure_content_; + bool allow_running_insecure_content_; + // A pointer to content setting rules stored by the renderer. Normally, the // |RendererContentSettingRules| object is owned by // |ChromeRenderProcessObserver|. In the tests it is owned by the caller of diff --git a/chrome/renderer/content_settings_observer_browsertest.cc b/chrome/renderer/content_settings_observer_browsertest.cc index f46865f..1dd0d84 100644 --- a/chrome/renderer/content_settings_observer_browsertest.cc +++ b/chrome/renderer/content_settings_observer_browsertest.cc @@ -34,7 +34,7 @@ class MockContentSettingsObserver : public ContentSettingsObserver { MockContentSettingsObserver::MockContentSettingsObserver( content::RenderView* render_view) - : ContentSettingsObserver(render_view), + : ContentSettingsObserver(render_view, NULL), image_url_("http://www.foo.com/image.jpg"), image_origin_("http://www.foo.com") { } @@ -74,11 +74,11 @@ TEST_F(ChromeRenderViewTest, DISABLED_AllowDOMStorage) { OnAllowDOMStorage(_, _, _, _, _)).WillByDefault(DeleteArg<4>()); EXPECT_CALL(observer, OnAllowDOMStorage(_, _, _, _, _)); - observer.AllowStorage(view_->GetWebView()->focusedFrame(), true); + observer.allowStorage(view_->GetWebView()->focusedFrame(), true); // Accessing localStorage from the same origin again shouldn't result in a // new IPC. - observer.AllowStorage(view_->GetWebView()->focusedFrame(), true); + observer.allowStorage(view_->GetWebView()->focusedFrame(), true); ::testing::Mock::VerifyAndClearExpectations(&observer); } @@ -189,7 +189,7 @@ TEST_F(ChromeRenderViewTest, ImagesBlockedByDefault) { observer->SetContentSettingRules(&content_setting_rules); EXPECT_CALL(mock_observer, OnContentBlocked(CONTENT_SETTINGS_TYPE_IMAGES)); - EXPECT_FALSE(observer->AllowImage(GetMainFrame(), + EXPECT_FALSE(observer->allowImage(GetMainFrame(), true, mock_observer.image_url_)); ::testing::Mock::VerifyAndClearExpectations(&observer); @@ -206,7 +206,7 @@ TEST_F(ChromeRenderViewTest, ImagesBlockedByDefault) { EXPECT_CALL( mock_observer, OnContentBlocked(CONTENT_SETTINGS_TYPE_IMAGES)).Times(0); - EXPECT_TRUE(observer->AllowImage(GetMainFrame(), true, + EXPECT_TRUE(observer->allowImage(GetMainFrame(), true, mock_observer.image_url_)); ::testing::Mock::VerifyAndClearExpectations(&observer); } @@ -233,7 +233,7 @@ TEST_F(ChromeRenderViewTest, ImagesAllowedByDefault) { EXPECT_CALL( mock_observer, OnContentBlocked(CONTENT_SETTINGS_TYPE_IMAGES)).Times(0); - EXPECT_TRUE(observer->AllowImage(GetMainFrame(), true, + EXPECT_TRUE(observer->allowImage(GetMainFrame(), true, mock_observer.image_url_)); ::testing::Mock::VerifyAndClearExpectations(&observer); @@ -248,7 +248,7 @@ TEST_F(ChromeRenderViewTest, ImagesAllowedByDefault) { false)); EXPECT_CALL(mock_observer, OnContentBlocked(CONTENT_SETTINGS_TYPE_IMAGES)); - EXPECT_FALSE(observer->AllowImage(GetMainFrame(), + EXPECT_FALSE(observer->allowImage(GetMainFrame(), true, mock_observer.image_url_)); ::testing::Mock::VerifyAndClearExpectations(&observer); } @@ -372,7 +372,7 @@ TEST_F(ChromeRenderViewTest, ContentSettingsInterstitialPages) { EXPECT_CALL( mock_observer, OnContentBlocked(CONTENT_SETTINGS_TYPE_IMAGES)).Times(0); - EXPECT_TRUE(observer->AllowImage(GetMainFrame(), true, + EXPECT_TRUE(observer->allowImage(GetMainFrame(), true, mock_observer.image_url_)); ::testing::Mock::VerifyAndClearExpectations(&observer); } |