1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "webkit/glue/site_isolation_metrics.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <set> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/hash_tables.h" 10731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/metrics/histogram.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/mime_sniffer.h" 1272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" 1372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h" 1472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebString.h" 1572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebURL.h" 1672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLRequest.h" 1772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "third_party/WebKit/Source/WebKit/chromium/public/WebURLResponse.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebFrame; 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebSecurityOrigin; 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebString; 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebURL; 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebURLRequest; 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochusing WebKit::WebURLResponse; 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace webkit_glue { 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef base::hash_map<unsigned, WebURLRequest::TargetType> TargetTypeMap; 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef base::hash_map<std::string, int> MimeTypeMap; 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochtypedef std::set<std::string> CrossOriginTextHtmlResponseSet; 31c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic TargetTypeMap* GetTargetTypeMap() { 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static TargetTypeMap target_type_map_; 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return &target_type_map_; 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copied from net/base/mime_util.cc, supported_non_image_types[] 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char* const kCrossOriginMimeTypesToLog[] = { 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "text/cache-manifest", 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "text/html", 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "text/xml", 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "text/xsl", 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "text/plain", 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "text/vnd.chromium.ftp-dir", 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "text/", 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "text/css", 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "image/svg+xml", 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "application/xml", 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "application/xhtml+xml", 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "application/rss+xml", 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "application/atom+xml", 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "application/json", 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "application/x-x509-user-cert", 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "multipart/x-mixed-replace", 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "(NONE)" // Keep track of missing MIME types as well 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic MimeTypeMap* GetMimeTypeMap() { 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static MimeTypeMap mime_type_map_; 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!mime_type_map_.size()) { 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < arraysize(kCrossOriginMimeTypesToLog); ++i) 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mime_type_map_[kCrossOriginMimeTypesToLog[i]] = i; 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return &mime_type_map_; 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This is set is used to keep track of the response urls that we want to 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// sniff, since we will have to wait for the payload to arrive. 69c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic CrossOriginTextHtmlResponseSet* GetCrossOriginTextHtmlResponseSet() { 70c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static CrossOriginTextHtmlResponseSet cross_origin_text_html_response_set_; 71c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return &cross_origin_text_html_response_set_; 72c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 73c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void LogVerifiedTextHtmlResponse() { 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_COUNTS( 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "SiteIsolation.CrossSiteNonFrameResponse_verified_texthtml_BLOCK", 1); 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic void LogMislabeledTextHtmlResponse() { 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_COUNTS( 81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "SiteIsolation.CrossSiteNonFrameResponse_mislabeled_texthtml", 1); 82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 83c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SiteIsolationMetrics::AddRequest(unsigned identifier, 85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WebURLRequest::TargetType target_type) { 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TargetTypeMap& target_type_map = *GetTargetTypeMap(); 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch target_type_map[identifier] = target_type; 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 90c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Check whether the given response is allowed due to access control headers. 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This is basically a copy of the logic of passesAccessControlCheck() in 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// WebCore/loader/CrossOriginAccessControl.cpp. 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SiteIsolationMetrics::AllowedByAccessControlHeader( 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WebFrame* frame, const WebURLResponse& response) { 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WebString access_control_origin = response.httpHeaderField( 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WebString::fromUTF8("Access-Control-Allow-Origin")); 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WebSecurityOrigin security_origin = 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WebSecurityOrigin::createFromString(access_control_origin); 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return access_control_origin == WebString::fromUTF8("*") || 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch frame->securityOrigin().canAccess(security_origin); 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// We want to log any cross-site request that we don't think a renderer should 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// be allowed to make. We can safely ignore frame requests (since we'd like 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// those to be in a separate renderer) and plugin requests, even if they are 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// cross-origin. 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// For comparison, we keep counts of: 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// - All requests made by a renderer 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// - All cross-site requests 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Then, for cross-site non-frame/plugin requests, we keep track of: 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// - Counts for MIME types of interest 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// - Counts of those MIME types that carry CORS headers 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// - Counts of mislabeled text/html responses (without CORS) 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// As well as those we would block: 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// - Counts of verified text/html responses (without CORS) 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// - Counts of XML/JSON responses (without CORS) 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// This will let us say what percentage of requests we would end up blocking. 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SiteIsolationMetrics::LogMimeTypeForCrossOriginRequest( 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WebFrame* frame, unsigned identifier, const WebURLResponse& response) { 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_COUNTS("SiteIsolation.Requests", 1); 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TargetTypeMap& target_type_map = *GetTargetTypeMap(); 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch TargetTypeMap::iterator iter = target_type_map.find(identifier); 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (iter != target_type_map.end()) { 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WebURLRequest::TargetType target_type = iter->second; 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch target_type_map.erase(iter); 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Focus on cross-site requests. 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!frame->securityOrigin().canAccess( 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch WebSecurityOrigin::create(response.url()))) { 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_COUNTS("SiteIsolation.CrossSiteRequests", 1); 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Now focus on non-frame, non-plugin requests. 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (target_type != WebURLRequest::TargetIsMainFrame && 138513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch target_type != WebURLRequest::TargetIsSubframe && 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch target_type != WebURLRequest::TargetIsObject) { 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If it is part of a MIME type we might block, log the MIME type. 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string mime_type = response.mimeType().utf8(); 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MimeTypeMap mime_type_map = *GetMimeTypeMap(); 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Also track it if it lacks a MIME type. 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(creis): 304 responses have no MIME type, so we don't handle 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // them correctly. Can we look up their MIME type from the cache? 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (mime_type == "") 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mime_type = "(NONE)"; 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MimeTypeMap::iterator mime_type_iter = mime_type_map.find(mime_type); 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (mime_type_iter != mime_type_map.end()) { 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_ENUMERATION( 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "SiteIsolation.CrossSiteNonFrameResponse_MIME_Type", 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mime_type_iter->second, 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch arraysize(kCrossOriginMimeTypesToLog)); 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We also check access control headers, in case this 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // cross-origin request has been explicitly permitted. 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (AllowedByAccessControlHeader(frame, response)) { 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_ENUMERATION( 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "SiteIsolation.CrossSiteNonFrameResponse_With_CORS_MIME_Type", 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mime_type_iter->second, 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch arraysize(kCrossOriginMimeTypesToLog)); 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Without access control headers, we might block this request. 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Sometimes resources are mislabled as text/html, though, and we 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // should only block them if we can verify that. To do so, we sniff 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the content once we have some of the payload. 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (mime_type == "text/html") { 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Remember the response until we can sniff its contents. 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetCrossOriginTextHtmlResponseSet()->insert( 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch response.url().spec()); 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (mime_type == "text/xml" || 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mime_type == "text/xsl" || 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mime_type == "application/xml" || 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mime_type == "application/xhtml+xml" || 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mime_type == "application/rss+xml" || 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mime_type == "application/atom+xml" || 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch mime_type == "application/json") { 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We will also block XML and JSON MIME types for cross-site 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // non-frame requests without CORS headers. 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_COUNTS( 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "SiteIsolation.CrossSiteNonFrameResponse_xml_or_json_BLOCK", 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1); 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SiteIsolationMetrics::SniffCrossOriginHTML(const WebURL& response_url, 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const char* data, 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int len) { 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!response_url.isValid()) 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Look up the URL to see if it is a text/html request we are tracking. 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CrossOriginTextHtmlResponseSet& cross_origin_text_html_response_set = 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *GetCrossOriginTextHtmlResponseSet(); 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CrossOriginTextHtmlResponseSet::iterator request_iter = 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cross_origin_text_html_response_set.find(response_url.spec()); 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request_iter != cross_origin_text_html_response_set.end()) { 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Log whether it actually looks like HTML. 204c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string sniffed_mime_type; 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool successful = net::SniffMimeType(data, len, response_url, 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "", &sniffed_mime_type); 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (successful && sniffed_mime_type == "text/html") 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LogVerifiedTextHtmlResponse(); 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch else 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LogMislabeledTextHtmlResponse(); 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cross_origin_text_html_response_set.erase(request_iter); 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid SiteIsolationMetrics::RemoveCompletedResponse( 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const WebURL& response_url) { 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!response_url.isValid()) 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Ensure we don't leave responses in the set after they've completed. 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CrossOriginTextHtmlResponseSet& cross_origin_text_html_response_set = 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *GetCrossOriginTextHtmlResponseSet(); 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CrossOriginTextHtmlResponseSet::iterator request_iter = 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cross_origin_text_html_response_set.find(response_url.spec()); 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (request_iter != cross_origin_text_html_response_set.end()) { 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LogMislabeledTextHtmlResponse(); 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cross_origin_text_html_response_set.erase(request_iter); 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace webkit_glue 232