| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "net/url_request/url_request_http_job.h" | 5 #include "net/url_request/url_request_http_job.h" |
| 6 | 6 |
| 7 #include "base/base_switches.h" | 7 #include "base/base_switches.h" |
| 8 #include "base/bind.h" | 8 #include "base/bind.h" |
| 9 #include "base/bind_helpers.h" | 9 #include "base/bind_helpers.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 #include "net/base/load_flags.h" | 26 #include "net/base/load_flags.h" |
| 27 #include "net/base/net_errors.h" | 27 #include "net/base/net_errors.h" |
| 28 #include "net/base/network_delegate.h" | 28 #include "net/base/network_delegate.h" |
| 29 #include "net/base/network_quality_estimator.h" | 29 #include "net/base/network_quality_estimator.h" |
| 30 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" | 30 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" |
| 31 #include "net/base/sdch_manager.h" | 31 #include "net/base/sdch_manager.h" |
| 32 #include "net/base/sdch_net_log_params.h" | 32 #include "net/base/sdch_net_log_params.h" |
| 33 #include "net/base/url_util.h" | 33 #include "net/base/url_util.h" |
| 34 #include "net/cert/cert_status_flags.h" | 34 #include "net/cert/cert_status_flags.h" |
| 35 #include "net/cookies/cookie_store.h" | 35 #include "net/cookies/cookie_store.h" |
| 36 #include "net/filter/stream_source_util.h" |
| 36 #include "net/http/http_content_disposition.h" | 37 #include "net/http/http_content_disposition.h" |
| 37 #include "net/http/http_network_session.h" | 38 #include "net/http/http_network_session.h" |
| 38 #include "net/http/http_request_headers.h" | 39 #include "net/http/http_request_headers.h" |
| 39 #include "net/http/http_response_headers.h" | 40 #include "net/http/http_response_headers.h" |
| 40 #include "net/http/http_response_info.h" | 41 #include "net/http/http_response_info.h" |
| 41 #include "net/http/http_status_code.h" | 42 #include "net/http/http_status_code.h" |
| 42 #include "net/http/http_transaction.h" | 43 #include "net/http/http_transaction.h" |
| 43 #include "net/http/http_transaction_factory.h" | 44 #include "net/http/http_transaction_factory.h" |
| 44 #include "net/http/http_util.h" | 45 #include "net/http/http_util.h" |
| 45 #include "net/proxy/proxy_info.h" | 46 #include "net/proxy/proxy_info.h" |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 ephemerality = PERSISTENT_MISMATCH; | 155 ephemerality = PERSISTENT_MISMATCH; |
| 155 } | 156 } |
| 156 UMA_HISTOGRAM_ENUMERATION("Net.TokenBinding.StoreEphemerality", ephemerality, | 157 UMA_HISTOGRAM_ENUMERATION("Net.TokenBinding.StoreEphemerality", ephemerality, |
| 157 EPHEMERALITY_MAX); | 158 EPHEMERALITY_MAX); |
| 158 } | 159 } |
| 159 | 160 |
| 160 } // namespace | 161 } // namespace |
| 161 | 162 |
| 162 namespace net { | 163 namespace net { |
| 163 | 164 |
| 164 class URLRequestHttpJob::HttpFilterContext : public FilterContext { | |
| 165 public: | |
| 166 explicit HttpFilterContext(URLRequestHttpJob* job); | |
| 167 ~HttpFilterContext() override; | |
| 168 | |
| 169 // FilterContext implementation. | |
| 170 bool GetMimeType(std::string* mime_type) const override; | |
| 171 bool GetURL(GURL* gurl) const override; | |
| 172 base::Time GetRequestTime() const override; | |
| 173 bool IsCachedContent() const override; | |
| 174 SdchManager::DictionarySet* SdchDictionariesAdvertised() const override; | |
| 175 int64_t GetByteReadCount() const override; | |
| 176 int GetResponseCode() const override; | |
| 177 const URLRequestContext* GetURLRequestContext() const override; | |
| 178 void RecordPacketStats(StatisticSelector statistic) const override; | |
| 179 const BoundNetLog& GetNetLog() const override; | |
| 180 | |
| 181 private: | |
| 182 URLRequestHttpJob* job_; | |
| 183 | |
| 184 // URLRequestHttpJob may be detached from URLRequest, but we still need to | |
| 185 // return something. | |
| 186 BoundNetLog dummy_log_; | |
| 187 | |
| 188 DISALLOW_COPY_AND_ASSIGN(HttpFilterContext); | |
| 189 }; | |
| 190 | |
| 191 URLRequestHttpJob::HttpFilterContext::HttpFilterContext(URLRequestHttpJob* job) | |
| 192 : job_(job) { | |
| 193 DCHECK(job_); | |
| 194 } | |
| 195 | |
| 196 URLRequestHttpJob::HttpFilterContext::~HttpFilterContext() { | |
| 197 } | |
| 198 | |
| 199 bool URLRequestHttpJob::HttpFilterContext::GetMimeType( | |
| 200 std::string* mime_type) const { | |
| 201 return job_->GetMimeType(mime_type); | |
| 202 } | |
| 203 | |
| 204 bool URLRequestHttpJob::HttpFilterContext::GetURL(GURL* gurl) const { | |
| 205 if (!job_->request()) | |
| 206 return false; | |
| 207 *gurl = job_->request()->url(); | |
| 208 return true; | |
| 209 } | |
| 210 | |
| 211 base::Time URLRequestHttpJob::HttpFilterContext::GetRequestTime() const { | |
| 212 return job_->request() ? job_->request()->request_time() : base::Time(); | |
| 213 } | |
| 214 | |
| 215 bool URLRequestHttpJob::HttpFilterContext::IsCachedContent() const { | |
| 216 return job_->is_cached_content_; | |
| 217 } | |
| 218 | |
| 219 SdchManager::DictionarySet* | |
| 220 URLRequestHttpJob::HttpFilterContext::SdchDictionariesAdvertised() const { | |
| 221 return job_->dictionaries_advertised_.get(); | |
| 222 } | |
| 223 | |
| 224 int64_t URLRequestHttpJob::HttpFilterContext::GetByteReadCount() const { | |
| 225 return job_->prefilter_bytes_read(); | |
| 226 } | |
| 227 | |
| 228 int URLRequestHttpJob::HttpFilterContext::GetResponseCode() const { | |
| 229 return job_->GetResponseCode(); | |
| 230 } | |
| 231 | |
| 232 const URLRequestContext* | |
| 233 URLRequestHttpJob::HttpFilterContext::GetURLRequestContext() const { | |
| 234 return job_->request() ? job_->request()->context() : NULL; | |
| 235 } | |
| 236 | |
| 237 void URLRequestHttpJob::HttpFilterContext::RecordPacketStats( | |
| 238 StatisticSelector statistic) const { | |
| 239 job_->RecordPacketStats(statistic); | |
| 240 } | |
| 241 | |
| 242 const BoundNetLog& URLRequestHttpJob::HttpFilterContext::GetNetLog() const { | |
| 243 return job_->request() ? job_->request()->net_log() : dummy_log_; | |
| 244 } | |
| 245 | |
| 246 // TODO(darin): make sure the port blocking code is not lost | 165 // TODO(darin): make sure the port blocking code is not lost |
| 247 // static | 166 // static |
| 248 URLRequestJob* URLRequestHttpJob::Factory(URLRequest* request, | 167 URLRequestJob* URLRequestHttpJob::Factory(URLRequest* request, |
| 249 NetworkDelegate* network_delegate, | 168 NetworkDelegate* network_delegate, |
| 250 const std::string& scheme) { | 169 const std::string& scheme) { |
| 251 DCHECK(scheme == "http" || scheme == "https" || scheme == "ws" || | 170 DCHECK(scheme == "http" || scheme == "https" || scheme == "ws" || |
| 252 scheme == "wss"); | 171 scheme == "wss"); |
| 253 | 172 |
| 254 if (!request->context()->http_transaction_factory()) { | 173 if (!request->context()->http_transaction_factory()) { |
| 255 NOTREACHED() << "requires a valid context"; | 174 NOTREACHED() << "requires a valid context"; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 287 throttling_entry_(nullptr), | 206 throttling_entry_(nullptr), |
| 288 sdch_test_activated_(false), | 207 sdch_test_activated_(false), |
| 289 sdch_test_control_(false), | 208 sdch_test_control_(false), |
| 290 is_cached_content_(false), | 209 is_cached_content_(false), |
| 291 request_creation_time_(), | 210 request_creation_time_(), |
| 292 packet_timing_enabled_(false), | 211 packet_timing_enabled_(false), |
| 293 done_(false), | 212 done_(false), |
| 294 bytes_observed_in_packets_(0), | 213 bytes_observed_in_packets_(0), |
| 295 request_time_snapshot_(), | 214 request_time_snapshot_(), |
| 296 final_packet_time_(), | 215 final_packet_time_(), |
| 297 filter_context_(new HttpFilterContext(this)), | |
| 298 on_headers_received_callback_( | 216 on_headers_received_callback_( |
| 299 base::Bind(&URLRequestHttpJob::OnHeadersReceivedCallback, | 217 base::Bind(&URLRequestHttpJob::OnHeadersReceivedCallback, |
| 300 base::Unretained(this))), | 218 base::Unretained(this))), |
| 301 awaiting_callback_(false), | 219 awaiting_callback_(false), |
| 302 http_user_agent_settings_(http_user_agent_settings), | 220 http_user_agent_settings_(http_user_agent_settings), |
| 303 backoff_manager_(request->context()->backoff_manager()), | 221 backoff_manager_(request->context()->backoff_manager()), |
| 304 total_received_bytes_from_previous_transactions_(0), | 222 total_received_bytes_from_previous_transactions_(0), |
| 305 total_sent_bytes_from_previous_transactions_(0), | 223 total_sent_bytes_from_previous_transactions_(0), |
| 306 weak_factory_(this) { | 224 weak_factory_(this) { |
| 307 URLRequestThrottlerManager* manager = request->context()->throttler_manager(); | 225 URLRequestThrottlerManager* manager = request->context()->throttler_manager(); |
| 308 if (manager) | 226 if (manager) |
| 309 throttling_entry_ = manager->RegisterRequestUrl(request->url()); | 227 throttling_entry_ = manager->RegisterRequestUrl(request->url()); |
| 310 | 228 |
| 311 ResetTimer(); | 229 ResetTimer(); |
| 312 } | 230 } |
| 313 | 231 |
| 314 URLRequestHttpJob::~URLRequestHttpJob() { | 232 URLRequestHttpJob::~URLRequestHttpJob() { |
| 315 CHECK(!awaiting_callback_); | 233 CHECK(!awaiting_callback_); |
| 316 | 234 |
| 235 // FIXME: FilterContext is gone. How should we handle SDCH stats??? |
| 236 #if 0 |
| 317 DCHECK(!sdch_test_control_ || !sdch_test_activated_); | 237 DCHECK(!sdch_test_control_ || !sdch_test_activated_); |
| 318 if (!is_cached_content_) { | 238 if (!is_cached_content_) { |
| 319 if (sdch_test_control_) | 239 if (sdch_test_control_) |
| 320 RecordPacketStats(FilterContext::SDCH_EXPERIMENT_HOLDBACK); | 240 RecordPacketStats(FilterContext::SDCH_EXPERIMENT_HOLDBACK); |
| 321 if (sdch_test_activated_) | 241 if (sdch_test_activated_) |
| 322 RecordPacketStats(FilterContext::SDCH_EXPERIMENT_DECODE); | 242 RecordPacketStats(FilterContext::SDCH_EXPERIMENT_DECODE); |
| 323 } | 243 } |
| 244 #endif |
| 324 // Make sure SDCH filters are told to emit histogram data while | 245 // Make sure SDCH filters are told to emit histogram data while |
| 325 // filter_context_ is still alive. | 246 // filter_context_ is still alive. |
| 326 DestroyFilters(); | 247 // DestroyFilters(); |
| 327 | 248 |
| 328 DoneWithRequest(ABORTED); | 249 DoneWithRequest(ABORTED); |
| 329 } | 250 } |
| 330 | 251 |
| 331 void URLRequestHttpJob::SetPriority(RequestPriority priority) { | 252 void URLRequestHttpJob::SetPriority(RequestPriority priority) { |
| 332 priority_ = priority; | 253 priority_ = priority; |
| 333 if (transaction_) | 254 if (transaction_) |
| 334 transaction_->SetPriority(priority_); | 255 transaction_->SetPriority(priority_); |
| 335 } | 256 } |
| 336 | 257 |
| (...skipping 884 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1221 return GetResponseHeaders()->response_code(); | 1142 return GetResponseHeaders()->response_code(); |
| 1222 } | 1143 } |
| 1223 | 1144 |
| 1224 void URLRequestHttpJob::PopulateNetErrorDetails( | 1145 void URLRequestHttpJob::PopulateNetErrorDetails( |
| 1225 NetErrorDetails* details) const { | 1146 NetErrorDetails* details) const { |
| 1226 if (!transaction_) | 1147 if (!transaction_) |
| 1227 return; | 1148 return; |
| 1228 return transaction_->PopulateNetErrorDetails(details); | 1149 return transaction_->PopulateNetErrorDetails(details); |
| 1229 } | 1150 } |
| 1230 | 1151 |
| 1231 Filter* URLRequestHttpJob::SetupFilter() const { | 1152 std::unique_ptr<StreamSource> URLRequestHttpJob::SetupSource() { |
| 1232 DCHECK(transaction_.get()); | 1153 DCHECK(transaction_.get()); |
| 1233 if (!response_info_) | 1154 if (!response_info_) |
| 1234 return NULL; | 1155 return nullptr; |
| 1235 | 1156 |
| 1236 std::vector<Filter::FilterType> encoding_types; | 1157 return StreamSourceUtil::BuildSourceChain(URLRequestJob::SetupSource(), |
| 1237 std::string encoding_type; | 1158 GetResponseHeaders()); |
| 1238 HttpResponseHeaders* headers = GetResponseHeaders(); | |
| 1239 size_t iter = 0; | |
| 1240 while (headers->EnumerateHeader(&iter, "Content-Encoding", &encoding_type)) { | |
| 1241 encoding_types.push_back(Filter::ConvertEncodingToType(encoding_type)); | |
| 1242 } | |
| 1243 | |
| 1244 // Even if encoding types are empty, there is a chance that we need to add | |
| 1245 // some decoding, as some proxies strip encoding completely. In such cases, | |
| 1246 // we may need to add (for example) SDCH filtering (when the context suggests | |
| 1247 // it is appropriate). | |
| 1248 Filter::FixupEncodingTypes(*filter_context_, &encoding_types); | |
| 1249 | |
| 1250 return !encoding_types.empty() | |
| 1251 ? Filter::Factory(encoding_types, *filter_context_) : NULL; | |
| 1252 } | 1159 } |
| 1253 | 1160 |
| 1254 bool URLRequestHttpJob::CopyFragmentOnRedirect(const GURL& location) const { | 1161 bool URLRequestHttpJob::CopyFragmentOnRedirect(const GURL& location) const { |
| 1255 // Allow modification of reference fragments by default, unless | 1162 // Allow modification of reference fragments by default, unless |
| 1256 // |allowed_unsafe_redirect_url_| is set and equal to the redirect URL. | 1163 // |allowed_unsafe_redirect_url_| is set and equal to the redirect URL. |
| 1257 // When this is the case, we assume that the network delegate has set the | 1164 // When this is the case, we assume that the network delegate has set the |
| 1258 // desired redirect URL (with or without fragment), so it must not be changed | 1165 // desired redirect URL (with or without fragment), so it must not be changed |
| 1259 // any more. | 1166 // any more. |
| 1260 return !allowed_unsafe_redirect_url_.is_valid() || | 1167 return !allowed_unsafe_redirect_url_.is_valid() || |
| 1261 allowed_unsafe_redirect_url_ != location; | 1168 allowed_unsafe_redirect_url_ != location; |
| (...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1536 DCHECK_GT(prefilter_bytes_read(), bytes_observed_in_packets_); | 1443 DCHECK_GT(prefilter_bytes_read(), bytes_observed_in_packets_); |
| 1537 | 1444 |
| 1538 base::Time now(base::Time::Now()); | 1445 base::Time now(base::Time::Now()); |
| 1539 if (!bytes_observed_in_packets_) | 1446 if (!bytes_observed_in_packets_) |
| 1540 request_time_snapshot_ = now; | 1447 request_time_snapshot_ = now; |
| 1541 final_packet_time_ = now; | 1448 final_packet_time_ = now; |
| 1542 | 1449 |
| 1543 bytes_observed_in_packets_ = prefilter_bytes_read(); | 1450 bytes_observed_in_packets_ = prefilter_bytes_read(); |
| 1544 } | 1451 } |
| 1545 | 1452 |
| 1546 void URLRequestHttpJob::RecordPacketStats( | |
| 1547 FilterContext::StatisticSelector statistic) const { | |
| 1548 if (!packet_timing_enabled_ || (final_packet_time_ == base::Time())) | |
| 1549 return; | |
| 1550 | |
| 1551 base::TimeDelta duration = final_packet_time_ - request_time_snapshot_; | |
| 1552 switch (statistic) { | |
| 1553 case FilterContext::SDCH_DECODE: { | |
| 1554 UMA_HISTOGRAM_CUSTOM_COUNTS("Sdch3.Network_Decode_Bytes_Processed_b", | |
| 1555 static_cast<int>(bytes_observed_in_packets_), 500, 100000, 100); | |
| 1556 return; | |
| 1557 } | |
| 1558 case FilterContext::SDCH_PASSTHROUGH: { | |
| 1559 // Despite advertising a dictionary, we handled non-sdch compressed | |
| 1560 // content. | |
| 1561 return; | |
| 1562 } | |
| 1563 | |
| 1564 case FilterContext::SDCH_EXPERIMENT_DECODE: { | |
| 1565 UMA_HISTOGRAM_CUSTOM_TIMES("Sdch3.Experiment3_Decode", | |
| 1566 duration, | |
| 1567 base::TimeDelta::FromMilliseconds(20), | |
| 1568 base::TimeDelta::FromMinutes(10), 100); | |
| 1569 return; | |
| 1570 } | |
| 1571 case FilterContext::SDCH_EXPERIMENT_HOLDBACK: { | |
| 1572 UMA_HISTOGRAM_CUSTOM_TIMES("Sdch3.Experiment3_Holdback", | |
| 1573 duration, | |
| 1574 base::TimeDelta::FromMilliseconds(20), | |
| 1575 base::TimeDelta::FromMinutes(10), 100); | |
| 1576 return; | |
| 1577 } | |
| 1578 default: | |
| 1579 NOTREACHED(); | |
| 1580 return; | |
| 1581 } | |
| 1582 } | |
| 1583 | |
| 1584 void URLRequestHttpJob::RecordPerfHistograms(CompletionCause reason) { | 1453 void URLRequestHttpJob::RecordPerfHistograms(CompletionCause reason) { |
| 1585 if (start_time_.is_null()) | 1454 if (start_time_.is_null()) |
| 1586 return; | 1455 return; |
| 1587 | 1456 |
| 1588 base::TimeDelta total_time = base::TimeTicks::Now() - start_time_; | 1457 base::TimeDelta total_time = base::TimeTicks::Now() - start_time_; |
| 1589 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTime", total_time); | 1458 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTime", total_time); |
| 1590 | 1459 |
| 1591 if (reason == FINISHED) { | 1460 if (reason == FINISHED) { |
| 1592 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeSuccess", total_time); | 1461 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeSuccess", total_time); |
| 1593 } else { | 1462 } else { |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1665 return override_response_headers_.get() ? | 1534 return override_response_headers_.get() ? |
| 1666 override_response_headers_.get() : | 1535 override_response_headers_.get() : |
| 1667 transaction_->GetResponseInfo()->headers.get(); | 1536 transaction_->GetResponseInfo()->headers.get(); |
| 1668 } | 1537 } |
| 1669 | 1538 |
| 1670 void URLRequestHttpJob::NotifyURLRequestDestroyed() { | 1539 void URLRequestHttpJob::NotifyURLRequestDestroyed() { |
| 1671 awaiting_callback_ = false; | 1540 awaiting_callback_ = false; |
| 1672 } | 1541 } |
| 1673 | 1542 |
| 1674 } // namespace net | 1543 } // namespace net |
| OLD | NEW |