summaryrefslogtreecommitdiffstats
path: root/chromium/content/child/site_isolation_policy.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/content/child/site_isolation_policy.cc')
-rw-r--r--chromium/content/child/site_isolation_policy.cc171
1 files changed, 53 insertions, 118 deletions
diff --git a/chromium/content/child/site_isolation_policy.cc b/chromium/content/child/site_isolation_policy.cc
index e98d744194d..026f625a1d4 100644
--- a/chromium/content/child/site_isolation_policy.cc
+++ b/chromium/content/child/site_isolation_policy.cc
@@ -9,45 +9,18 @@
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
-#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
-#include "content/child/child_thread.h"
#include "content/public/common/content_switches.h"
+#include "content/public/common/resource_response_info.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/http/http_response_headers.h"
-#include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/platform/WebURL.h"
-#include "third_party/WebKit/public/platform/WebURLRequest.h"
-#include "third_party/WebKit/public/platform/WebURLResponse.h"
-#include "third_party/WebKit/public/web/WebDocument.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
-#include "third_party/WebKit/public/web/WebFrameClient.h"
-#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
using base::StringPiece;
-using blink::WebDocument;
-using blink::WebString;
-using blink::WebURL;
-using blink::WebURLResponse;
-using blink::WebURLRequest;
namespace content {
namespace {
-// Maintain the bookkeeping data between OnReceivedResponse and
-// OnReceivedData. The key is a request id maintained by ResourceDispatcher.
-static base::LazyInstance<SiteIsolationPolicy::RequestIdToMetaDataMap>
- g_metadata_map = LAZY_INSTANCE_INITIALIZER;
-
-// Maintain the bookkeeping data for OnReceivedData. Blocking decision is made
-// when OnReceivedData is called for the first time for a request, and the
-// decision will remain the same for following data. This map maintains the
-// decision. The key is a request id maintained by ResourceDispatcher.
-static base::LazyInstance<SiteIsolationPolicy::RequestIdToResultMap>
- g_result_map = LAZY_INSTANCE_INITIALIZER;
-
// The cross-site document blocking/UMA data collection is deactivated by
// default, and only activated in renderer processes.
static bool g_policy_enabled = false;
@@ -123,7 +96,7 @@ void IncrementHistogramEnum(const std::string& name,
void HistogramCountBlockedResponse(
const std::string& bucket_prefix,
- const SiteIsolationPolicy::ResponseMetaData& resp_data,
+ linked_ptr<SiteIsolationResponseMetaData>& resp_data,
bool nosniff_block) {
std::string block_label(nosniff_block ? ".NoSniffBlocked" : ".Blocked");
IncrementHistogramCount(bucket_prefix + block_label);
@@ -138,12 +111,12 @@ void HistogramCountBlockedResponse(
// (e.g, 404). 3) the renderer is expected not to use the cross-site
// document content for purposes other than JS/CSS (e.g, XHR).
bool renderable_status_code =
- IsRenderableStatusCode(resp_data.http_status_code);
+ IsRenderableStatusCode(resp_data->http_status_code);
if (renderable_status_code) {
IncrementHistogramEnum(
bucket_prefix + block_label + ".RenderableStatusCode",
- resp_data.resource_type,
+ resp_data->resource_type,
ResourceType::LAST_TYPE);
} else {
IncrementHistogramCount(bucket_prefix + block_label +
@@ -160,21 +133,20 @@ void HistogramCountNotBlockedResponse(const std::string& bucket_prefix,
} // namespace
-SiteIsolationPolicy::ResponseMetaData::ResponseMetaData() {}
+SiteIsolationResponseMetaData::SiteIsolationResponseMetaData() {}
void SiteIsolationPolicy::SetPolicyEnabled(bool enabled) {
g_policy_enabled = enabled;
}
-void SiteIsolationPolicy::OnReceivedResponse(
- int request_id,
- const GURL& frame_origin,
- const GURL& response_url,
- ResourceType::Type resource_type,
- int origin_pid,
- const webkit_glue::ResourceResponseInfo& info) {
+linked_ptr<SiteIsolationResponseMetaData>
+SiteIsolationPolicy::OnReceivedResponse(const GURL& frame_origin,
+ const GURL& response_url,
+ ResourceType::Type resource_type,
+ int origin_pid,
+ const ResourceResponseInfo& info) {
if (!g_policy_enabled)
- return;
+ return linked_ptr<SiteIsolationResponseMetaData>();
// if |origin_pid| is non-zero, it means that this response is for a plugin
// spawned from this renderer process. We exclude responses for plugins for
@@ -182,26 +154,26 @@ void SiteIsolationPolicy::OnReceivedResponse(
// the browser process so that we don't apply cross-site document blocking to
// them.
if (origin_pid)
- return;
+ return linked_ptr<SiteIsolationResponseMetaData>();
UMA_HISTOGRAM_COUNTS("SiteIsolation.AllResponses", 1);
// See if this is for navigation. If it is, don't block it, under the
// assumption that we will put it in an appropriate process.
if (ResourceType::IsFrame(resource_type))
- return;
+ return linked_ptr<SiteIsolationResponseMetaData>();
if (!IsBlockableScheme(response_url))
- return;
+ return linked_ptr<SiteIsolationResponseMetaData>();
if (IsSameSite(frame_origin, response_url))
- return;
+ return linked_ptr<SiteIsolationResponseMetaData>();
- SiteIsolationPolicy::ResponseMetaData::CanonicalMimeType canonical_mime_type =
+ SiteIsolationResponseMetaData::CanonicalMimeType canonical_mime_type =
GetCanonicalMimeType(info.mime_type);
- if (canonical_mime_type == SiteIsolationPolicy::ResponseMetaData::Others)
- return;
+ if (canonical_mime_type == SiteIsolationResponseMetaData::Others)
+ return linked_ptr<SiteIsolationResponseMetaData>();
// Every CORS request should have the Access-Control-Allow-Origin header even
// if it is preceded by a pre-flight request. Therefore, if this is a CORS
@@ -213,63 +185,36 @@ void SiteIsolationPolicy::OnReceivedResponse(
info.headers->EnumerateHeader(
NULL, "access-control-allow-origin", &access_control_origin);
if (IsValidCorsHeaderSet(frame_origin, response_url, access_control_origin))
- return;
+ return linked_ptr<SiteIsolationResponseMetaData>();
// Real XSD data collection starts from here.
std::string no_sniff;
info.headers->EnumerateHeader(NULL, "x-content-type-options", &no_sniff);
- ResponseMetaData resp_data;
- resp_data.frame_origin = frame_origin.spec();
- resp_data.response_url = response_url;
- resp_data.resource_type = resource_type;
- resp_data.canonical_mime_type = canonical_mime_type;
- resp_data.http_status_code = info.headers->response_code();
- resp_data.no_sniff = LowerCaseEqualsASCII(no_sniff, "nosniff");
+ linked_ptr<SiteIsolationResponseMetaData> resp_data(
+ new SiteIsolationResponseMetaData);
+ resp_data->frame_origin = frame_origin.spec();
+ resp_data->response_url = response_url;
+ resp_data->resource_type = resource_type;
+ resp_data->canonical_mime_type = canonical_mime_type;
+ resp_data->http_status_code = info.headers->response_code();
+ resp_data->no_sniff = LowerCaseEqualsASCII(no_sniff, "nosniff");
- (g_metadata_map.Get())[request_id] = resp_data;
+ return resp_data;
}
bool SiteIsolationPolicy::ShouldBlockResponse(
- int request_id,
+ linked_ptr<SiteIsolationResponseMetaData>& resp_data,
const char* raw_data,
int raw_length,
std::string* alternative_data) {
if (!g_policy_enabled)
return false;
- RequestIdToMetaDataMap& metadata_map = g_metadata_map.Get();
- RequestIdToResultMap& result_map = g_result_map.Get();
-
- // If there's an entry for |request_id| in blocked_map, this request's first
- // data packet has already been examined. We can return the result here.
- if (result_map.count(request_id) != 0) {
- if (result_map[request_id]) {
- // Here, the blocking result has been set for the previous run of
- // ShouldBlockResponse(), so we set alternative data to an empty string so
- // that ResourceDispatcher doesn't call its peer's onReceivedData() with
- // the alternative data.
- alternative_data->erase();
- return true;
- }
- return false;
- }
-
- // If result_map doesn't have an entry for |request_id|, we're receiving the
- // first data packet for request_id. If request_id is not registered, this
- // request is identified as a non-target of our policy. So we return true.
- if (metadata_map.count(request_id) == 0) {
- // We set request_id to true so that we always return true for this request.
- result_map[request_id] = false;
- return false;
- }
+ DCHECK(resp_data.get());
StringPiece data(raw_data, raw_length);
- // We now look at the first data packet received for request_id.
- ResponseMetaData resp_data = metadata_map[request_id];
- metadata_map.erase(request_id);
-
// Record the length of the first received network packet to see if it's
// enough for sniffing.
UMA_HISTOGRAM_COUNTS("SiteIsolation.XSD.DataLength", raw_length);
@@ -278,8 +223,8 @@ bool SiteIsolationPolicy::ShouldBlockResponse(
// type (text/html, text/xml, etc).
UMA_HISTOGRAM_ENUMERATION(
"SiteIsolation.XSD.MimeType",
- resp_data.canonical_mime_type,
- SiteIsolationPolicy::ResponseMetaData::MaxCanonicalMimeType);
+ resp_data->canonical_mime_type,
+ SiteIsolationResponseMetaData::MaxCanonicalMimeType);
// Store the result of cross-site document blocking analysis.
bool is_blocked = false;
@@ -289,32 +234,32 @@ bool SiteIsolationPolicy::ShouldBlockResponse(
// type claims it to be. For example, we apply a HTML sniffer for a document
// tagged with text/html here. Whenever this check becomes true, we'll block
// the response.
- if (resp_data.canonical_mime_type !=
- SiteIsolationPolicy::ResponseMetaData::Plain) {
+ if (resp_data->canonical_mime_type !=
+ SiteIsolationResponseMetaData::Plain) {
std::string bucket_prefix;
bool sniffed_as_target_document = false;
- if (resp_data.canonical_mime_type ==
- SiteIsolationPolicy::ResponseMetaData::HTML) {
+ if (resp_data->canonical_mime_type ==
+ SiteIsolationResponseMetaData::HTML) {
bucket_prefix = "SiteIsolation.XSD.HTML";
sniffed_as_target_document = SniffForHTML(data);
- } else if (resp_data.canonical_mime_type ==
- SiteIsolationPolicy::ResponseMetaData::XML) {
+ } else if (resp_data->canonical_mime_type ==
+ SiteIsolationResponseMetaData::XML) {
bucket_prefix = "SiteIsolation.XSD.XML";
sniffed_as_target_document = SniffForXML(data);
- } else if (resp_data.canonical_mime_type ==
- SiteIsolationPolicy::ResponseMetaData::JSON) {
+ } else if (resp_data->canonical_mime_type ==
+ SiteIsolationResponseMetaData::JSON) {
bucket_prefix = "SiteIsolation.XSD.JSON";
sniffed_as_target_document = SniffForJSON(data);
} else {
NOTREACHED() << "Not a blockable mime type: "
- << resp_data.canonical_mime_type;
+ << resp_data->canonical_mime_type;
}
if (sniffed_as_target_document) {
is_blocked = true;
HistogramCountBlockedResponse(bucket_prefix, resp_data, false);
} else {
- if (resp_data.no_sniff) {
+ if (resp_data->no_sniff) {
is_blocked = true;
HistogramCountBlockedResponse(bucket_prefix, resp_data, true);
} else {
@@ -336,7 +281,7 @@ bool SiteIsolationPolicy::ShouldBlockResponse(
if (bucket_prefix.size() > 0) {
is_blocked = true;
HistogramCountBlockedResponse(bucket_prefix, resp_data, false);
- } else if (resp_data.no_sniff) {
+ } else if (resp_data->no_sniff) {
is_blocked = true;
HistogramCountBlockedResponse("SiteIsolation.XSD.Plain", resp_data, true);
} else {
@@ -348,48 +293,40 @@ bool SiteIsolationPolicy::ShouldBlockResponse(
if (!CommandLine::ForCurrentProcess()->HasSwitch(
switches::kBlockCrossSiteDocuments))
is_blocked = false;
- result_map[request_id] = is_blocked;
if (is_blocked) {
alternative_data->erase();
alternative_data->insert(0, " ");
- LOG(ERROR) << resp_data.response_url
+ LOG(ERROR) << resp_data->response_url
<< " is blocked as an illegal cross-site document from "
- << resp_data.frame_origin;
+ << resp_data->frame_origin;
}
return is_blocked;
}
-void SiteIsolationPolicy::OnRequestComplete(int request_id) {
- if (!g_policy_enabled)
- return;
- g_metadata_map.Get().erase(request_id);
- g_result_map.Get().erase(request_id);
-}
-
-SiteIsolationPolicy::ResponseMetaData::CanonicalMimeType
+SiteIsolationResponseMetaData::CanonicalMimeType
SiteIsolationPolicy::GetCanonicalMimeType(const std::string& mime_type) {
if (LowerCaseEqualsASCII(mime_type, kTextHtml)) {
- return SiteIsolationPolicy::ResponseMetaData::HTML;
+ return SiteIsolationResponseMetaData::HTML;
}
if (LowerCaseEqualsASCII(mime_type, kTextPlain)) {
- return SiteIsolationPolicy::ResponseMetaData::Plain;
+ return SiteIsolationResponseMetaData::Plain;
}
if (LowerCaseEqualsASCII(mime_type, kAppJson) ||
LowerCaseEqualsASCII(mime_type, kTextJson) ||
LowerCaseEqualsASCII(mime_type, kTextXjson)) {
- return SiteIsolationPolicy::ResponseMetaData::JSON;
+ return SiteIsolationResponseMetaData::JSON;
}
if (LowerCaseEqualsASCII(mime_type, kTextXml) ||
LowerCaseEqualsASCII(mime_type, xAppRssXml) ||
LowerCaseEqualsASCII(mime_type, kAppXml)) {
- return SiteIsolationPolicy::ResponseMetaData::XML;
+ return SiteIsolationResponseMetaData::XML;
}
- return SiteIsolationPolicy::ResponseMetaData::Others;
+ return SiteIsolationResponseMetaData::Others;
}
bool SiteIsolationPolicy::IsBlockableScheme(const GURL& url) {
@@ -410,12 +347,10 @@ bool SiteIsolationPolicy::IsSameSite(const GURL& frame_origin,
// SameDomainOrHost() extracts the effective domains (public suffix plus one)
// from the two URLs and compare them.
- // TODO(dsjang): use INCLUDE_PRIVATE_REGISTRIES when http://crbug.com/7988 is
- // fixed.
return net::registry_controlled_domains::SameDomainOrHost(
frame_origin,
response_url,
- net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
+ net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
}
// We don't use Webkit's existing CORS policy implementation since