diff options
author | creis@chromium.org <creis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-23 17:37:54 +0000 |
---|---|---|
committer | creis@chromium.org <creis@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-05-23 17:37:54 +0000 |
commit | f4b8f31dde49067a092303025d4baaf47e93f491 (patch) | |
tree | b2e88b62dfad97470c2c97e5fd32c6b68b7186d8 /webkit/glue/site_isolation_metrics.cc | |
parent | 865f37920b4b2b600832017c9f3c1741a38b416a (diff) | |
download | chromium_src-f4b8f31dde49067a092303025d4baaf47e93f491.zip chromium_src-f4b8f31dde49067a092303025d4baaf47e93f491.tar.gz chromium_src-f4b8f31dde49067a092303025d4baaf47e93f491.tar.bz2 |
Update the Site Isolation UMA metrics.
Fixes a bug with tracking CORS headers and starts tracking all requests
and all cross-site requests, for calculating the fraction we would block.
Also explicitly counts the requests we would block in new UMA histograms.
Currently has a problem with "304 Not Modified" responses, since no MIME
type is provided...
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/2132002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@48003 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/glue/site_isolation_metrics.cc')
-rw-r--r-- | webkit/glue/site_isolation_metrics.cc | 123 |
1 files changed, 89 insertions, 34 deletions
diff --git a/webkit/glue/site_isolation_metrics.cc b/webkit/glue/site_isolation_metrics.cc index a97bb96..912263f 100644 --- a/webkit/glue/site_isolation_metrics.cc +++ b/webkit/glue/site_isolation_metrics.cc @@ -51,7 +51,8 @@ static const char* const kCrossOriginMimeTypesToLog[] = { "application/atom+xml", "application/json", "application/x-x509-user-cert", - "multipart/x-mixed-replace" + "multipart/x-mixed-replace", + "(NONE)" // Keep track of missing MIME types as well }; static MimeTypeMap* GetMimeTypeMap() { @@ -72,7 +73,7 @@ static CrossOriginTextHtmlResponseSet* GetCrossOriginTextHtmlResponseSet() { static void LogVerifiedTextHtmlResponse() { UMA_HISTOGRAM_COUNTS( - "SiteIsolation.CrossSiteNonFrameResponse_verified_texthtml", 1); + "SiteIsolation.CrossSiteNonFrameResponse_verified_texthtml_BLOCK", 1); } static void LogMislabeledTextHtmlResponse() { @@ -86,50 +87,102 @@ void SiteIsolationMetrics::AddRequest(unsigned identifier, target_type_map[identifier] = target_type; } +// Check whether the given response is allowed due to access control headers. +// This is basically a copy of the logic of passesAccessControlCheck() in +// WebCore/loader/CrossOriginAccessControl.cpp. +bool SiteIsolationMetrics::AllowedByAccessControlHeader( + WebFrame* frame, const WebURLResponse& response) { + WebString access_control_origin = response.httpHeaderField( + WebString::fromUTF8("Access-Control-Allow-Origin")); + WebSecurityOrigin security_origin = + WebSecurityOrigin::createFromString(access_control_origin); + return access_control_origin == WebString::fromUTF8("*") || + frame->securityOrigin().canAccess(security_origin); +} + +// We want to log any cross-site request that we don't think a renderer should +// be allowed to make. We can safely ignore frame requests (since we'd like +// those to be in a separate renderer) and plugin requests, even if they are +// cross-origin. +// +// For comparison, we keep counts of: +// - All requests made by a renderer +// - All cross-site requests +// +// Then, for cross-site non-frame/plugin requests, we keep track of: +// - Counts for MIME types of interest +// - Counts of those MIME types that carry CORS headers +// - Counts of mislabeled text/html responses (without CORS) +// As well as those we would block: +// - Counts of verified text/html responses (without CORS) +// - Counts of XML/JSON responses (without CORS) +// +// This will let us say what percentage of requests we would end up blocking. void SiteIsolationMetrics::LogMimeTypeForCrossOriginRequest( WebFrame* frame, unsigned identifier, const WebURLResponse& response) { + UMA_HISTOGRAM_COUNTS("SiteIsolation.Requests", 1); + TargetTypeMap& target_type_map = *GetTargetTypeMap(); TargetTypeMap::iterator iter = target_type_map.find(identifier); if (iter != target_type_map.end()) { WebURLRequest::TargetType target_type = iter->second; target_type_map.erase(iter); - // We want to log any cross-site request that we don't think a renderer - // should be allowed to make. We can safely ignore frame requests (since - // we'd like those to be in a separate renderer) and plugin requests, even - // if they are cross-origin. - if (target_type != WebURLRequest::TargetIsMainFrame && - target_type != WebURLRequest::TargetIsSubFrame && - target_type != WebURLRequest::TargetIsObject && - !frame->securityOrigin().canAccess( + + // Focus on cross-site requests. + if (!frame->securityOrigin().canAccess( WebSecurityOrigin::create(response.url()))) { - std::string mime_type = response.mimeType().utf8(); - MimeTypeMap mime_type_map = *GetMimeTypeMap(); - MimeTypeMap::iterator mime_type_iter = mime_type_map.find(mime_type); - if (mime_type_iter != mime_type_map.end()) { - UMA_HISTOGRAM_ENUMERATION( - "SiteIsolation.CrossSiteNonFrameResponse_MIME_Type", - mime_type_iter->second, - arraysize(kCrossOriginMimeTypesToLog)); - - // We also should check access control headers, in case this - // cross-origin request has been explicitly permitted. - // This is basically a copy of the logic of passesAccessControlCheck() - // in WebCore/loader/CrossOriginAccessControl.cpp. - WebString access_control_origin = response.httpHeaderField( - WebString::fromUTF8("Access-Control-Allow-Origin")); - if (access_control_origin != WebString::fromUTF8("*") - && !frame->securityOrigin().canAccess( - WebSecurityOrigin::createFromString(access_control_origin))) { + UMA_HISTOGRAM_COUNTS("SiteIsolation.CrossSiteRequests", 1); + + // Now focus on non-frame, non-plugin requests. + if (target_type != WebURLRequest::TargetIsMainFrame && + target_type != WebURLRequest::TargetIsSubFrame && + target_type != WebURLRequest::TargetIsObject) { + // If it is part of a MIME type we might block, log the MIME type. + std::string mime_type = response.mimeType().utf8(); + MimeTypeMap mime_type_map = *GetMimeTypeMap(); + // Also track it if it lacks a MIME type. + // TODO(creis): 304 responses have no MIME type, so we don't handle + // them correctly. Can we look up their MIME type from the cache? + if (mime_type == "") + mime_type = "(NONE)"; + MimeTypeMap::iterator mime_type_iter = mime_type_map.find(mime_type); + if (mime_type_iter != mime_type_map.end()) { UMA_HISTOGRAM_ENUMERATION( - "SiteIsolation.CrossSiteNonFrameResponse_With_CORS_MIME_Type", + "SiteIsolation.CrossSiteNonFrameResponse_MIME_Type", mime_type_iter->second, arraysize(kCrossOriginMimeTypesToLog)); - } - // Sometimes resources are mislabeled as text/html. Once we have some - // of the payload, we want to determine if this was actually text/html. - if (mime_type == "text/html") - GetCrossOriginTextHtmlResponseSet()->insert(response.url().spec()); + // We also check access control headers, in case this + // cross-origin request has been explicitly permitted. + if (AllowedByAccessControlHeader(frame, response)) { + UMA_HISTOGRAM_ENUMERATION( + "SiteIsolation.CrossSiteNonFrameResponse_With_CORS_MIME_Type", + mime_type_iter->second, + arraysize(kCrossOriginMimeTypesToLog)); + } else { + // Without access control headers, we might block this request. + // Sometimes resources are mislabled as text/html, though, and we + // should only block them if we can verify that. To do so, we sniff + // the content once we have some of the payload. + if (mime_type == "text/html") { + // Remember the response until we can sniff its contents. + GetCrossOriginTextHtmlResponseSet()->insert( + response.url().spec()); + } else if (mime_type == "text/xml" || + mime_type == "text/xsl" || + mime_type == "application/xml" || + mime_type == "application/xhtml+xml" || + mime_type == "application/rss+xml" || + mime_type == "application/atom+xml" || + mime_type == "application/json") { + // We will also block XML and JSON MIME types for cross-site + // non-frame requests without CORS headers. + UMA_HISTOGRAM_COUNTS( + "SiteIsolation.CrossSiteNonFrameResponse_xml_or_json_BLOCK", + 1); + } + } + } } } } @@ -141,11 +194,13 @@ void SiteIsolationMetrics::SniffCrossOriginHTML(const WebURL& response_url, if (!response_url.isValid()) return; + // Look up the URL to see if it is a text/html request we are tracking. CrossOriginTextHtmlResponseSet& cross_origin_text_html_response_set = *GetCrossOriginTextHtmlResponseSet(); CrossOriginTextHtmlResponseSet::iterator request_iter = cross_origin_text_html_response_set.find(response_url.spec()); if (request_iter != cross_origin_text_html_response_set.end()) { + // Log whether it actually looks like HTML. std::string sniffed_mime_type; bool successful = net::SniffMimeType(data, len, response_url, "", &sniffed_mime_type); |