site_isolation_policy.cc revision 58537e28ecd584eab876aee8be7156509866d23a
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"
9424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/logging.h"
10424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/metrics/histogram.h"
11424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/strings/string_piece.h"
12424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/strings/string_util.h"
13424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "content/public/common/content_switches.h"
14424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
15424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "net/http/http_response_headers.h"
16424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
17424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebString.h"
18424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebURL.h"
19424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebURLRequest.h"
20424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "third_party/WebKit/public/platform/WebURLResponse.h"
21424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "third_party/WebKit/public/web/WebDocument.h"
22424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "third_party/WebKit/public/web/WebFrame.h"
23424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "third_party/WebKit/public/web/WebFrameClient.h"
24424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
25424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
26424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)using WebKit::WebDocument;
27424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)using WebKit::WebString;
28424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)using WebKit::WebURL;
29424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)using WebKit::WebURLResponse;
30424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)using WebKit::WebURLRequest;
31424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
32424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)namespace content {
33424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
34424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)namespace {
35424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
36424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// MIME types
37424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const char kTextHtml[] = "text/html";
38424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const char kTextXml[] = "text/xml";
39424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const char xAppRssXml[] = "application/rss+xml";
40424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const char kAppXml[] = "application/xml";
41424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const char kAppJson[] = "application/json";
42424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const char kTextJson[] = "text/json";
43424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const char kTextXjson[] = "text/x-json";
44424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const char kTextPlain[] = "text/plain";
45424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
46424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}  // anonymous namespace
47424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
48424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)SiteIsolationPolicy::ResponseMetaData::ResponseMetaData() {}
49424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
5058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// The cross-site document blocking/UMA data collection is deactivated by
5158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// default, and only activated in renderer processes.
5258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool SiteIsolationPolicy::g_policy_enabled = false;
5358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
5458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void SiteIsolationPolicy::SetPolicyEnabled(bool enabled) {
5558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  g_policy_enabled = enabled;
5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
58424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void SiteIsolationPolicy::OnReceivedResponse(
59424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int request_id,
60424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    GURL& frame_origin,
61424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    GURL& response_url,
62424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    ResourceType::Type resource_type,
6358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    int origin_pid,
64424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const webkit_glue::ResourceResponseInfo& info) {
6558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!g_policy_enabled)
6658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return;
6758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
6858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // if |origin_pid| is non-zero, it means that this response is for a plugin
6958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // spawned from this renderer process. We exclude responses for plugins for
7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // now, but eventually, we're going to make plugin processes directly talk to
7158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // the browser process so that we don't apply cross-site document blocking to
7258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // them.
7358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (origin_pid)
7458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return;
7558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
76424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  UMA_HISTOGRAM_COUNTS("SiteIsolation.AllResponses", 1);
77424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
78424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // See if this is for navigation. If it is, don't block it, under the
79424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // assumption that we will put it in an appropriate process.
80424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (ResourceType::IsFrame(resource_type))
81424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
82424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
83424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!IsBlockableScheme(response_url))
84424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
85424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
86424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (IsSameSite(frame_origin, response_url))
87424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
88424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
89424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  SiteIsolationPolicy::ResponseMetaData::CanonicalMimeType canonical_mime_type =
90424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      GetCanonicalMimeType(info.mime_type);
91424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
92424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (canonical_mime_type == SiteIsolationPolicy::ResponseMetaData::Others)
93424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
94424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
95424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Every CORS request should have the Access-Control-Allow-Origin header even
96424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // if it is preceded by a pre-flight request. Therefore, if this is a CORS
97424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // request, it has this header.  response.httpHeaderField() internally uses
98424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // case-insensitive matching for the header name.
99424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  std::string access_control_origin;
100424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
101424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // We can use a case-insensitive header name for EnumerateHeader().
102424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  info.headers->EnumerateHeader(
103424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      NULL, "access-control-allow-origin", &access_control_origin);
104424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (IsValidCorsHeaderSet(frame_origin, response_url, access_control_origin))
105424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
106424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
107424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Real XSD data collection starts from here.
108424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  std::string no_sniff;
109424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  info.headers->EnumerateHeader(NULL, "x-content-type-options", &no_sniff);
110424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
111424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ResponseMetaData resp_data;
112424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  resp_data.frame_origin = frame_origin.spec();
113424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  resp_data.response_url = response_url;
114424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  resp_data.resource_type = resource_type;
115424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  resp_data.canonical_mime_type = canonical_mime_type;
116424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  resp_data.http_status_code = info.headers->response_code();
117424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  resp_data.no_sniff = LowerCaseEqualsASCII(no_sniff, "nosniff");
118424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
119424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  RequestIdToMetaDataMap* metadata_map = GetRequestIdToMetaDataMap();
120424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  (*metadata_map)[request_id] = resp_data;
121424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
122424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
123424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// These macros are defined here so that we prevent code size bloat-up due to
124424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// the UMA_HISTOGRAM_* macros. Similar logic is used for recording UMA stats for
125424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// different MIME types, but we cannot create a helper function for this since
126424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// UMA_HISTOGRAM_* macros do not accept variables as their bucket names. As a
127424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// solution, macros are used instead to capture the repeated pattern for
128424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// recording UMA stats.  TODO(dsjang): this is only needed for collecting UMA
129424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// stat. Will be deleted when this class is used for actual blocking.
130424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
131424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#define SITE_ISOLATION_POLICY_COUNT_BLOCK(BUCKET_PREFIX) \
132424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    UMA_HISTOGRAM_COUNTS( BUCKET_PREFIX ".Blocked", 1); \
133424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    result = true;                                      \
134424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (renderable_status_code) { \
135424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      UMA_HISTOGRAM_ENUMERATION( \
136424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          BUCKET_PREFIX ".Blocked.RenderableStatusCode", \
137424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        resp_data.resource_type, \
138424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        WebURLRequest::TargetIsUnspecified + 1); \
139424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    } else { \
140424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      UMA_HISTOGRAM_COUNTS(BUCKET_PREFIX ".Blocked.NonRenderableStatusCode",1);\
141424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
142424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
143424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#define SITE_ISOLATION_POLICY_COUNT_NO_SNIFF_BLOCK(BUCKET_PREFIX) \
144424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    UMA_HISTOGRAM_COUNTS( BUCKET_PREFIX ".NoSniffBlocked", 1); \
145424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    result = true;  \
146424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (renderable_status_code) { \
147424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      UMA_HISTOGRAM_ENUMERATION( \
148424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          BUCKET_PREFIX ".NoSniffBlocked.RenderableStatusCode", \
149424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        resp_data.resource_type, \
150424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        WebURLRequest::TargetIsUnspecified + 1); \
151424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    } else { \
152424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      UMA_HISTOGRAM_ENUMERATION( \
153424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          BUCKET_PREFIX ".NoSniffBlocked.NonRenderableStatusCode", \
154424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        resp_data.resource_type, \
155424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        WebURLRequest::TargetIsUnspecified + 1); \
156424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
157424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
158424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#define SITE_ISOLATION_POLICY_COUNT_NOTBLOCK(BUCKET_PREFIX) \
159424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    UMA_HISTOGRAM_COUNTS(BUCKET_PREFIX ".NotBlocked", 1); \
160424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (is_sniffed_for_js) \
161424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      UMA_HISTOGRAM_COUNTS(BUCKET_PREFIX ".NotBlocked.MaybeJS", 1); \
162424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
163424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#define SITE_ISOLATION_POLICY_SNIFF_AND_COUNT(SNIFF_EXPR,BUCKET_PREFIX) \
164424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (SNIFF_EXPR) { \
165424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    SITE_ISOLATION_POLICY_COUNT_BLOCK(BUCKET_PREFIX) \
166424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  } else { \
167424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (resp_data.no_sniff) { \
168424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      SITE_ISOLATION_POLICY_COUNT_NO_SNIFF_BLOCK(BUCKET_PREFIX) \
169424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    } else { \
170424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      SITE_ISOLATION_POLICY_COUNT_NOTBLOCK(BUCKET_PREFIX) \
171424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    } \
172424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
173424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
174424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool SiteIsolationPolicy::ShouldBlockResponse(
175424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int request_id,
176424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const char* data,
177424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int length,
178424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    std::string* alternative_data) {
17958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!g_policy_enabled)
18058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return false;
18158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
182424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  RequestIdToMetaDataMap* metadata_map = GetRequestIdToMetaDataMap();
183424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  RequestIdToResultMap* result_map = GetRequestIdToResultMap();
184424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
185424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // If there's an entry for |request_id| in blocked_map, this request's first
186424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // data packet has already been examined. We can return the result here.
187424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (result_map->count(request_id) != 0) {
188424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if ((*result_map)[request_id]) {
189424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // Here, the blocking result has been set for the previous run of
190424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // ShouldBlockResponse(), so we set alternative data to an empty string so
191424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // that ResourceDispatcher doesn't call its peer's onReceivedData() with
192424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // the alternative data.
193424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      alternative_data->erase();
194424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      return true;
195424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
196424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return false;
197424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
198424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
199424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // If result_map doesn't have an entry for |request_id|, we're receiving the
200424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // first data packet for request_id. If request_id is not registered, this
201424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // request is identified as a non-target of our policy. So we return true.
202424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (metadata_map->count(request_id) == 0) {
203424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // We set request_id to true so that we always return true for this request.
204424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    (*result_map)[request_id] = false;
205424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return false;
206424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
207424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
208424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // We now look at the first data packet received for request_id.
209424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ResponseMetaData resp_data = (*metadata_map)[request_id];
210424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  metadata_map->erase(request_id);
211424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
212424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Record the length of the first received network packet to see if it's
213424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // enough for sniffing.
214424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  UMA_HISTOGRAM_COUNTS("SiteIsolation.XSD.DataLength", length);
215424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
216424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Record the number of cross-site document responses with a specific mime
217424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // type (text/html, text/xml, etc).
218424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION(
219424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      "SiteIsolation.XSD.MimeType",
220424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      resp_data.canonical_mime_type,
221424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      SiteIsolationPolicy::ResponseMetaData::MaxCanonicalMimeType);
222424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
223424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Store the result of cross-site document blocking analysis. True means we
224424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // can return this document to the renderer, false means that we have to block
225424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // the response data.
226424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  bool result = false;
227424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
228424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // The content is blocked if it is sniffed for HTML/JSON/XML. When the blocked
229424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // response is with an error status code, it is not disruptive by the
230424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // following reasons : 1) the blocked content is not a binary object (such as
231424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // an image) since it is sniffed for text; 2) then, this blocking only breaks
232424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // the renderer behavior only if it is either JavaScript or CSS. However, the
233424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // renderer doesn't use the contents of JS/CSS with unaffected status code
234424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // (e.g, 404). 3) the renderer is expected not to use the cross-site document
235424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // content for purposes other than JS/CSS (e.g, XHR).
236424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  bool renderable_status_code = IsRenderableStatusCodeForDocument(
237424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      resp_data.http_status_code);
238424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
239424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // This is only used for false-negative analysis for non-blocked resources.
240424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  bool is_sniffed_for_js = SniffForJS(data, length);
241424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
242424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Record the number of responses whose content is sniffed for what its mime
243424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // type claims it to be. For example, we apply a HTML sniffer for a document
244424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // tagged with text/html here. Whenever this check becomes true, we'll block
245424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // the response.
246424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  switch (resp_data.canonical_mime_type) {
247424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case SiteIsolationPolicy::ResponseMetaData::HTML:
248424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      SITE_ISOLATION_POLICY_SNIFF_AND_COUNT(SniffForHTML(data, length),
249424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                            "SiteIsolation.XSD.HTML");
250424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      break;
251424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case SiteIsolationPolicy::ResponseMetaData::XML:
252424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      SITE_ISOLATION_POLICY_SNIFF_AND_COUNT(SniffForXML(data, length),
253424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                            "SiteIsolation.XSD.XML");
254424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      break;
255424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case SiteIsolationPolicy::ResponseMetaData::JSON:
256424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      SITE_ISOLATION_POLICY_SNIFF_AND_COUNT(SniffForJSON(data, length),
257424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                            "SiteIsolation.XSD.JSON");
258424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      break;
259424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case SiteIsolationPolicy::ResponseMetaData::Plain:
260424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      if (SniffForHTML(data, length)) {
261424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        SITE_ISOLATION_POLICY_COUNT_BLOCK(
262424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            "SiteIsolation.XSD.Plain.HTML");
263424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      } else if (SniffForXML(data, length)) {
264424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        SITE_ISOLATION_POLICY_COUNT_BLOCK(
265424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            "SiteIsolation.XSD.Plain.XML");
266424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      } else if (SniffForJSON(data, length)) {
267424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        SITE_ISOLATION_POLICY_COUNT_BLOCK(
268424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)            "SiteIsolation.XSD.Plain.JSON");
269424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      } else if (is_sniffed_for_js) {
270424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        if (resp_data.no_sniff) {
271424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          SITE_ISOLATION_POLICY_COUNT_NO_SNIFF_BLOCK(
272424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)              "SiteIsolation.XSD.Plain");
273424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        } else {
274424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          SITE_ISOLATION_POLICY_COUNT_NOTBLOCK(
275424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)              "SiteIsolation.XSD.Plain");
276424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        }
277424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      }
278424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      break;
279424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    default :
280424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      NOTREACHED() <<
281424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          "Not a blockable mime type. This mime type shouldn't reach here.";
282424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      break;
283424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
284424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
285424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
286424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!command_line.HasSwitch(switches::kBlockCrossSiteDocuments))
287424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    result = false;
288424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  (*result_map)[request_id] = result;
289424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
290424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (result) {
291424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    alternative_data->erase();
292424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    alternative_data->insert(0, " ");
293424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    LOG(ERROR) << resp_data.response_url
294424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)               << " is blocked as an illegal cross-site document from "
295424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)               << resp_data.frame_origin;
296424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
297424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return result;
298424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
299424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
300424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#undef SITE_ISOLATION_POLICY_COUNT_NOTBLOCK
301424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#undef SITE_ISOLATION_POLICY_SNIFF_AND_COUNT
302424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#undef SITE_ISOLATION_POLICY_COUNT_BLOCK
303424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
304424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void SiteIsolationPolicy::OnRequestComplete(int request_id) {
30558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!g_policy_enabled)
30658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return;
307424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  RequestIdToMetaDataMap* metadata_map = GetRequestIdToMetaDataMap();
308424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  RequestIdToResultMap* result_map = GetRequestIdToResultMap();
309424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  metadata_map->erase(request_id);
310424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  result_map->erase(request_id);
311424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
312424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
313424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)SiteIsolationPolicy::ResponseMetaData::CanonicalMimeType
314424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)SiteIsolationPolicy::GetCanonicalMimeType(const std::string& mime_type) {
315424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (LowerCaseEqualsASCII(mime_type, kTextHtml)) {
316424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return SiteIsolationPolicy::ResponseMetaData::HTML;
317424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
318424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
319424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (LowerCaseEqualsASCII(mime_type, kTextPlain)) {
320424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return SiteIsolationPolicy::ResponseMetaData::Plain;
321424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
322424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
323424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (LowerCaseEqualsASCII(mime_type, kAppJson) ||
324424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      LowerCaseEqualsASCII(mime_type, kTextJson) ||
325424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      LowerCaseEqualsASCII(mime_type, kTextXjson)) {
326424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return SiteIsolationPolicy::ResponseMetaData::JSON;
327424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
328424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
329424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (LowerCaseEqualsASCII(mime_type, kTextXml) ||
330424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      LowerCaseEqualsASCII(mime_type, xAppRssXml) ||
331424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      LowerCaseEqualsASCII(mime_type, kAppXml)) {
332424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return SiteIsolationPolicy::ResponseMetaData::XML;
333424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
334424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
335424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return SiteIsolationPolicy::ResponseMetaData::Others;
336424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
337424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
338424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
339424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool SiteIsolationPolicy::IsBlockableScheme(const GURL& url) {
340424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // We exclude ftp:// from here. FTP doesn't provide a Content-Type
341424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // header which our policy depends on, so we cannot protect any
342424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // document from FTP servers.
343424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return url.SchemeIs("http") || url.SchemeIs("https");
344424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
345424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
346424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool SiteIsolationPolicy::IsSameSite(const GURL& frame_origin,
347424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                     const GURL& response_url) {
348424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
349424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!frame_origin.is_valid() || !response_url.is_valid())
350424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return false;
351424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
352424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (frame_origin.scheme() != response_url.scheme())
353424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return false;
354424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
355424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // SameDomainOrHost() extracts the effective domains (public suffix plus one)
356424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // from the two URLs and compare them.
357424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // TODO(dsjang): use INCLUDE_PRIVATE_REGISTRIES when http://crbug.com/7988 is
358424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // fixed.
359424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return net::registry_controlled_domains::SameDomainOrHost(
360424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      frame_origin,
361424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      response_url,
362424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
363424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
364424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
365424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool SiteIsolationPolicy::IsFrameNavigating(WebKit::WebFrame* frame) {
366424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // When a navigation starts, frame->provisionalDataSource() is set
367424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // to a not-null value which stands for the request made for the
368424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // navigation. As soon as the network request is committed to the
369424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // frame, frame->provisionalDataSource() is converted to null, and
370424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // the committed data source is moved to frame->dataSource(). This
371424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // is the most reliable way to detect whether the frame is in
372424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // navigation or not.
373424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return frame->provisionalDataSource() != NULL;
374424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
375424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
376424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// We don't use Webkit's existing CORS policy implementation since
377424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// their policy works in terms of origins, not sites. For example,
378424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// when frame is sub.a.com and it is not allowed to access a document
379424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// with sub1.a.com. But under Site Isolation, it's allowed.
380424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool SiteIsolationPolicy::IsValidCorsHeaderSet(
381424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    GURL& frame_origin,
382424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    GURL& website_origin,
383424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    std::string access_control_origin) {
384424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Many websites are sending back "\"*\"" instead of "*". This is
385424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // non-standard practice, and not supported by Chrome. Refer to
386424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // CrossOriginAccessControl::passesAccessControlCheck().
387424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
388424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // TODO(dsjang): * is not allowed for the response from a request
389424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // with cookies. This allows for more than what the renderer will
390424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // eventually be able to receive, so we won't see illegal cross-site
391424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // documents allowed by this. We have to find a way to see if this
392424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // response is from a cookie-tagged request or not in the future.
393424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (access_control_origin == "*")
394424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return true;
395424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
396424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // TODO(dsjang): The CORS spec only treats a fully specified URL, except for
397424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // "*", but many websites are using just a domain for access_control_origin,
398424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // and this is blocked by Webkit's CORS logic here :
399424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // CrossOriginAccessControl::passesAccessControlCheck(). GURL is set
400424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // is_valid() to false when it is created from a URL containing * in the
401424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // domain part.
402424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
403424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  GURL cors_origin(access_control_origin);
404424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return IsSameSite(frame_origin, cors_origin);
405424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
406424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
407424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// This function is a slight modification of |net::SniffForHTML|.
408424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool SiteIsolationPolicy::SniffForHTML(const char* data, size_t length) {
409424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // The content sniffer used by Chrome and Firefox are using "<!--"
410424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // as one of the HTML signatures, but it also appears in valid
411424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // JavaScript, considered as well-formed JS by the browser.  Since
412424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // we do not want to block any JS, we exclude it from our HTML
413424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // signatures. This can weaken our document block policy, but we can
414424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // break less websites.
415424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // TODO(dsjang): parameterize |net::SniffForHTML| with an option
416424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // that decides whether to include <!-- or not, so that we can
417424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // remove this function.
418424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const char* html_signatures[] = {"<!DOCTYPE html",  // HTML5 spec
419424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                   "<script",         // HTML5 spec, Mozilla
420424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                   "<html",           // HTML5 spec, Mozilla
421424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                   "<head",           // HTML5 spec, Mozilla
422424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                   "<iframe",         // Mozilla
423424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                   "<h1",             // Mozilla
424424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                   "<div",            // Mozilla
425424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                   "<font",           // Mozilla
426424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                   "<table",          // Mozilla
427424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                   "<a",              // Mozilla
428424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                   "<style",          // Mozilla
429424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                   "<title",          // Mozilla
430424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                   "<b",              // Mozilla
431424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                   "<body",           // Mozilla
432424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                   "<br", "<p",       // Mozilla
433424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                   "<?xml"            // Mozilla
434424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  };
435424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
436424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (MatchesSignature(
437424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          data, length, html_signatures, arraysize(html_signatures)))
438424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return true;
439424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
440424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // "<!--" is specially treated since web JS can use "<!--" "-->" pair for
441424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // comments.
442424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  static const char* comment_begins[] = {"<!--"};
443424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
444424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (MatchesSignature(
445424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          data, length, comment_begins, arraysize(comment_begins))) {
446424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // Search for --> and do SniffForHTML after that. If we can find the
447424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // comment's end, we start HTML sniffing from there again.
448424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    static const char end_comment[] = "-->";
449424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    base::StringPiece data_as_stringpiece(data, length);
450424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
451424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    size_t offset = data_as_stringpiece.find(end_comment);
452424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (offset != base::StringPiece::npos) {
453424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      size_t new_start_offset = offset + strlen(end_comment);
454424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      if (new_start_offset < length) {
455424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        return SniffForHTML(data + new_start_offset,
456424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                            length - new_start_offset);
457424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      }
458424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
459424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
460424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
461424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return false;
462424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
463424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
464424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool SiteIsolationPolicy::SniffForXML(const char* data, size_t length) {
465424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // TODO(dsjang): Chrome's mime_sniffer is using strncasecmp() for
466424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // this signature. However, XML is case-sensitive. Don't we have to
467424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // be more lenient only to block documents starting with the exact
468424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // string <?xml rather than <?XML ?
469424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const char* xml_signatures[] = {"<?xml"  // Mozilla
470424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  };
471424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return MatchesSignature(
472424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      data, length, xml_signatures, arraysize(xml_signatures));
473424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
474424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
475424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool SiteIsolationPolicy::SniffForJSON(const char* data, size_t length) {
476424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // TODO(dsjang): We have to come up with a better way to sniff
477424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // JSON. However, even RE cannot help us that much due to the fact
478424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // that we don't do full parsing.  This DFA starts with state 0, and
479424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // finds {, "/' and : in that order. We're avoiding adding a
480424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // dependency on a regular expression library.
481424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const int kInitState = 0;
482424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const int kLeftBraceState = 1;
483424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const int kLeftQuoteState = 2;
484424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const int kColonState = 3;
485424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const int kDeadState = 4;
486424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
487424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  int state = kInitState;
488424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  for (size_t i = 0; i < length && state < kColonState; ++i) {
489424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const char c = data[i];
490424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
491424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      continue;
492424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
493424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    switch (state) {
494424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      case kInitState:
495424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        if (c == '{')
496424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          state = kLeftBraceState;
497424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        else
498424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          state = kDeadState;
499424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        break;
500424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      case kLeftBraceState:
501424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        if (c == '\"' || c == '\'')
502424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          state = kLeftQuoteState;
503424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        else
504424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          state = kDeadState;
505424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        break;
506424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      case kLeftQuoteState:
507424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        if (c == ':')
508424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          state = kColonState;
509424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        break;
510424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      default:
511424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        NOTREACHED();
512424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        break;
513424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
514424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
515424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return state == kColonState;
516424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
517424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
518424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool SiteIsolationPolicy::MatchesSignature(const char* raw_data,
519424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                           size_t raw_length,
520424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                           const char* signatures[],
521424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                           size_t arr_size) {
522424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  size_t start = 0;
523424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Skip white characters at the beginning of the document.
524424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  for (start = 0; start < raw_length; ++start) {
525424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    char c = raw_data[start];
526424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (!(c == ' ' || c == '\t' || c == '\r' || c == '\n'))
527424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      break;
528424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
529424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
530424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // There is no not-whitespace character in this document.
531424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!(start < raw_length))
532424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return false;
533424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
534424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const char* data = raw_data + start;
535424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  size_t length = raw_length - start;
536424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
537424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  for (size_t sig_index = 0; sig_index < arr_size; ++sig_index) {
538424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const char* signature = signatures[sig_index];
539424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    size_t signature_length = strlen(signature);
540424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
541424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (length < signature_length)
542424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      continue;
543424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
544424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (!base::strncasecmp(signature, data, signature_length))
545424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      return true;
546424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
547424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return false;
548424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
549424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
550424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool SiteIsolationPolicy::IsRenderableStatusCodeForDocument(int status_code) {
551424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Chrome only uses the content of a response with one of these status codes
552424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // for CSS/JavaScript. For images, Chrome just ignores status code.
553424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const int renderable_status_code[] = {200, 201, 202, 203, 206, 300, 301, 302,
554424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                                        303, 305, 306, 307};
555424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  for (size_t i = 0; i < arraysize(renderable_status_code); ++i) {
556424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (renderable_status_code[i] == status_code)
557424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      return true;
558424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
559424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return false;
560424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
561424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
562424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)bool SiteIsolationPolicy::SniffForJS(const char* data, size_t length) {
563424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // TODO(dsjang): This is a real hack. The only purpose of this function is to
564424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // try to see if there's any possibility that this data can be JavaScript
565424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // (superset of JS). This function will be removed once UMA stats are
566424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // gathered.
567424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
568424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Search for "var " for JS detection.
569424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return base::StringPiece(data, length).find("var ") !=
570424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    base::StringPiece::npos;
571424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
572424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
573424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)SiteIsolationPolicy::RequestIdToMetaDataMap*
574424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)SiteIsolationPolicy::GetRequestIdToMetaDataMap() {
575424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  CR_DEFINE_STATIC_LOCAL(RequestIdToMetaDataMap, metadata_map_, ());
576424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return &metadata_map_;
577424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
578424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
579424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)SiteIsolationPolicy::RequestIdToResultMap*
580424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)SiteIsolationPolicy::GetRequestIdToResultMap() {
581424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  CR_DEFINE_STATIC_LOCAL(RequestIdToResultMap, result_map_, ());
582424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return &result_map_;
583424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
584424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
585424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}  // namespace content
586