| 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 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 59 explicit HttpFilterContext(URLRequestHttpJob* job); | 59 explicit HttpFilterContext(URLRequestHttpJob* job); |
| 60 ~HttpFilterContext() override; | 60 ~HttpFilterContext() override; |
| 61 | 61 |
| 62 // FilterContext implementation. | 62 // FilterContext implementation. |
| 63 bool GetMimeType(std::string* mime_type) const override; | 63 bool GetMimeType(std::string* mime_type) const override; |
| 64 bool GetURL(GURL* gurl) const override; | 64 bool GetURL(GURL* gurl) const override; |
| 65 bool GetContentDisposition(std::string* disposition) const override; | 65 bool GetContentDisposition(std::string* disposition) const override; |
| 66 base::Time GetRequestTime() const override; | 66 base::Time GetRequestTime() const override; |
| 67 bool IsCachedContent() const override; | 67 bool IsCachedContent() const override; |
| 68 bool IsDownload() const override; | 68 bool IsDownload() const override; |
| 69 bool SdchResponseExpected() const override; | 69 SdchManager::DictionarySet* SdchDictionariesAdvertised() const override; |
| 70 int64 GetByteReadCount() const override; | 70 int64 GetByteReadCount() const override; |
| 71 int GetResponseCode() const override; | 71 int GetResponseCode() const override; |
| 72 const URLRequestContext* GetURLRequestContext() const override; | 72 const URLRequestContext* GetURLRequestContext() const override; |
| 73 void RecordPacketStats(StatisticSelector statistic) const override; | 73 void RecordPacketStats(StatisticSelector statistic) const override; |
| 74 const BoundNetLog& GetNetLog() const override; | 74 const BoundNetLog& GetNetLog() const override; |
| 75 | 75 |
| 76 // Method to allow us to reset filter context for a response that should have | |
| 77 // been SDCH encoded when there is an update due to an explicit HTTP header. | |
| 78 void ResetSdchResponseToFalse(); | |
| 79 | |
| 80 private: | 76 private: |
| 81 URLRequestHttpJob* job_; | 77 URLRequestHttpJob* job_; |
| 82 | 78 |
| 83 // URLRequestHttpJob may be detached from URLRequest, but we still need to | 79 // URLRequestHttpJob may be detached from URLRequest, but we still need to |
| 84 // return something. | 80 // return something. |
| 85 BoundNetLog dummy_log_; | 81 BoundNetLog dummy_log_; |
| 86 | 82 |
| 87 DISALLOW_COPY_AND_ASSIGN(HttpFilterContext); | 83 DISALLOW_COPY_AND_ASSIGN(HttpFilterContext); |
| 88 }; | 84 }; |
| 89 | 85 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 119 } | 115 } |
| 120 | 116 |
| 121 bool URLRequestHttpJob::HttpFilterContext::IsCachedContent() const { | 117 bool URLRequestHttpJob::HttpFilterContext::IsCachedContent() const { |
| 122 return job_->is_cached_content_; | 118 return job_->is_cached_content_; |
| 123 } | 119 } |
| 124 | 120 |
| 125 bool URLRequestHttpJob::HttpFilterContext::IsDownload() const { | 121 bool URLRequestHttpJob::HttpFilterContext::IsDownload() const { |
| 126 return (job_->request_info_.load_flags & LOAD_IS_DOWNLOAD) != 0; | 122 return (job_->request_info_.load_flags & LOAD_IS_DOWNLOAD) != 0; |
| 127 } | 123 } |
| 128 | 124 |
| 129 void URLRequestHttpJob::HttpFilterContext::ResetSdchResponseToFalse() { | 125 SdchManager::DictionarySet* |
| 130 DCHECK(job_->sdch_dictionary_advertised_); | 126 URLRequestHttpJob::HttpFilterContext::SdchDictionariesAdvertised() const { |
| 131 job_->sdch_dictionary_advertised_ = false; | 127 return job_->dictionaries_advertised_.get(); |
| 132 } | |
| 133 | |
| 134 bool URLRequestHttpJob::HttpFilterContext::SdchResponseExpected() const { | |
| 135 return job_->sdch_dictionary_advertised_; | |
| 136 } | 128 } |
| 137 | 129 |
| 138 int64 URLRequestHttpJob::HttpFilterContext::GetByteReadCount() const { | 130 int64 URLRequestHttpJob::HttpFilterContext::GetByteReadCount() const { |
| 139 return job_->filter_input_byte_count(); | 131 return job_->filter_input_byte_count(); |
| 140 } | 132 } |
| 141 | 133 |
| 142 int URLRequestHttpJob::HttpFilterContext::GetResponseCode() const { | 134 int URLRequestHttpJob::HttpFilterContext::GetResponseCode() const { |
| 143 return job_->GetResponseCode(); | 135 return job_->GetResponseCode(); |
| 144 } | 136 } |
| 145 | 137 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 193 response_cookies_save_index_(0), | 185 response_cookies_save_index_(0), |
| 194 proxy_auth_state_(AUTH_STATE_DONT_NEED_AUTH), | 186 proxy_auth_state_(AUTH_STATE_DONT_NEED_AUTH), |
| 195 server_auth_state_(AUTH_STATE_DONT_NEED_AUTH), | 187 server_auth_state_(AUTH_STATE_DONT_NEED_AUTH), |
| 196 start_callback_(base::Bind(&URLRequestHttpJob::OnStartCompleted, | 188 start_callback_(base::Bind(&URLRequestHttpJob::OnStartCompleted, |
| 197 base::Unretained(this))), | 189 base::Unretained(this))), |
| 198 notify_before_headers_sent_callback_( | 190 notify_before_headers_sent_callback_( |
| 199 base::Bind(&URLRequestHttpJob::NotifyBeforeSendHeadersCallback, | 191 base::Bind(&URLRequestHttpJob::NotifyBeforeSendHeadersCallback, |
| 200 base::Unretained(this))), | 192 base::Unretained(this))), |
| 201 read_in_progress_(false), | 193 read_in_progress_(false), |
| 202 throttling_entry_(NULL), | 194 throttling_entry_(NULL), |
| 203 sdch_dictionary_advertised_(false), | |
| 204 sdch_test_activated_(false), | 195 sdch_test_activated_(false), |
| 205 sdch_test_control_(false), | 196 sdch_test_control_(false), |
| 206 is_cached_content_(false), | 197 is_cached_content_(false), |
| 207 request_creation_time_(), | 198 request_creation_time_(), |
| 208 packet_timing_enabled_(false), | 199 packet_timing_enabled_(false), |
| 209 done_(false), | 200 done_(false), |
| 210 bytes_observed_in_packets_(0), | 201 bytes_observed_in_packets_(0), |
| 211 request_time_snapshot_(), | 202 request_time_snapshot_(), |
| 212 final_packet_time_(), | 203 final_packet_time_(), |
| 213 filter_context_(new HttpFilterContext(this)), | 204 filter_context_(new HttpFilterContext(this)), |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 266 // Privacy mode could still be disabled in OnCookiesLoaded if we are going | 257 // Privacy mode could still be disabled in OnCookiesLoaded if we are going |
| 267 // to send previously saved cookies. | 258 // to send previously saved cookies. |
| 268 request_info_.privacy_mode = enable_privacy_mode ? | 259 request_info_.privacy_mode = enable_privacy_mode ? |
| 269 PRIVACY_MODE_ENABLED : PRIVACY_MODE_DISABLED; | 260 PRIVACY_MODE_ENABLED : PRIVACY_MODE_DISABLED; |
| 270 | 261 |
| 271 // Strip Referer from request_info_.extra_headers to prevent, e.g., plugins | 262 // Strip Referer from request_info_.extra_headers to prevent, e.g., plugins |
| 272 // from overriding headers that are controlled using other means. Otherwise a | 263 // from overriding headers that are controlled using other means. Otherwise a |
| 273 // plugin could set a referrer although sending the referrer is inhibited. | 264 // plugin could set a referrer although sending the referrer is inhibited. |
| 274 request_info_.extra_headers.RemoveHeader(HttpRequestHeaders::kReferer); | 265 request_info_.extra_headers.RemoveHeader(HttpRequestHeaders::kReferer); |
| 275 | 266 |
| 276 // Our consumer should have made sure that this is a safe referrer. See for | 267 // Our consumer should have made sure that this is a safe referrer. See for |
| 277 // instance WebCore::FrameLoader::HideReferrer. | 268 // instance WebCore::FrameLoader::HideReferrer. |
| 278 if (referrer.is_valid()) { | 269 if (referrer.is_valid()) { |
| 279 request_info_.extra_headers.SetHeader(HttpRequestHeaders::kReferer, | 270 request_info_.extra_headers.SetHeader(HttpRequestHeaders::kReferer, |
| 280 referrer.spec()); | 271 referrer.spec()); |
| 281 } | 272 } |
| 282 | 273 |
| 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()); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 if (!is_cached_content_ && throttling_entry_.get()) { | 314 if (!is_cached_content_ && throttling_entry_.get()) { |
| 324 URLRequestThrottlerHeaderAdapter response_adapter(GetResponseHeaders()); | 315 URLRequestThrottlerHeaderAdapter response_adapter(GetResponseHeaders()); |
| 325 throttling_entry_->UpdateWithResponse(request_info_.url.host(), | 316 throttling_entry_->UpdateWithResponse(request_info_.url.host(), |
| 326 &response_adapter); | 317 &response_adapter); |
| 327 } | 318 } |
| 328 | 319 |
| 329 // The ordering of these calls is not important. | 320 // The ordering of these calls is not important. |
| 330 ProcessStrictTransportSecurityHeader(); | 321 ProcessStrictTransportSecurityHeader(); |
| 331 ProcessPublicKeyPinsHeader(); | 322 ProcessPublicKeyPinsHeader(); |
| 332 | 323 |
| 324 // Handle the server notification of a new SDCH dictionary. |
| 333 SdchManager* sdch_manager(request()->context()->sdch_manager()); | 325 SdchManager* sdch_manager(request()->context()->sdch_manager()); |
| 334 if (sdch_manager) { | 326 if (sdch_manager) { |
| 335 SdchProblemCode rv = sdch_manager->IsInSupportedDomain(request()->url()); | 327 SdchProblemCode rv = sdch_manager->IsInSupportedDomain(request()->url()); |
| 336 if (rv != SDCH_OK) { | 328 if (rv != SDCH_OK) { |
| 337 // If SDCH is just disabled, it is not a real error. | 329 // If SDCH is just disabled, it is not a real error. |
| 338 if (rv != SDCH_DISABLED && rv != SDCH_SECURE_SCHEME_NOT_SUPPORTED) { | 330 if (rv != SDCH_DISABLED && rv != SDCH_SECURE_SCHEME_NOT_SUPPORTED) { |
| 339 SdchManager::SdchErrorRecovery(rv); | 331 SdchManager::SdchErrorRecovery(rv); |
| 340 request()->net_log().AddEvent( | 332 request()->net_log().AddEvent( |
| 341 NetLog::TYPE_SDCH_DECODING_ERROR, | 333 NetLog::TYPE_SDCH_DECODING_ERROR, |
| 342 base::Bind(&NetLogSdchResourceProblemCallback, rv)); | 334 base::Bind(&NetLogSdchResourceProblemCallback, rv)); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 364 request_->net_log().AddEvent( | 356 request_->net_log().AddEvent( |
| 365 NetLog::TYPE_SDCH_DICTIONARY_ERROR, | 357 NetLog::TYPE_SDCH_DICTIONARY_ERROR, |
| 366 base::Bind(&NetLogSdchDictionaryFetchProblemCallback, rv, | 358 base::Bind(&NetLogSdchDictionaryFetchProblemCallback, rv, |
| 367 sdch_dictionary_url, false)); | 359 sdch_dictionary_url, false)); |
| 368 } | 360 } |
| 369 } | 361 } |
| 370 } | 362 } |
| 371 } | 363 } |
| 372 } | 364 } |
| 373 | 365 |
| 366 // Handle the server signalling no SDCH encoding. |
| 367 if (dictionaries_advertised_) { |
| 368 // We are wary of proxies that discard or damage SDCH encoding. If a server |
| 369 // explicitly states that this is not SDCH content, then we can correct our |
| 370 // assumption that this is an SDCH response, and avoid the need to recover |
| 371 // as though the content is corrupted (when we discover it is not SDCH |
| 372 // encoded). |
| 373 std::string sdch_response_status; |
| 374 void* iter = NULL; |
| 375 while (GetResponseHeaders()->EnumerateHeader(&iter, "X-Sdch-Encode", |
| 376 &sdch_response_status)) { |
| 377 if (sdch_response_status == "0") { |
| 378 dictionaries_advertised_.reset(); |
| 379 break; |
| 380 } |
| 381 } |
| 382 } |
| 383 |
| 374 // The HTTP transaction may be restarted several times for the purposes | 384 // The HTTP transaction may be restarted several times for the purposes |
| 375 // of sending authorization information. Each time it restarts, we get | 385 // of sending authorization information. Each time it restarts, we get |
| 376 // notified of the headers completion so that we can update the cookie store. | 386 // notified of the headers completion so that we can update the cookie store. |
| 377 if (transaction_->IsReadyToRestartForAuth()) { | 387 if (transaction_->IsReadyToRestartForAuth()) { |
| 378 DCHECK(!response_info_->auth_challenge.get()); | 388 DCHECK(!response_info_->auth_challenge.get()); |
| 379 // TODO(battre): This breaks the webrequest API for | 389 // TODO(battre): This breaks the webrequest API for |
| 380 // URLRequestTestHTTP.BasicAuthWithCookies | 390 // URLRequestTestHTTP.BasicAuthWithCookies |
| 381 // where OnBeforeSendHeaders -> OnSendHeaders -> OnBeforeSendHeaders | 391 // where OnBeforeSendHeaders -> OnSendHeaders -> OnBeforeSendHeaders |
| 382 // occurs. | 392 // occurs. |
| 383 RestartTransactionWithAuth(AuthCredentials()); | 393 RestartTransactionWithAuth(AuthCredentials()); |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 525 advertise_sdch = false; | 535 advertise_sdch = false; |
| 526 // If SDCH is just disabled, it is not a real error. | 536 // If SDCH is just disabled, it is not a real error. |
| 527 if (rv != SDCH_DISABLED && rv != SDCH_SECURE_SCHEME_NOT_SUPPORTED) { | 537 if (rv != SDCH_DISABLED && rv != SDCH_SECURE_SCHEME_NOT_SUPPORTED) { |
| 528 SdchManager::SdchErrorRecovery(rv); | 538 SdchManager::SdchErrorRecovery(rv); |
| 529 request()->net_log().AddEvent( | 539 request()->net_log().AddEvent( |
| 530 NetLog::TYPE_SDCH_DECODING_ERROR, | 540 NetLog::TYPE_SDCH_DECODING_ERROR, |
| 531 base::Bind(&NetLogSdchResourceProblemCallback, rv)); | 541 base::Bind(&NetLogSdchResourceProblemCallback, rv)); |
| 532 } | 542 } |
| 533 } | 543 } |
| 534 } | 544 } |
| 535 std::string avail_dictionaries; | |
| 536 if (advertise_sdch) { | 545 if (advertise_sdch) { |
| 537 sdch_manager->GetAvailDictionaryList(request_->url(), | 546 dictionaries_advertised_ = |
| 538 &avail_dictionaries); | 547 sdch_manager->GetDictionarySet(request_->url()); |
| 548 } |
| 539 | 549 |
| 540 // The AllowLatencyExperiment() is only true if we've successfully done a | 550 // The AllowLatencyExperiment() is only true if we've successfully done a |
| 541 // full SDCH compression recently in this browser session for this host. | 551 // full SDCH compression recently in this browser session for this host. |
| 542 // Note that for this path, there might be no applicable dictionaries, | 552 // Note that for this path, there might be no applicable dictionaries, |
| 543 // and hence we can't participate in the experiment. | 553 // and hence we can't participate in the experiment. |
| 544 if (!avail_dictionaries.empty() && | 554 if (dictionaries_advertised_ && |
| 545 sdch_manager->AllowLatencyExperiment(request_->url())) { | 555 sdch_manager->AllowLatencyExperiment(request_->url())) { |
| 546 // We are participating in the test (or control), and hence we'll | 556 // We are participating in the test (or control), and hence we'll |
| 547 // eventually record statistics via either SDCH_EXPERIMENT_DECODE or | 557 // eventually record statistics via either SDCH_EXPERIMENT_DECODE or |
| 548 // SDCH_EXPERIMENT_HOLDBACK, and we'll need some packet timing data. | 558 // SDCH_EXPERIMENT_HOLDBACK, and we'll need some packet timing data. |
| 549 packet_timing_enabled_ = true; | 559 packet_timing_enabled_ = true; |
| 550 if (base::RandDouble() < .01) { | 560 if (base::RandDouble() < .01) { |
| 551 sdch_test_control_ = true; // 1% probability. | 561 sdch_test_control_ = true; // 1% probability. |
| 552 advertise_sdch = false; | 562 dictionaries_advertised_.reset(); |
| 553 } else { | 563 advertise_sdch = false; |
| 554 sdch_test_activated_ = true; | 564 } else { |
| 555 } | 565 sdch_test_activated_ = true; |
| 556 } | 566 } |
| 557 } | 567 } |
| 558 | 568 |
| 559 // Supply Accept-Encoding headers first so that it is more likely that they | 569 // Supply Accept-Encoding headers first so that it is more likely that they |
| 560 // will be in the first transmitted packet. This can sometimes make it | 570 // will be in the first transmitted packet. This can sometimes make it |
| 561 // easier to filter and analyze the streams to assure that a proxy has not | 571 // easier to filter and analyze the streams to assure that a proxy has not |
| 562 // damaged these headers. Some proxies deliberately corrupt Accept-Encoding | 572 // damaged these headers. Some proxies deliberately corrupt Accept-Encoding |
| 563 // headers. | 573 // headers. |
| 564 if (!advertise_sdch) { | 574 if (!advertise_sdch) { |
| 565 // Tell the server what compression formats we support (other than SDCH). | 575 // Tell the server what compression formats we support (other than SDCH). |
| 566 request_info_.extra_headers.SetHeader( | 576 request_info_.extra_headers.SetHeader( |
| 567 HttpRequestHeaders::kAcceptEncoding, "gzip, deflate"); | 577 HttpRequestHeaders::kAcceptEncoding, "gzip, deflate"); |
| 568 } else { | 578 } else { |
| 569 // Include SDCH in acceptable list. | 579 // Include SDCH in acceptable list. |
| 570 request_info_.extra_headers.SetHeader( | 580 request_info_.extra_headers.SetHeader( |
| 571 HttpRequestHeaders::kAcceptEncoding, "gzip, deflate, sdch"); | 581 HttpRequestHeaders::kAcceptEncoding, "gzip, deflate, sdch"); |
| 572 if (!avail_dictionaries.empty()) { | 582 if (dictionaries_advertised_) { |
| 573 request_info_.extra_headers.SetHeader( | 583 request_info_.extra_headers.SetHeader( |
| 574 kAvailDictionaryHeader, | 584 kAvailDictionaryHeader, |
| 575 avail_dictionaries); | 585 dictionaries_advertised_->GetDictionaryClientHashList()); |
| 576 sdch_dictionary_advertised_ = true; | |
| 577 // Since we're tagging this transaction as advertising a dictionary, | 586 // Since we're tagging this transaction as advertising a dictionary, |
| 578 // we'll definitely employ an SDCH filter (or tentative sdch filter) | 587 // we'll definitely employ an SDCH filter (or tentative sdch filter) |
| 579 // when we get a response. When done, we'll record histograms via | 588 // when we get a response. When done, we'll record histograms via |
| 580 // SDCH_DECODE or SDCH_PASSTHROUGH. Hence we need to record packet | 589 // SDCH_DECODE or SDCH_PASSTHROUGH. Hence we need to record packet |
| 581 // arrival times. | 590 // arrival times. |
| 582 packet_timing_enabled_ = true; | 591 packet_timing_enabled_ = true; |
| 583 } | 592 } |
| 584 } | 593 } |
| 585 } | 594 } |
| 586 | 595 |
| 587 if (http_user_agent_settings_) { | 596 if (http_user_agent_settings_) { |
| 588 // Only add default Accept-Language if the request didn't have it | 597 // Only add default Accept-Language if the request didn't have it |
| 589 // specified. | 598 // specified. |
| 590 std::string accept_language = | 599 std::string accept_language = |
| (...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1022 | 1031 |
| 1023 *info = *response_info_; | 1032 *info = *response_info_; |
| 1024 if (override_response_headers_.get()) | 1033 if (override_response_headers_.get()) |
| 1025 info->headers = override_response_headers_; | 1034 info->headers = override_response_headers_; |
| 1026 } | 1035 } |
| 1027 } | 1036 } |
| 1028 | 1037 |
| 1029 void URLRequestHttpJob::GetLoadTimingInfo( | 1038 void URLRequestHttpJob::GetLoadTimingInfo( |
| 1030 LoadTimingInfo* load_timing_info) const { | 1039 LoadTimingInfo* load_timing_info) const { |
| 1031 // If haven't made it far enough to receive any headers, don't return | 1040 // If haven't made it far enough to receive any headers, don't return |
| 1032 // anything. This makes for more consistent behavior in the case of errors. | 1041 // anything. This makes for more consistent behavior in the case of errors. |
| 1033 if (!transaction_ || receive_headers_end_.is_null()) | 1042 if (!transaction_ || receive_headers_end_.is_null()) |
| 1034 return; | 1043 return; |
| 1035 if (transaction_->GetLoadTimingInfo(load_timing_info)) | 1044 if (transaction_->GetLoadTimingInfo(load_timing_info)) |
| 1036 load_timing_info->receive_headers_end = receive_headers_end_; | 1045 load_timing_info->receive_headers_end = receive_headers_end_; |
| 1037 } | 1046 } |
| 1038 | 1047 |
| 1039 bool URLRequestHttpJob::GetResponseCookies(std::vector<std::string>* cookies) { | 1048 bool URLRequestHttpJob::GetResponseCookies(std::vector<std::string>* cookies) { |
| 1040 DCHECK(transaction_.get()); | 1049 DCHECK(transaction_.get()); |
| 1041 | 1050 |
| 1042 if (!response_info_) | 1051 if (!response_info_) |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1065 return NULL; | 1074 return NULL; |
| 1066 | 1075 |
| 1067 std::vector<Filter::FilterType> encoding_types; | 1076 std::vector<Filter::FilterType> encoding_types; |
| 1068 std::string encoding_type; | 1077 std::string encoding_type; |
| 1069 HttpResponseHeaders* headers = GetResponseHeaders(); | 1078 HttpResponseHeaders* headers = GetResponseHeaders(); |
| 1070 void* iter = NULL; | 1079 void* iter = NULL; |
| 1071 while (headers->EnumerateHeader(&iter, "Content-Encoding", &encoding_type)) { | 1080 while (headers->EnumerateHeader(&iter, "Content-Encoding", &encoding_type)) { |
| 1072 encoding_types.push_back(Filter::ConvertEncodingToType(encoding_type)); | 1081 encoding_types.push_back(Filter::ConvertEncodingToType(encoding_type)); |
| 1073 } | 1082 } |
| 1074 | 1083 |
| 1075 if (filter_context_->SdchResponseExpected()) { | |
| 1076 // We are wary of proxies that discard or damage SDCH encoding. If a server | |
| 1077 // explicitly states that this is not SDCH content, then we can correct our | |
| 1078 // assumption that this is an SDCH response, and avoid the need to recover | |
| 1079 // as though the content is corrupted (when we discover it is not SDCH | |
| 1080 // encoded). | |
| 1081 std::string sdch_response_status; | |
| 1082 iter = NULL; | |
| 1083 while (headers->EnumerateHeader(&iter, "X-Sdch-Encode", | |
| 1084 &sdch_response_status)) { | |
| 1085 if (sdch_response_status == "0") { | |
| 1086 filter_context_->ResetSdchResponseToFalse(); | |
| 1087 break; | |
| 1088 } | |
| 1089 } | |
| 1090 } | |
| 1091 | |
| 1092 // Even if encoding types are empty, there is a chance that we need to add | 1084 // Even if encoding types are empty, there is a chance that we need to add |
| 1093 // some decoding, as some proxies strip encoding completely. In such cases, | 1085 // some decoding, as some proxies strip encoding completely. In such cases, |
| 1094 // we may need to add (for example) SDCH filtering (when the context suggests | 1086 // we may need to add (for example) SDCH filtering (when the context suggests |
| 1095 // it is appropriate). | 1087 // it is appropriate). |
| 1096 Filter::FixupEncodingTypes(*filter_context_, &encoding_types); | 1088 Filter::FixupEncodingTypes(*filter_context_, &encoding_types); |
| 1097 | 1089 |
| 1098 return !encoding_types.empty() | 1090 return !encoding_types.empty() |
| 1099 ? Filter::Factory(encoding_types, *filter_context_) : NULL; | 1091 ? Filter::Factory(encoding_types, *filter_context_) : NULL; |
| 1100 } | 1092 } |
| 1101 | 1093 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1125 // redirect to. | 1117 // redirect to. |
| 1126 return request_->context()->job_factory() && | 1118 return request_->context()->job_factory() && |
| 1127 request_->context()->job_factory()->IsSafeRedirectTarget(location); | 1119 request_->context()->job_factory()->IsSafeRedirectTarget(location); |
| 1128 } | 1120 } |
| 1129 | 1121 |
| 1130 bool URLRequestHttpJob::NeedsAuth() { | 1122 bool URLRequestHttpJob::NeedsAuth() { |
| 1131 int code = GetResponseCode(); | 1123 int code = GetResponseCode(); |
| 1132 if (code == -1) | 1124 if (code == -1) |
| 1133 return false; | 1125 return false; |
| 1134 | 1126 |
| 1135 // Check if we need either Proxy or WWW Authentication. This could happen | 1127 // Check if we need either Proxy or WWW Authentication. This could happen |
| 1136 // because we either provided no auth info, or provided incorrect info. | 1128 // because we either provided no auth info, or provided incorrect info. |
| 1137 switch (code) { | 1129 switch (code) { |
| 1138 case 407: | 1130 case 407: |
| 1139 if (proxy_auth_state_ == AUTH_STATE_CANCELED) | 1131 if (proxy_auth_state_ == AUTH_STATE_CANCELED) |
| 1140 return false; | 1132 return false; |
| 1141 proxy_auth_state_ = AUTH_STATE_NEED_AUTH; | 1133 proxy_auth_state_ = AUTH_STATE_NEED_AUTH; |
| 1142 return true; | 1134 return true; |
| 1143 case 401: | 1135 case 401: |
| 1144 if (server_auth_state_ == AUTH_STATE_CANCELED) | 1136 if (server_auth_state_ == AUTH_STATE_CANCELED) |
| 1145 return false; | 1137 return false; |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1259 weak_factory_.GetWeakPtr(), rv)); | 1251 weak_factory_.GetWeakPtr(), rv)); |
| 1260 } | 1252 } |
| 1261 | 1253 |
| 1262 void URLRequestHttpJob::ResumeNetworkStart() { | 1254 void URLRequestHttpJob::ResumeNetworkStart() { |
| 1263 DCHECK(transaction_.get()); | 1255 DCHECK(transaction_.get()); |
| 1264 transaction_->ResumeNetworkStart(); | 1256 transaction_->ResumeNetworkStart(); |
| 1265 } | 1257 } |
| 1266 | 1258 |
| 1267 bool URLRequestHttpJob::ShouldFixMismatchedContentLength(int rv) const { | 1259 bool URLRequestHttpJob::ShouldFixMismatchedContentLength(int rv) const { |
| 1268 // Some servers send the body compressed, but specify the content length as | 1260 // Some servers send the body compressed, but specify the content length as |
| 1269 // the uncompressed size. Although this violates the HTTP spec we want to | 1261 // the uncompressed size. Although this violates the HTTP spec we want to |
| 1270 // support it (as IE and FireFox do), but *only* for an exact match. | 1262 // support it (as IE and FireFox do), but *only* for an exact match. |
| 1271 // See http://crbug.com/79694. | 1263 // See http://crbug.com/79694. |
| 1272 if (rv == net::ERR_CONTENT_LENGTH_MISMATCH || | 1264 if (rv == net::ERR_CONTENT_LENGTH_MISMATCH || |
| 1273 rv == net::ERR_INCOMPLETE_CHUNKED_ENCODING) { | 1265 rv == net::ERR_INCOMPLETE_CHUNKED_ENCODING) { |
| 1274 if (request_ && request_->response_headers()) { | 1266 if (request_ && request_->response_headers()) { |
| 1275 int64 expected_length = request_->response_headers()->GetContentLength(); | 1267 int64 expected_length = request_->response_headers()->GetContentLength(); |
| 1276 VLOG(1) << __FUNCTION__ << "() " | 1268 VLOG(1) << __FUNCTION__ << "() " |
| 1277 << "\"" << request_->url().spec() << "\"" | 1269 << "\"" << request_->url().spec() << "\"" |
| 1278 << " content-length = " << expected_length | 1270 << " content-length = " << expected_length |
| 1279 << " pre total = " << prefilter_bytes_read() | 1271 << " pre total = " << prefilter_bytes_read() |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1454 DCHECK(request_); | 1446 DCHECK(request_); |
| 1455 if (!request_) | 1447 if (!request_) |
| 1456 return; | 1448 return; |
| 1457 | 1449 |
| 1458 if (is_cached_content_ || // Don't record cached content | 1450 if (is_cached_content_ || // Don't record cached content |
| 1459 !GetStatus().is_success() || // Don't record failed content | 1451 !GetStatus().is_success() || // Don't record failed content |
| 1460 !IsCompressibleContent() || // Only record compressible content | 1452 !IsCompressibleContent() || // Only record compressible content |
| 1461 !prefilter_bytes_read()) // Zero-byte responses aren't useful. | 1453 !prefilter_bytes_read()) // Zero-byte responses aren't useful. |
| 1462 return; | 1454 return; |
| 1463 | 1455 |
| 1464 // Miniature requests aren't really compressible. Don't count them. | 1456 // Miniature requests aren't really compressible. Don't count them. |
| 1465 const int kMinSize = 16; | 1457 const int kMinSize = 16; |
| 1466 if (prefilter_bytes_read() < kMinSize) | 1458 if (prefilter_bytes_read() < kMinSize) |
| 1467 return; | 1459 return; |
| 1468 | 1460 |
| 1469 // Only record for http or https urls. | 1461 // Only record for http or https urls. |
| 1470 bool is_http = request_->url().SchemeIs("http"); | 1462 bool is_http = request_->url().SchemeIs("http"); |
| 1471 bool is_https = request_->url().SchemeIs("https"); | 1463 bool is_https = request_->url().SchemeIs("https"); |
| 1472 if (!is_http && !is_https) | 1464 if (!is_http && !is_https) |
| 1473 return; | 1465 return; |
| 1474 | 1466 |
| 1475 int compressed_B = prefilter_bytes_read(); | 1467 int compressed_B = prefilter_bytes_read(); |
| 1476 int decompressed_B = postfilter_bytes_read(); | 1468 int decompressed_B = postfilter_bytes_read(); |
| 1477 bool was_filtered = HasFilter(); | 1469 bool was_filtered = HasFilter(); |
| 1478 | 1470 |
| 1479 // We want to record how often downloaded resources are compressed. | 1471 // We want to record how often downloaded resources are compressed. |
| 1480 // But, we recognize that different protocols may have different | 1472 // But, we recognize that different protocols may have different |
| 1481 // properties. So, for each request, we'll put it into one of 3 | 1473 // properties. So, for each request, we'll put it into one of 3 |
| 1482 // groups: | 1474 // groups: |
| 1483 // a) SSL resources | 1475 // a) SSL resources |
| 1484 // Proxies cannot tamper with compression headers with SSL. | 1476 // Proxies cannot tamper with compression headers with SSL. |
| 1485 // b) Non-SSL, loaded-via-proxy resources | 1477 // b) Non-SSL, loaded-via-proxy resources |
| 1486 // In this case, we know a proxy might have interfered. | 1478 // In this case, we know a proxy might have interfered. |
| 1487 // c) Non-SSL, loaded-without-proxy resources | 1479 // c) Non-SSL, loaded-without-proxy resources |
| 1488 // In this case, we know there was no explicit proxy. However, | 1480 // In this case, we know there was no explicit proxy. However, |
| 1489 // it is possible that a transparent proxy was still interfering. | 1481 // it is possible that a transparent proxy was still interfering. |
| 1490 // | 1482 // |
| 1491 // For each group, we record the same 3 histograms. | 1483 // For each group, we record the same 3 histograms. |
| 1492 | 1484 |
| 1493 if (is_https) { | 1485 if (is_https) { |
| 1494 if (was_filtered) { | 1486 if (was_filtered) { |
| 1495 COMPRESSION_HISTOGRAM("SSL.BytesBeforeCompression", compressed_B); | 1487 COMPRESSION_HISTOGRAM("SSL.BytesBeforeCompression", compressed_B); |
| 1496 COMPRESSION_HISTOGRAM("SSL.BytesAfterCompression", decompressed_B); | 1488 COMPRESSION_HISTOGRAM("SSL.BytesAfterCompression", decompressed_B); |
| 1497 } else { | 1489 } else { |
| 1498 COMPRESSION_HISTOGRAM("SSL.ShouldHaveBeenCompressed", decompressed_B); | 1490 COMPRESSION_HISTOGRAM("SSL.ShouldHaveBeenCompressed", decompressed_B); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1570 return override_response_headers_.get() ? | 1562 return override_response_headers_.get() ? |
| 1571 override_response_headers_.get() : | 1563 override_response_headers_.get() : |
| 1572 transaction_->GetResponseInfo()->headers.get(); | 1564 transaction_->GetResponseInfo()->headers.get(); |
| 1573 } | 1565 } |
| 1574 | 1566 |
| 1575 void URLRequestHttpJob::NotifyURLRequestDestroyed() { | 1567 void URLRequestHttpJob::NotifyURLRequestDestroyed() { |
| 1576 awaiting_callback_ = false; | 1568 awaiting_callback_ = false; |
| 1577 } | 1569 } |
| 1578 | 1570 |
| 1579 } // namespace net | 1571 } // namespace net |
| OLD | NEW |