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" |
11 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
12 #include "base/debug/alias.h" | |
13 #include "base/debug/dump_without_crashing.h" | |
14 #include "base/file_version_info.h" | 12 #include "base/file_version_info.h" |
15 #include "base/message_loop/message_loop.h" | 13 #include "base/message_loop/message_loop.h" |
16 #include "base/metrics/field_trial.h" | 14 #include "base/metrics/field_trial.h" |
17 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
18 #include "base/profiler/scoped_tracker.h" | 16 #include "base/profiler/scoped_tracker.h" |
19 #include "base/rand_util.h" | 17 #include "base/rand_util.h" |
20 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
21 #include "base/time/time.h" | 19 #include "base/time/time.h" |
22 #include "net/base/host_port_pair.h" | 20 #include "net/base/host_port_pair.h" |
23 #include "net/base/load_flags.h" | 21 #include "net/base/load_flags.h" |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 done_(false), | 200 done_(false), |
203 bytes_observed_in_packets_(0), | 201 bytes_observed_in_packets_(0), |
204 request_time_snapshot_(), | 202 request_time_snapshot_(), |
205 final_packet_time_(), | 203 final_packet_time_(), |
206 filter_context_(new HttpFilterContext(this)), | 204 filter_context_(new HttpFilterContext(this)), |
207 on_headers_received_callback_( | 205 on_headers_received_callback_( |
208 base::Bind(&URLRequestHttpJob::OnHeadersReceivedCallback, | 206 base::Bind(&URLRequestHttpJob::OnHeadersReceivedCallback, |
209 base::Unretained(this))), | 207 base::Unretained(this))), |
210 awaiting_callback_(false), | 208 awaiting_callback_(false), |
211 http_user_agent_settings_(http_user_agent_settings), | 209 http_user_agent_settings_(http_user_agent_settings), |
212 transaction_state_(TRANSACTION_WAS_NOT_INITIALIZED), | |
213 weak_factory_(this) { | 210 weak_factory_(this) { |
214 URLRequestThrottlerManager* manager = request->context()->throttler_manager(); | 211 URLRequestThrottlerManager* manager = request->context()->throttler_manager(); |
215 if (manager) | 212 if (manager) |
216 throttling_entry_ = manager->RegisterRequestUrl(request->url()); | 213 throttling_entry_ = manager->RegisterRequestUrl(request->url()); |
217 | 214 |
218 // TODO(battre) Remove this overriding once crbug.com/289715 has been | |
219 // resolved. | |
220 on_headers_received_callback_ = | |
221 base::Bind(&URLRequestHttpJob::OnHeadersReceivedCallbackForDebugging, | |
222 weak_factory_.GetWeakPtr()); | |
223 | |
224 ResetTimer(); | 215 ResetTimer(); |
225 } | 216 } |
226 | 217 |
227 URLRequestHttpJob::~URLRequestHttpJob() { | 218 URLRequestHttpJob::~URLRequestHttpJob() { |
228 CHECK(!awaiting_callback_); | 219 CHECK(!awaiting_callback_); |
229 | 220 |
230 DCHECK(!sdch_test_control_ || !sdch_test_activated_); | 221 DCHECK(!sdch_test_control_ || !sdch_test_activated_); |
231 if (!is_cached_content_) { | 222 if (!is_cached_content_) { |
232 if (sdch_test_control_) | 223 if (sdch_test_control_) |
233 RecordPacketStats(FilterContext::SDCH_EXPERIMENT_HOLDBACK); | 224 RecordPacketStats(FilterContext::SDCH_EXPERIMENT_HOLDBACK); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 request_info_.extra_headers.SetHeaderIfMissing( | 274 request_info_.extra_headers.SetHeaderIfMissing( |
284 HttpRequestHeaders::kUserAgent, | 275 HttpRequestHeaders::kUserAgent, |
285 http_user_agent_settings_ ? | 276 http_user_agent_settings_ ? |
286 http_user_agent_settings_->GetUserAgent() : std::string()); | 277 http_user_agent_settings_->GetUserAgent() : std::string()); |
287 | 278 |
288 AddExtraHeaders(); | 279 AddExtraHeaders(); |
289 AddCookieHeaderAndStart(); | 280 AddCookieHeaderAndStart(); |
290 } | 281 } |
291 | 282 |
292 void URLRequestHttpJob::Kill() { | 283 void URLRequestHttpJob::Kill() { |
293 if (awaiting_callback_) { | |
294 // TODO(battre) crbug.com/289715 | |
295 // Simulate a crash to see who kills the job while it is waiting for a | |
296 // callback. This should not happen, see URLRequest::OrphanJob(). | |
297 base::debug::DumpWithoutCrashing(); | |
298 } | |
299 if (!transaction_.get()) | 284 if (!transaction_.get()) |
300 return; | 285 return; |
301 | 286 |
302 weak_factory_.InvalidateWeakPtrs(); | 287 weak_factory_.InvalidateWeakPtrs(); |
303 DestroyTransaction(); | 288 DestroyTransaction(); |
304 URLRequestJob::Kill(); | 289 URLRequestJob::Kill(); |
305 } | 290 } |
306 | 291 |
307 void URLRequestHttpJob::NotifyBeforeSendProxyHeadersCallback( | 292 void URLRequestHttpJob::NotifyBeforeSendProxyHeadersCallback( |
308 const ProxyInfo& proxy_info, | 293 const ProxyInfo& proxy_info, |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 void URLRequestHttpJob::NotifyDone(const URLRequestStatus& status) { | 400 void URLRequestHttpJob::NotifyDone(const URLRequestStatus& status) { |
416 DoneWithRequest(FINISHED); | 401 DoneWithRequest(FINISHED); |
417 URLRequestJob::NotifyDone(status); | 402 URLRequestJob::NotifyDone(status); |
418 } | 403 } |
419 | 404 |
420 void URLRequestHttpJob::DestroyTransaction() { | 405 void URLRequestHttpJob::DestroyTransaction() { |
421 DCHECK(transaction_.get()); | 406 DCHECK(transaction_.get()); |
422 | 407 |
423 DoneWithRequest(ABORTED); | 408 DoneWithRequest(ABORTED); |
424 transaction_.reset(); | 409 transaction_.reset(); |
425 transaction_state_ = TRANSACTION_WAS_DESTROYED; | |
426 response_info_ = NULL; | 410 response_info_ = NULL; |
427 receive_headers_end_ = base::TimeTicks(); | 411 receive_headers_end_ = base::TimeTicks(); |
428 } | 412 } |
429 | 413 |
430 void URLRequestHttpJob::StartTransaction() { | 414 void URLRequestHttpJob::StartTransaction() { |
431 if (network_delegate()) { | 415 if (network_delegate()) { |
432 OnCallToDelegate(); | 416 OnCallToDelegate(); |
433 int rv = network_delegate()->NotifyBeforeSendHeaders( | 417 int rv = network_delegate()->NotifyBeforeSendHeaders( |
434 request_, notify_before_headers_sent_callback_, | 418 request_, notify_before_headers_sent_callback_, |
435 &request_info_.extra_headers); | 419 &request_info_.extra_headers); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
477 } | 461 } |
478 | 462 |
479 if (transaction_.get()) { | 463 if (transaction_.get()) { |
480 rv = transaction_->RestartWithAuth(auth_credentials_, start_callback_); | 464 rv = transaction_->RestartWithAuth(auth_credentials_, start_callback_); |
481 auth_credentials_ = AuthCredentials(); | 465 auth_credentials_ = AuthCredentials(); |
482 } else { | 466 } else { |
483 DCHECK(request_->context()->http_transaction_factory()); | 467 DCHECK(request_->context()->http_transaction_factory()); |
484 | 468 |
485 rv = request_->context()->http_transaction_factory()->CreateTransaction( | 469 rv = request_->context()->http_transaction_factory()->CreateTransaction( |
486 priority_, &transaction_); | 470 priority_, &transaction_); |
487 if (rv == OK) | |
488 transaction_state_ = TRANSACTION_WAS_INITIALIZED; | |
489 | 471 |
490 if (rv == OK && request_info_.url.SchemeIsWSOrWSS()) { | 472 if (rv == OK && request_info_.url.SchemeIsWSOrWSS()) { |
491 base::SupportsUserData::Data* data = request_->GetUserData( | 473 base::SupportsUserData::Data* data = request_->GetUserData( |
492 WebSocketHandshakeStreamBase::CreateHelper::DataKey()); | 474 WebSocketHandshakeStreamBase::CreateHelper::DataKey()); |
493 if (data) { | 475 if (data) { |
494 transaction_->SetWebSocketHandshakeStreamCreateHelper( | 476 transaction_->SetWebSocketHandshakeStreamCreateHelper( |
495 static_cast<WebSocketHandshakeStreamBase::CreateHelper*>(data)); | 477 static_cast<WebSocketHandshakeStreamBase::CreateHelper*>(data)); |
496 } else { | 478 } else { |
497 rv = ERR_DISALLOWED_URL_SCHEME; | 479 rv = ERR_DISALLOWED_URL_SCHEME; |
498 } | 480 } |
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
944 transaction_->GetResponseInfo()->cert_request_info.get()); | 926 transaction_->GetResponseInfo()->cert_request_info.get()); |
945 } else { | 927 } else { |
946 // Even on an error, there may be useful information in the response | 928 // Even on an error, there may be useful information in the response |
947 // info (e.g. whether there's a cached copy). | 929 // info (e.g. whether there's a cached copy). |
948 if (transaction_.get()) | 930 if (transaction_.get()) |
949 response_info_ = transaction_->GetResponseInfo(); | 931 response_info_ = transaction_->GetResponseInfo(); |
950 NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result)); | 932 NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result)); |
951 } | 933 } |
952 } | 934 } |
953 | 935 |
954 // TODO(battre) Use URLRequestHttpJob::OnHeadersReceivedCallback again, once | |
955 // crbug.com/289715 has been resolved. | |
956 // static | |
957 void URLRequestHttpJob::OnHeadersReceivedCallbackForDebugging( | |
958 base::WeakPtr<net::URLRequestHttpJob> job, | |
959 int result) { | |
960 CHECK(job.get()); | |
961 net::URLRequestHttpJob::TransactionState state = job->transaction_state_; | |
962 base::debug::Alias(&state); | |
963 CHECK(job->transaction_.get()); | |
964 job->OnHeadersReceivedCallback(result); | |
965 } | |
966 | |
967 void URLRequestHttpJob::OnHeadersReceivedCallback(int result) { | 936 void URLRequestHttpJob::OnHeadersReceivedCallback(int result) { |
968 awaiting_callback_ = false; | 937 awaiting_callback_ = false; |
969 | 938 |
970 // Check that there are no callbacks to already canceled requests. | 939 // Check that there are no callbacks to already canceled requests. |
971 DCHECK_NE(URLRequestStatus::CANCELED, GetStatus().status()); | 940 DCHECK_NE(URLRequestStatus::CANCELED, GetStatus().status()); |
972 | 941 |
973 SaveCookiesAndNotifyHeadersComplete(result); | 942 SaveCookiesAndNotifyHeadersComplete(result); |
974 } | 943 } |
975 | 944 |
976 void URLRequestHttpJob::OnReadCompleted(int result) { | 945 void URLRequestHttpJob::OnReadCompleted(int result) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1040 return transaction_.get() ? | 1009 return transaction_.get() ? |
1041 transaction_->GetUploadProgress() : UploadProgress(); | 1010 transaction_->GetUploadProgress() : UploadProgress(); |
1042 } | 1011 } |
1043 | 1012 |
1044 bool URLRequestHttpJob::GetMimeType(std::string* mime_type) const { | 1013 bool URLRequestHttpJob::GetMimeType(std::string* mime_type) const { |
1045 DCHECK(transaction_.get()); | 1014 DCHECK(transaction_.get()); |
1046 | 1015 |
1047 if (!response_info_) | 1016 if (!response_info_) |
1048 return false; | 1017 return false; |
1049 | 1018 |
1050 return GetResponseHeaders()->GetMimeType(mime_type); | 1019 HttpResponseHeaders* headers = GetResponseHeaders(); |
| 1020 if (!headers) |
| 1021 return false; |
| 1022 return headers->GetMimeType(mime_type); |
1051 } | 1023 } |
1052 | 1024 |
1053 bool URLRequestHttpJob::GetCharset(std::string* charset) { | 1025 bool URLRequestHttpJob::GetCharset(std::string* charset) { |
1054 DCHECK(transaction_.get()); | 1026 DCHECK(transaction_.get()); |
1055 | 1027 |
1056 if (!response_info_) | 1028 if (!response_info_) |
1057 return false; | 1029 return false; |
1058 | 1030 |
1059 return GetResponseHeaders()->GetCharset(charset); | 1031 return GetResponseHeaders()->GetCharset(charset); |
1060 } | 1032 } |
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1476 base::TimeDelta::FromMilliseconds(20), | 1448 base::TimeDelta::FromMilliseconds(20), |
1477 base::TimeDelta::FromMinutes(10), 100); | 1449 base::TimeDelta::FromMinutes(10), 100); |
1478 return; | 1450 return; |
1479 } | 1451 } |
1480 default: | 1452 default: |
1481 NOTREACHED(); | 1453 NOTREACHED(); |
1482 return; | 1454 return; |
1483 } | 1455 } |
1484 } | 1456 } |
1485 | 1457 |
1486 // The common type of histogram we use for all compression-tracking histograms. | |
1487 #define COMPRESSION_HISTOGRAM(name, sample) \ | |
1488 do { \ | |
1489 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.Compress." name, sample, \ | |
1490 500, 1000000, 100); \ | |
1491 } while (0) | |
1492 | |
1493 void URLRequestHttpJob::RecordCompressionHistograms() { | |
1494 DCHECK(request_); | |
1495 if (!request_) | |
1496 return; | |
1497 | |
1498 if (is_cached_content_ || // Don't record cached content | |
1499 !GetStatus().is_success() || // Don't record failed content | |
1500 !IsCompressibleContent() || // Only record compressible content | |
1501 !prefilter_bytes_read()) // Zero-byte responses aren't useful. | |
1502 return; | |
1503 | |
1504 // Miniature requests aren't really compressible. Don't count them. | |
1505 const int kMinSize = 16; | |
1506 if (prefilter_bytes_read() < kMinSize) | |
1507 return; | |
1508 | |
1509 // Only record for http or https urls. | |
1510 bool is_http = request_->url().SchemeIs("http"); | |
1511 bool is_https = request_->url().SchemeIs("https"); | |
1512 if (!is_http && !is_https) | |
1513 return; | |
1514 | |
1515 int compressed_B = prefilter_bytes_read(); | |
1516 int decompressed_B = postfilter_bytes_read(); | |
1517 bool was_filtered = HasFilter(); | |
1518 | |
1519 // We want to record how often downloaded resources are compressed. | |
1520 // But, we recognize that different protocols may have different | |
1521 // properties. So, for each request, we'll put it into one of 3 | |
1522 // groups: | |
1523 // a) SSL resources | |
1524 // Proxies cannot tamper with compression headers with SSL. | |
1525 // b) Non-SSL, loaded-via-proxy resources | |
1526 // In this case, we know a proxy might have interfered. | |
1527 // c) Non-SSL, loaded-without-proxy resources | |
1528 // In this case, we know there was no explicit proxy. However, | |
1529 // it is possible that a transparent proxy was still interfering. | |
1530 // | |
1531 // For each group, we record the same 3 histograms. | |
1532 | |
1533 if (is_https) { | |
1534 if (was_filtered) { | |
1535 COMPRESSION_HISTOGRAM("SSL.BytesBeforeCompression", compressed_B); | |
1536 COMPRESSION_HISTOGRAM("SSL.BytesAfterCompression", decompressed_B); | |
1537 } else { | |
1538 COMPRESSION_HISTOGRAM("SSL.ShouldHaveBeenCompressed", decompressed_B); | |
1539 } | |
1540 return; | |
1541 } | |
1542 | |
1543 if (request_->was_fetched_via_proxy()) { | |
1544 if (was_filtered) { | |
1545 COMPRESSION_HISTOGRAM("Proxy.BytesBeforeCompression", compressed_B); | |
1546 COMPRESSION_HISTOGRAM("Proxy.BytesAfterCompression", decompressed_B); | |
1547 } else { | |
1548 COMPRESSION_HISTOGRAM("Proxy.ShouldHaveBeenCompressed", decompressed_B); | |
1549 } | |
1550 return; | |
1551 } | |
1552 | |
1553 if (was_filtered) { | |
1554 COMPRESSION_HISTOGRAM("NoProxy.BytesBeforeCompression", compressed_B); | |
1555 COMPRESSION_HISTOGRAM("NoProxy.BytesAfterCompression", decompressed_B); | |
1556 } else { | |
1557 COMPRESSION_HISTOGRAM("NoProxy.ShouldHaveBeenCompressed", decompressed_B); | |
1558 } | |
1559 } | |
1560 | |
1561 bool URLRequestHttpJob::IsCompressibleContent() const { | |
1562 std::string mime_type; | |
1563 return GetMimeType(&mime_type) && | |
1564 (IsSupportedJavascriptMimeType(mime_type.c_str()) || | |
1565 IsSupportedNonImageMimeType(mime_type.c_str())); | |
1566 } | |
1567 | |
1568 void URLRequestHttpJob::RecordPerfHistograms(CompletionCause reason) { | 1458 void URLRequestHttpJob::RecordPerfHistograms(CompletionCause reason) { |
1569 if (start_time_.is_null()) | 1459 if (start_time_.is_null()) |
1570 return; | 1460 return; |
1571 | 1461 |
1572 base::TimeDelta total_time = base::TimeTicks::Now() - start_time_; | 1462 base::TimeDelta total_time = base::TimeTicks::Now() - start_time_; |
1573 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTime", total_time); | 1463 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTime", total_time); |
1574 | 1464 |
1575 if (reason == FINISHED) { | 1465 if (reason == FINISHED) { |
1576 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeSuccess", total_time); | 1466 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeSuccess", total_time); |
1577 } else { | 1467 } else { |
(...skipping 15 matching lines...) Expand all Loading... |
1593 start_time_ = base::TimeTicks(); | 1483 start_time_ = base::TimeTicks(); |
1594 } | 1484 } |
1595 | 1485 |
1596 void URLRequestHttpJob::DoneWithRequest(CompletionCause reason) { | 1486 void URLRequestHttpJob::DoneWithRequest(CompletionCause reason) { |
1597 if (done_) | 1487 if (done_) |
1598 return; | 1488 return; |
1599 done_ = true; | 1489 done_ = true; |
1600 RecordPerfHistograms(reason); | 1490 RecordPerfHistograms(reason); |
1601 if (reason == FINISHED) { | 1491 if (reason == FINISHED) { |
1602 request_->set_received_response_content_length(prefilter_bytes_read()); | 1492 request_->set_received_response_content_length(prefilter_bytes_read()); |
1603 RecordCompressionHistograms(); | |
1604 } | 1493 } |
1605 } | 1494 } |
1606 | 1495 |
1607 HttpResponseHeaders* URLRequestHttpJob::GetResponseHeaders() const { | 1496 HttpResponseHeaders* URLRequestHttpJob::GetResponseHeaders() const { |
1608 DCHECK(transaction_.get()); | 1497 DCHECK(transaction_.get()); |
1609 DCHECK(transaction_->GetResponseInfo()); | 1498 DCHECK(transaction_->GetResponseInfo()); |
1610 return override_response_headers_.get() ? | 1499 return override_response_headers_.get() ? |
1611 override_response_headers_.get() : | 1500 override_response_headers_.get() : |
1612 transaction_->GetResponseInfo()->headers.get(); | 1501 transaction_->GetResponseInfo()->headers.get(); |
1613 } | 1502 } |
1614 | 1503 |
1615 void URLRequestHttpJob::NotifyURLRequestDestroyed() { | 1504 void URLRequestHttpJob::NotifyURLRequestDestroyed() { |
1616 awaiting_callback_ = false; | 1505 awaiting_callback_ = false; |
1617 } | 1506 } |
1618 | 1507 |
1619 } // namespace net | 1508 } // namespace net |
OLD | NEW |