| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/child/site_isolation_stats_gatherer.h" | 5 #include "content/child/site_isolation_stats_gatherer.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 | 9 |
| 10 #include "base/macros.h" | 10 #include "base/macros.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 uint32_t boundary_value) { | 46 uint32_t boundary_value) { |
| 47 // The default value of min, max, bucket_count are copied from histogram.h. | 47 // The default value of min, max, bucket_count are copied from histogram.h. |
| 48 base::HistogramBase* histogram_pointer = base::LinearHistogram::FactoryGet( | 48 base::HistogramBase* histogram_pointer = base::LinearHistogram::FactoryGet( |
| 49 name, 1, boundary_value, boundary_value + 1, | 49 name, 1, boundary_value, boundary_value + 1, |
| 50 base::HistogramBase::kUmaTargetedHistogramFlag); | 50 base::HistogramBase::kUmaTargetedHistogramFlag); |
| 51 histogram_pointer->Add(sample); | 51 histogram_pointer->Add(sample); |
| 52 } | 52 } |
| 53 | 53 |
| 54 void HistogramCountBlockedResponse( | 54 void HistogramCountBlockedResponse( |
| 55 const std::string& bucket_prefix, | 55 const std::string& bucket_prefix, |
| 56 const linked_ptr<SiteIsolationResponseMetaData>& resp_data, | 56 const scoped_ptr<SiteIsolationResponseMetaData>& resp_data, |
| 57 bool nosniff_block) { | 57 bool nosniff_block) { |
| 58 std::string block_label(nosniff_block ? ".NoSniffBlocked" : ".Blocked"); | 58 std::string block_label(nosniff_block ? ".NoSniffBlocked" : ".Blocked"); |
| 59 IncrementHistogramCount(bucket_prefix + block_label); | 59 IncrementHistogramCount(bucket_prefix + block_label); |
| 60 | 60 |
| 61 // The content is blocked if it is sniffed as HTML/JSON/XML. When | 61 // The content is blocked if it is sniffed as HTML/JSON/XML. When |
| 62 // the blocked response is with an error status code, it is not | 62 // the blocked response is with an error status code, it is not |
| 63 // disruptive for the following reasons : 1) the blocked content is | 63 // disruptive for the following reasons : 1) the blocked content is |
| 64 // not a binary object (such as an image) since it is sniffed as | 64 // not a binary object (such as an image) since it is sniffed as |
| 65 // text; 2) then, this blocking only breaks the renderer behavior | 65 // text; 2) then, this blocking only breaks the renderer behavior |
| 66 // only if it is either JavaScript or CSS. However, the renderer | 66 // only if it is either JavaScript or CSS. However, the renderer |
| (...skipping 22 matching lines...) Expand all Loading... |
| 89 | 89 |
| 90 } // namespace | 90 } // namespace |
| 91 | 91 |
| 92 SiteIsolationResponseMetaData::SiteIsolationResponseMetaData() { | 92 SiteIsolationResponseMetaData::SiteIsolationResponseMetaData() { |
| 93 } | 93 } |
| 94 | 94 |
| 95 void SiteIsolationStatsGatherer::SetEnabled(bool enabled) { | 95 void SiteIsolationStatsGatherer::SetEnabled(bool enabled) { |
| 96 g_stats_gathering_enabled = enabled; | 96 g_stats_gathering_enabled = enabled; |
| 97 } | 97 } |
| 98 | 98 |
| 99 linked_ptr<SiteIsolationResponseMetaData> | 99 scoped_ptr<SiteIsolationResponseMetaData> |
| 100 SiteIsolationStatsGatherer::OnReceivedResponse( | 100 SiteIsolationStatsGatherer::OnReceivedResponse( |
| 101 const GURL& frame_origin, | 101 const GURL& frame_origin, |
| 102 const GURL& response_url, | 102 const GURL& response_url, |
| 103 ResourceType resource_type, | 103 ResourceType resource_type, |
| 104 int origin_pid, | 104 int origin_pid, |
| 105 const ResourceResponseInfo& info) { | 105 const ResourceResponseInfo& info) { |
| 106 if (!g_stats_gathering_enabled) | 106 if (!g_stats_gathering_enabled) |
| 107 return linked_ptr<SiteIsolationResponseMetaData>(); | 107 return nullptr; |
| 108 | 108 |
| 109 // if |origin_pid| is non-zero, it means that this response is for a plugin | 109 // if |origin_pid| is non-zero, it means that this response is for a plugin |
| 110 // spawned from this renderer process. We exclude responses for plugins for | 110 // spawned from this renderer process. We exclude responses for plugins for |
| 111 // now, but eventually, we're going to make plugin processes directly talk to | 111 // now, but eventually, we're going to make plugin processes directly talk to |
| 112 // the browser process so that we don't apply cross-site document blocking to | 112 // the browser process so that we don't apply cross-site document blocking to |
| 113 // them. | 113 // them. |
| 114 if (origin_pid) | 114 if (origin_pid) |
| 115 return linked_ptr<SiteIsolationResponseMetaData>(); | 115 return nullptr; |
| 116 | 116 |
| 117 UMA_HISTOGRAM_COUNTS("SiteIsolation.AllResponses", 1); | 117 UMA_HISTOGRAM_COUNTS("SiteIsolation.AllResponses", 1); |
| 118 | 118 |
| 119 // See if this is for navigation. If it is, don't block it, under the | 119 // See if this is for navigation. If it is, don't block it, under the |
| 120 // assumption that we will put it in an appropriate process. | 120 // assumption that we will put it in an appropriate process. |
| 121 if (IsResourceTypeFrame(resource_type)) | 121 if (IsResourceTypeFrame(resource_type)) |
| 122 return linked_ptr<SiteIsolationResponseMetaData>(); | 122 return nullptr; |
| 123 | 123 |
| 124 if (!CrossSiteDocumentClassifier::IsBlockableScheme(response_url)) | 124 if (!CrossSiteDocumentClassifier::IsBlockableScheme(response_url)) |
| 125 return linked_ptr<SiteIsolationResponseMetaData>(); | 125 return nullptr; |
| 126 | 126 |
| 127 if (CrossSiteDocumentClassifier::IsSameSite(frame_origin, response_url)) | 127 if (CrossSiteDocumentClassifier::IsSameSite(frame_origin, response_url)) |
| 128 return linked_ptr<SiteIsolationResponseMetaData>(); | 128 return nullptr; |
| 129 | 129 |
| 130 CrossSiteDocumentMimeType canonical_mime_type = | 130 CrossSiteDocumentMimeType canonical_mime_type = |
| 131 CrossSiteDocumentClassifier::GetCanonicalMimeType(info.mime_type); | 131 CrossSiteDocumentClassifier::GetCanonicalMimeType(info.mime_type); |
| 132 | 132 |
| 133 if (canonical_mime_type == CROSS_SITE_DOCUMENT_MIME_TYPE_OTHERS) | 133 if (canonical_mime_type == CROSS_SITE_DOCUMENT_MIME_TYPE_OTHERS) |
| 134 return linked_ptr<SiteIsolationResponseMetaData>(); | 134 return nullptr; |
| 135 | 135 |
| 136 // Every CORS request should have the Access-Control-Allow-Origin header even | 136 // Every CORS request should have the Access-Control-Allow-Origin header even |
| 137 // if it is preceded by a pre-flight request. Therefore, if this is a CORS | 137 // if it is preceded by a pre-flight request. Therefore, if this is a CORS |
| 138 // request, it has this header. response.httpHeaderField() internally uses | 138 // request, it has this header. response.httpHeaderField() internally uses |
| 139 // case-insensitive matching for the header name. | 139 // case-insensitive matching for the header name. |
| 140 std::string access_control_origin; | 140 std::string access_control_origin; |
| 141 | 141 |
| 142 // We can use a case-insensitive header name for EnumerateHeader(). | 142 // We can use a case-insensitive header name for EnumerateHeader(). |
| 143 info.headers->EnumerateHeader(NULL, "access-control-allow-origin", | 143 info.headers->EnumerateHeader(NULL, "access-control-allow-origin", |
| 144 &access_control_origin); | 144 &access_control_origin); |
| 145 if (CrossSiteDocumentClassifier::IsValidCorsHeaderSet( | 145 if (CrossSiteDocumentClassifier::IsValidCorsHeaderSet( |
| 146 frame_origin, response_url, access_control_origin)) | 146 frame_origin, response_url, access_control_origin)) |
| 147 return linked_ptr<SiteIsolationResponseMetaData>(); | 147 return nullptr; |
| 148 | 148 |
| 149 // Real XSD data collection starts from here. | 149 // Real XSD data collection starts from here. |
| 150 std::string no_sniff; | 150 std::string no_sniff; |
| 151 info.headers->EnumerateHeader(NULL, "x-content-type-options", &no_sniff); | 151 info.headers->EnumerateHeader(NULL, "x-content-type-options", &no_sniff); |
| 152 | 152 |
| 153 linked_ptr<SiteIsolationResponseMetaData> resp_data( | 153 scoped_ptr<SiteIsolationResponseMetaData> resp_data( |
| 154 new SiteIsolationResponseMetaData); | 154 new SiteIsolationResponseMetaData); |
| 155 resp_data->frame_origin = frame_origin.spec(); | 155 resp_data->frame_origin = frame_origin.spec(); |
| 156 resp_data->response_url = response_url; | 156 resp_data->response_url = response_url; |
| 157 resp_data->resource_type = resource_type; | 157 resp_data->resource_type = resource_type; |
| 158 resp_data->canonical_mime_type = canonical_mime_type; | 158 resp_data->canonical_mime_type = canonical_mime_type; |
| 159 resp_data->http_status_code = info.headers->response_code(); | 159 resp_data->http_status_code = info.headers->response_code(); |
| 160 resp_data->no_sniff = base::LowerCaseEqualsASCII(no_sniff, "nosniff"); | 160 resp_data->no_sniff = base::LowerCaseEqualsASCII(no_sniff, "nosniff"); |
| 161 | 161 |
| 162 return resp_data; | 162 return resp_data; |
| 163 } | 163 } |
| 164 | 164 |
| 165 bool SiteIsolationStatsGatherer::OnReceivedFirstChunk( | 165 bool SiteIsolationStatsGatherer::OnReceivedFirstChunk( |
| 166 const linked_ptr<SiteIsolationResponseMetaData>& resp_data, | 166 const scoped_ptr<SiteIsolationResponseMetaData>& resp_data, |
| 167 const char* raw_data, | 167 const char* raw_data, |
| 168 int raw_length) { | 168 int raw_length) { |
| 169 if (!g_stats_gathering_enabled) | 169 if (!g_stats_gathering_enabled) |
| 170 return false; | 170 return false; |
| 171 | 171 |
| 172 DCHECK(resp_data.get()); | 172 DCHECK(resp_data.get()); |
| 173 | 173 |
| 174 base::StringPiece data(raw_data, raw_length); | 174 base::StringPiece data(raw_data, raw_length); |
| 175 | 175 |
| 176 // Record the length of the first received chunk of data to see if it's enough | 176 // Record the length of the first received chunk of data to see if it's enough |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 } | 252 } |
| 253 | 253 |
| 254 bool SiteIsolationStatsGatherer::SniffForJS(base::StringPiece data) { | 254 bool SiteIsolationStatsGatherer::SniffForJS(base::StringPiece data) { |
| 255 // The purpose of this function is to try to see if there's any possibility | 255 // The purpose of this function is to try to see if there's any possibility |
| 256 // that this data can be JavaScript (superset of JS). Search for "var " for JS | 256 // that this data can be JavaScript (superset of JS). Search for "var " for JS |
| 257 // detection. This is a real hack and should only be used for stats gathering. | 257 // detection. This is a real hack and should only be used for stats gathering. |
| 258 return data.find("var ") != base::StringPiece::npos; | 258 return data.find("var ") != base::StringPiece::npos; |
| 259 } | 259 } |
| 260 | 260 |
| 261 } // namespace content | 261 } // namespace content |
| OLD | NEW |