site_isolation_policy.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
1424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// found in the LICENSE file. 4424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 5424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "content/child/site_isolation_policy.h" 6424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 7424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/basictypes.h" 8424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/command_line.h" 94e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/lazy_instance.h" 10424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/logging.h" 11424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/metrics/histogram.h" 12424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/strings/string_piece.h" 13424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/strings/string_util.h" 144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/child/child_thread.h" 15424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "content/public/common/content_switches.h" 16424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "net/base/registry_controlled_domains/registry_controlled_domain.h" 17424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "net/http/http_response_headers.h" 18424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h" 19424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebString.h" 20424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebURL.h" 21424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebURLRequest.h" 22424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebURLResponse.h" 23424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "third_party/WebKit/public/web/WebDocument.h" 24424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "third_party/WebKit/public/web/WebFrame.h" 25424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "third_party/WebKit/public/web/WebFrameClient.h" 26424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "third_party/WebKit/public/web/WebSecurityOrigin.h" 27424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)using base::StringPiece; 29424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)using WebKit::WebDocument; 30424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)using WebKit::WebString; 31424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)using WebKit::WebURL; 32424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)using WebKit::WebURLResponse; 33424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)using WebKit::WebURLRequest; 34424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 35424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)namespace content { 36424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 37424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)namespace { 38424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Maintain the bookkeeping data between OnReceivedResponse and 404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// OnReceivedData. The key is a request id maintained by ResourceDispatcher. 414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)static base::LazyInstance<SiteIsolationPolicy::RequestIdToMetaDataMap> 424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) g_metadata_map = LAZY_INSTANCE_INITIALIZER; 434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Maintain the bookkeeping data for OnReceivedData. Blocking decision is made 454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// when OnReceivedData is called for the first time for a request, and the 464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// decision will remain the same for following data. This map maintains the 474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// decision. The key is a request id maintained by ResourceDispatcher. 484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)static base::LazyInstance<SiteIsolationPolicy::RequestIdToResultMap> 494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) g_result_map = LAZY_INSTANCE_INITIALIZER; 504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// The cross-site document blocking/UMA data collection is deactivated by 524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// default, and only activated in renderer processes. 534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)static bool g_policy_enabled = false; 544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 55424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// MIME types 56424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const char kTextHtml[] = "text/html"; 57424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const char kTextXml[] = "text/xml"; 58424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const char xAppRssXml[] = "application/rss+xml"; 59424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const char kAppXml[] = "application/xml"; 60424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const char kAppJson[] = "application/json"; 61424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const char kTextJson[] = "text/json"; 62424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const char kTextXjson[] = "text/x-json"; 63424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const char kTextPlain[] = "text/plain"; 64424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// TODO(dsjang): this is only needed for collecting UMA stat. Will be deleted 664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// when this class is used for actual blocking. 674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool IsRenderableStatusCode(int status_code) { 684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Chrome only uses the content of a response with one of these status codes 694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // for CSS/JavaScript. For images, Chrome just ignores status code. 704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const int renderable_status_code[] = {200, 201, 202, 203, 206, 300, 714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 301, 302, 303, 305, 306, 307}; 724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (size_t i = 0; i < arraysize(renderable_status_code); ++i) { 734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (renderable_status_code[i] == status_code) 744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return true; 754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool MatchesSignature(StringPiece data, 804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const StringPiece signatures[], 814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) size_t arr_size) { 82424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) size_t offset = data.find_first_not_of(" \t\r\n"); 844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // There is no not-whitespace character in this document. 854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (offset == base::StringPiece::npos) 864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 87424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) data.remove_prefix(offset); 894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) size_t length = data.length(); 904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (size_t sig_index = 0; sig_index < arr_size; ++sig_index) { 924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const StringPiece& signature = signatures[sig_index]; 934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) size_t signature_length = signature.length(); 944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (length < signature_length) 954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) continue; 964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (LowerCaseEqualsASCII( 984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) data.begin(), data.begin() + signature_length, signature.data())) 994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return true; 1004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 1024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void IncrementHistogramCount(const std::string& name) { 1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // The default value of min, max, bucket_count are copied from histogram.h. 1064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::HistogramBase* histogram_pointer = base::Histogram::FactoryGet( 1074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) name, 1, 100000, 50, base::HistogramBase::kUmaTargetedHistogramFlag); 1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) histogram_pointer->Add(1); 1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void IncrementHistogramEnum(const std::string& name, 1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) uint32 sample, 1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) uint32 boundary_value) { 1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // The default value of min, max, bucket_count are copied from histogram.h. 1154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::HistogramBase* histogram_pointer = base::LinearHistogram::FactoryGet( 1164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) name, 1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1, 1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) boundary_value, 1194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) boundary_value + 1, 1204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::HistogramBase::kUmaTargetedHistogramFlag); 1214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) histogram_pointer->Add(sample); 1224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void HistogramCountBlockedResponse( 1254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::string& bucket_prefix, 1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const SiteIsolationPolicy::ResponseMetaData& resp_data, 1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool nosniff_block) { 1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string block_label(nosniff_block ? ".NoSniffBlocked" : ".Blocked"); 1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) IncrementHistogramCount(bucket_prefix + block_label); 1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // The content is blocked if it is sniffed as HTML/JSON/XML. When 1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // the blocked response is with an error status code, it is not 1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // disruptive for the following reasons : 1) the blocked content is 1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // not a binary object (such as an image) since it is sniffed as 1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // text; 2) then, this blocking only breaks the renderer behavior 1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // only if it is either JavaScript or CSS. However, the renderer 1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // doesn't use the contents of JS/CSS with unaffected status code 1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // (e.g, 404). 3) the renderer is expected not to use the cross-site 1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // document content for purposes other than JS/CSS (e.g, XHR). 1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool renderable_status_code = 1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) IsRenderableStatusCode(resp_data.http_status_code); 1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (renderable_status_code) { 1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) IncrementHistogramEnum( 1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bucket_prefix + block_label + ".RenderableStatusCode", 1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) resp_data.resource_type, 1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ResourceType::LAST_TYPE); 1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else { 1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) IncrementHistogramCount(bucket_prefix + block_label + 1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ".NonRenderableStatusCode"); 1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void HistogramCountNotBlockedResponse(const std::string& bucket_prefix, 1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool sniffed_as_js) { 1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) IncrementHistogramCount(bucket_prefix + ".NotBlocked"); 1574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (sniffed_as_js) 1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) IncrementHistogramCount(bucket_prefix + ".NotBlocked.MaybeJS"); 1594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void HistogramCountPolicyDecision( 1624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::string& bucket_prefix, 1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool sniffed_as_document, 1644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool sniffed_as_js, 1654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const SiteIsolationPolicy::ResponseMetaData& resp_data) { 1664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (sniffed_as_document) { 1674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) HistogramCountBlockedResponse(bucket_prefix, resp_data, false); 1684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else { 1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (resp_data.no_sniff) 1704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) HistogramCountBlockedResponse(bucket_prefix, resp_data, true); 1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) else 1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) HistogramCountNotBlockedResponse(bucket_prefix, sniffed_as_js); 1734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} // namespace 1774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)SiteIsolationPolicy::ResponseMetaData::ResponseMetaData() {} 17958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 18058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void SiteIsolationPolicy::SetPolicyEnabled(bool enabled) { 18158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) g_policy_enabled = enabled; 18258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 18358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 184424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void SiteIsolationPolicy::OnReceivedResponse( 185424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) int request_id, 1864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const GURL& frame_origin, 1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const GURL& response_url, 188424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) ResourceType::Type resource_type, 18958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int origin_pid, 190424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const webkit_glue::ResourceResponseInfo& info) { 19158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!g_policy_enabled) 19258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 19358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 19458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // if |origin_pid| is non-zero, it means that this response is for a plugin 19558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // spawned from this renderer process. We exclude responses for plugins for 19658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // now, but eventually, we're going to make plugin processes directly talk to 19758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // the browser process so that we don't apply cross-site document blocking to 19858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // them. 19958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (origin_pid) 20058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 20158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 202424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) UMA_HISTOGRAM_COUNTS("SiteIsolation.AllResponses", 1); 203424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 204424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // See if this is for navigation. If it is, don't block it, under the 205424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // assumption that we will put it in an appropriate process. 206424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (ResourceType::IsFrame(resource_type)) 207424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return; 208424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 209424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!IsBlockableScheme(response_url)) 210424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return; 211424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 212424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (IsSameSite(frame_origin, response_url)) 213424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return; 214424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 215424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) SiteIsolationPolicy::ResponseMetaData::CanonicalMimeType canonical_mime_type = 216424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) GetCanonicalMimeType(info.mime_type); 217424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 218424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (canonical_mime_type == SiteIsolationPolicy::ResponseMetaData::Others) 219424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return; 220424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 221424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Every CORS request should have the Access-Control-Allow-Origin header even 222424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // if it is preceded by a pre-flight request. Therefore, if this is a CORS 223424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // request, it has this header. response.httpHeaderField() internally uses 224424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // case-insensitive matching for the header name. 225424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) std::string access_control_origin; 226424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 227424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // We can use a case-insensitive header name for EnumerateHeader(). 228424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) info.headers->EnumerateHeader( 229424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) NULL, "access-control-allow-origin", &access_control_origin); 230424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (IsValidCorsHeaderSet(frame_origin, response_url, access_control_origin)) 231424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return; 232424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 233424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Real XSD data collection starts from here. 234424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) std::string no_sniff; 235424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) info.headers->EnumerateHeader(NULL, "x-content-type-options", &no_sniff); 236424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 237424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) ResponseMetaData resp_data; 238424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) resp_data.frame_origin = frame_origin.spec(); 239424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) resp_data.response_url = response_url; 240424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) resp_data.resource_type = resource_type; 241424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) resp_data.canonical_mime_type = canonical_mime_type; 242424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) resp_data.http_status_code = info.headers->response_code(); 243424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) resp_data.no_sniff = LowerCaseEqualsASCII(no_sniff, "nosniff"); 244424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 2454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) (g_metadata_map.Get())[request_id] = resp_data; 246424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 247424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 248424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool SiteIsolationPolicy::ShouldBlockResponse( 249424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) int request_id, 2504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const char* raw_data, 2514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) int raw_length, 252424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) std::string* alternative_data) { 25358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!g_policy_enabled) 25458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return false; 25558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) RequestIdToMetaDataMap& metadata_map = g_metadata_map.Get(); 2574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) RequestIdToResultMap& result_map = g_result_map.Get(); 258424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 259424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // If there's an entry for |request_id| in blocked_map, this request's first 260424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // data packet has already been examined. We can return the result here. 2614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (result_map.count(request_id) != 0) { 2624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (result_map[request_id]) { 263424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Here, the blocking result has been set for the previous run of 264424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // ShouldBlockResponse(), so we set alternative data to an empty string so 265424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // that ResourceDispatcher doesn't call its peer's onReceivedData() with 266424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // the alternative data. 267424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) alternative_data->erase(); 268424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 269424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 270424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 271424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 272424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 273424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // If result_map doesn't have an entry for |request_id|, we're receiving the 274424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // first data packet for request_id. If request_id is not registered, this 275424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // request is identified as a non-target of our policy. So we return true. 2764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (metadata_map.count(request_id) == 0) { 277424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // We set request_id to true so that we always return true for this request. 2784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) result_map[request_id] = false; 279424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 280424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 281424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 2824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) StringPiece data(raw_data, raw_length); 2834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 284424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // We now look at the first data packet received for request_id. 2854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ResponseMetaData resp_data = metadata_map[request_id]; 2864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) metadata_map.erase(request_id); 287424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 288424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Record the length of the first received network packet to see if it's 289424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // enough for sniffing. 2904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) UMA_HISTOGRAM_COUNTS("SiteIsolation.XSD.DataLength", raw_length); 291424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 292424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Record the number of cross-site document responses with a specific mime 293424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // type (text/html, text/xml, etc). 294424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION( 295424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) "SiteIsolation.XSD.MimeType", 296424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) resp_data.canonical_mime_type, 297424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) SiteIsolationPolicy::ResponseMetaData::MaxCanonicalMimeType); 298424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 2994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Store the result of cross-site document blocking analysis. 3004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool is_blocked = false; 3014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool sniffed_as_js = SniffForJS(data); 302424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 303424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Record the number of responses whose content is sniffed for what its mime 304424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // type claims it to be. For example, we apply a HTML sniffer for a document 305424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // tagged with text/html here. Whenever this check becomes true, we'll block 306424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // the response. 3074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (resp_data.canonical_mime_type != 3084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SiteIsolationPolicy::ResponseMetaData::Plain) { 3094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string bucket_prefix; 3104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool sniffed_as_target_document = false; 3114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (resp_data.canonical_mime_type == 3124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SiteIsolationPolicy::ResponseMetaData::HTML) { 3134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bucket_prefix = "SiteIsolation.XSD.HTML"; 3144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sniffed_as_target_document = SniffForHTML(data); 3154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else if (resp_data.canonical_mime_type == 3164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SiteIsolationPolicy::ResponseMetaData::XML) { 3174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bucket_prefix = "SiteIsolation.XSD.XML"; 3184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sniffed_as_target_document = SniffForXML(data); 3194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else if (resp_data.canonical_mime_type == 3204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SiteIsolationPolicy::ResponseMetaData::JSON) { 3214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bucket_prefix = "SiteIsolation.XSD.JSON"; 3224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sniffed_as_target_document = SniffForJSON(data); 3234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else { 3244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NOTREACHED() << "Not a blockable mime type: " 3254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) << resp_data.canonical_mime_type; 3264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 3274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (sniffed_as_target_document) { 3294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) is_blocked = true; 3304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) HistogramCountBlockedResponse(bucket_prefix, resp_data, false); 3314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else { 3324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (resp_data.no_sniff) { 3334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) is_blocked = true; 3344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) HistogramCountBlockedResponse(bucket_prefix, resp_data, true); 3354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else { 3364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) HistogramCountNotBlockedResponse(bucket_prefix, sniffed_as_js); 337424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 3384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 3394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else { 3404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // This block is for plain text documents. We apply our HTML, XML, 3414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // and JSON sniffer to a text document in the order, and block it 3424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // if any of them succeeds in sniffing. 3434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) std::string bucket_prefix; 3444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (SniffForHTML(data)) 3454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bucket_prefix = "SiteIsolation.XSD.Plain.HTML"; 3464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) else if (SniffForXML(data)) 3474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bucket_prefix = "SiteIsolation.XSD.Plain.XML"; 3484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) else if (SniffForJSON(data)) 3494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bucket_prefix = "SiteIsolation.XSD.Plain.JSON"; 3504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 3514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (bucket_prefix.size() > 0) { 3524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) is_blocked = true; 3534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) HistogramCountBlockedResponse(bucket_prefix, resp_data, false); 3544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else if (resp_data.no_sniff) { 3554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) is_blocked = true; 3564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) HistogramCountBlockedResponse("SiteIsolation.XSD.Plain", resp_data, true); 3574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else { 3584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) HistogramCountNotBlockedResponse("SiteIsolation.XSD.Plain", 3594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) sniffed_as_js); 3604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 361424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 362424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 3634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!CommandLine::ForCurrentProcess()->HasSwitch( 3644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) switches::kBlockCrossSiteDocuments)) 3654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) is_blocked = false; 3664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) result_map[request_id] = is_blocked; 367424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 3684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (is_blocked) { 369424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) alternative_data->erase(); 370424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) alternative_data->insert(0, " "); 371424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) LOG(ERROR) << resp_data.response_url 372424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) << " is blocked as an illegal cross-site document from " 373424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) << resp_data.frame_origin; 374424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 3754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return is_blocked; 376424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 377424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 378424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void SiteIsolationPolicy::OnRequestComplete(int request_id) { 37958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!g_policy_enabled) 38058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 3814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) g_metadata_map.Get().erase(request_id); 3824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) g_result_map.Get().erase(request_id); 383424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 384424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 385424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)SiteIsolationPolicy::ResponseMetaData::CanonicalMimeType 386424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)SiteIsolationPolicy::GetCanonicalMimeType(const std::string& mime_type) { 387424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (LowerCaseEqualsASCII(mime_type, kTextHtml)) { 388424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return SiteIsolationPolicy::ResponseMetaData::HTML; 389424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 390424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 391424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (LowerCaseEqualsASCII(mime_type, kTextPlain)) { 392424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return SiteIsolationPolicy::ResponseMetaData::Plain; 393424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 394424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 395424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (LowerCaseEqualsASCII(mime_type, kAppJson) || 396424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) LowerCaseEqualsASCII(mime_type, kTextJson) || 397424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) LowerCaseEqualsASCII(mime_type, kTextXjson)) { 398424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return SiteIsolationPolicy::ResponseMetaData::JSON; 399424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 400424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 401424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (LowerCaseEqualsASCII(mime_type, kTextXml) || 402424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) LowerCaseEqualsASCII(mime_type, xAppRssXml) || 403424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) LowerCaseEqualsASCII(mime_type, kAppXml)) { 404424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return SiteIsolationPolicy::ResponseMetaData::XML; 405424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 406424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 407424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return SiteIsolationPolicy::ResponseMetaData::Others; 408424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 409424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 410424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool SiteIsolationPolicy::IsBlockableScheme(const GURL& url) { 411424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // We exclude ftp:// from here. FTP doesn't provide a Content-Type 412424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // header which our policy depends on, so we cannot protect any 413424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // document from FTP servers. 414424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return url.SchemeIs("http") || url.SchemeIs("https"); 415424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 416424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 417424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool SiteIsolationPolicy::IsSameSite(const GURL& frame_origin, 418424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const GURL& response_url) { 419424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 420424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!frame_origin.is_valid() || !response_url.is_valid()) 421424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 422424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 423424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (frame_origin.scheme() != response_url.scheme()) 424424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 425424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 426424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // SameDomainOrHost() extracts the effective domains (public suffix plus one) 427424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // from the two URLs and compare them. 428424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // TODO(dsjang): use INCLUDE_PRIVATE_REGISTRIES when http://crbug.com/7988 is 429424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // fixed. 430424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return net::registry_controlled_domains::SameDomainOrHost( 431424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) frame_origin, 432424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) response_url, 433424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES); 434424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 435424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 436424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// We don't use Webkit's existing CORS policy implementation since 437424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// their policy works in terms of origins, not sites. For example, 438424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// when frame is sub.a.com and it is not allowed to access a document 439424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// with sub1.a.com. But under Site Isolation, it's allowed. 440424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool SiteIsolationPolicy::IsValidCorsHeaderSet( 4414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const GURL& frame_origin, 4424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const GURL& website_origin, 4434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const std::string& access_control_origin) { 444424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Many websites are sending back "\"*\"" instead of "*". This is 445424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // non-standard practice, and not supported by Chrome. Refer to 446424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // CrossOriginAccessControl::passesAccessControlCheck(). 447424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 448424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // TODO(dsjang): * is not allowed for the response from a request 449424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // with cookies. This allows for more than what the renderer will 450424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // eventually be able to receive, so we won't see illegal cross-site 451424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // documents allowed by this. We have to find a way to see if this 452424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // response is from a cookie-tagged request or not in the future. 453424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (access_control_origin == "*") 454424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 455424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 456424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // TODO(dsjang): The CORS spec only treats a fully specified URL, except for 457424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // "*", but many websites are using just a domain for access_control_origin, 458424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // and this is blocked by Webkit's CORS logic here : 459424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // CrossOriginAccessControl::passesAccessControlCheck(). GURL is set 460424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // is_valid() to false when it is created from a URL containing * in the 461424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // domain part. 462424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 463424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) GURL cors_origin(access_control_origin); 464424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return IsSameSite(frame_origin, cors_origin); 465424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 466424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 467424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// This function is a slight modification of |net::SniffForHTML|. 4684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool SiteIsolationPolicy::SniffForHTML(StringPiece data) { 469424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // The content sniffer used by Chrome and Firefox are using "<!--" 470424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // as one of the HTML signatures, but it also appears in valid 471424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // JavaScript, considered as well-formed JS by the browser. Since 472424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // we do not want to block any JS, we exclude it from our HTML 473424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // signatures. This can weaken our document block policy, but we can 474424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // break less websites. 475424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // TODO(dsjang): parameterize |net::SniffForHTML| with an option 476424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // that decides whether to include <!-- or not, so that we can 477424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // remove this function. 4784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // TODO(dsjang): Once SiteIsolationPolicy is moved into the browser 4794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // process, we should do single-thread checking here for the static 4804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // initializer. 4814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const StringPiece kHtmlSignatures[] = { 4824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) StringPiece("<!DOCTYPE html"), // HTML5 spec 4834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) StringPiece("<script"), // HTML5 spec, Mozilla 4844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) StringPiece("<html"), // HTML5 spec, Mozilla 4854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) StringPiece("<head"), // HTML5 spec, Mozilla 4864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) StringPiece("<iframe"), // Mozilla 4874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) StringPiece("<h1"), // Mozilla 4884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) StringPiece("<div"), // Mozilla 4894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) StringPiece("<font"), // Mozilla 4904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) StringPiece("<table"), // Mozilla 4914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) StringPiece("<a"), // Mozilla 4924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) StringPiece("<style"), // Mozilla 4934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) StringPiece("<title"), // Mozilla 4944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) StringPiece("<b"), // Mozilla 4954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) StringPiece("<body"), // Mozilla 4964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) StringPiece("<br"), // Mozilla 4974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) StringPiece("<p"), // Mozilla 4984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) StringPiece("<?xml") // Mozilla 499424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) }; 500424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 5014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) while (data.length() > 0) { 5024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (MatchesSignature( 5034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) data, kHtmlSignatures, arraysize(kHtmlSignatures))) 5044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return true; 505424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 5064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // If we cannot find "<!--", we fail sniffing this as HTML. 5074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const StringPiece kCommentBegins[] = { StringPiece("<!--") }; 5084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!MatchesSignature(data, kCommentBegins, arraysize(kCommentBegins))) 5094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) break; 510424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 511424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Search for --> and do SniffForHTML after that. If we can find the 512424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // comment's end, we start HTML sniffing from there again. 5134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const char kEndComment[] = "-->"; 5144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) size_t offset = data.find(kEndComment); 5154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (offset == base::StringPiece::npos) 5164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) break; 5174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 5184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Proceed to the index next to the ending comment (-->). 5194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) data.remove_prefix(offset + strlen(kEndComment)); 520424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 521424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 522424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 523424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 524424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 5254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool SiteIsolationPolicy::SniffForXML(base::StringPiece data) { 526424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // TODO(dsjang): Chrome's mime_sniffer is using strncasecmp() for 527424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // this signature. However, XML is case-sensitive. Don't we have to 528424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // be more lenient only to block documents starting with the exact 529424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // string <?xml rather than <?XML ? 5304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // TODO(dsjang): Once SiteIsolationPolicy is moved into the browser 5314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // process, we should do single-thread checking here for the static 5324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // initializer. 5334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const StringPiece kXmlSignatures[] = { StringPiece("<?xml") }; 5344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return MatchesSignature(data, kXmlSignatures, arraysize(kXmlSignatures)); 535424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 536424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 5374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool SiteIsolationPolicy::SniffForJSON(base::StringPiece data) { 538424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // TODO(dsjang): We have to come up with a better way to sniff 539424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // JSON. However, even RE cannot help us that much due to the fact 540424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // that we don't do full parsing. This DFA starts with state 0, and 541424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // finds {, "/' and : in that order. We're avoiding adding a 542424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // dependency on a regular expression library. 5434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) enum { 5444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) kStartState, 5454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) kLeftBraceState, 5464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) kLeftQuoteState, 5474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) kColonState, 5484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) kTerminalState, 5494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } state = kStartState; 5504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 5514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) size_t length = data.length(); 552424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) for (size_t i = 0; i < length && state < kColonState; ++i) { 553424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const char c = data[i]; 554424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (c == ' ' || c == '\t' || c == '\r' || c == '\n') 555424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) continue; 556424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 557424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) switch (state) { 5584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) case kStartState: 559424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (c == '{') 560424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) state = kLeftBraceState; 561424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) else 5624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) state = kTerminalState; 563424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) break; 564424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case kLeftBraceState: 565424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (c == '\"' || c == '\'') 566424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) state = kLeftQuoteState; 567424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) else 5684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) state = kTerminalState; 569424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) break; 570424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case kLeftQuoteState: 571424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (c == ':') 572424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) state = kColonState; 573424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) break; 5744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) case kColonState: 5754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) case kTerminalState: 576424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) NOTREACHED(); 577424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) break; 578424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 579424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 580424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return state == kColonState; 581424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 582424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 5834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool SiteIsolationPolicy::SniffForJS(StringPiece data) { 584424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // TODO(dsjang): This is a real hack. The only purpose of this function is to 585424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // try to see if there's any possibility that this data can be JavaScript 586424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // (superset of JS). This function will be removed once UMA stats are 587424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // gathered. 588424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 589424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Search for "var " for JS detection. 5904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return data.find("var ") != base::StringPiece::npos; 591424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 592424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 593424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} // namespace content 594