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