Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(241)

Side by Side Diff: net/url_request/url_request_http_job.cc

Issue 711753003: Pin dictionaries from being deleted while request is outstanding. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Incorporated comments; fixed try job errors. Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 explicit HttpFilterContext(URLRequestHttpJob* job); 58 explicit HttpFilterContext(URLRequestHttpJob* job);
59 ~HttpFilterContext() override; 59 ~HttpFilterContext() override;
60 60
61 // FilterContext implementation. 61 // FilterContext implementation.
62 bool GetMimeType(std::string* mime_type) const override; 62 bool GetMimeType(std::string* mime_type) const override;
63 bool GetURL(GURL* gurl) const override; 63 bool GetURL(GURL* gurl) const override;
64 bool GetContentDisposition(std::string* disposition) const override; 64 bool GetContentDisposition(std::string* disposition) const override;
65 base::Time GetRequestTime() const override; 65 base::Time GetRequestTime() const override;
66 bool IsCachedContent() const override; 66 bool IsCachedContent() const override;
67 bool IsDownload() const override; 67 bool IsDownload() const override;
68 bool SdchResponseExpected() const override; 68 SdchManager::DictionarySet* SdchDictionariesAdvertised() const override;
69 int64 GetByteReadCount() const override; 69 int64 GetByteReadCount() const override;
70 int GetResponseCode() const override; 70 int GetResponseCode() const override;
71 const URLRequestContext* GetURLRequestContext() const override; 71 const URLRequestContext* GetURLRequestContext() const override;
72 void RecordPacketStats(StatisticSelector statistic) const override; 72 void RecordPacketStats(StatisticSelector statistic) const override;
73 73
74 // Method to allow us to reset filter context for a response that should have
75 // been SDCH encoded when there is an update due to an explicit HTTP header.
76 void ResetSdchResponseToFalse();
77
78 private: 74 private:
79 URLRequestHttpJob* job_; 75 URLRequestHttpJob* job_;
80 76
81 DISALLOW_COPY_AND_ASSIGN(HttpFilterContext); 77 DISALLOW_COPY_AND_ASSIGN(HttpFilterContext);
82 }; 78 };
83 79
84 URLRequestHttpJob::HttpFilterContext::HttpFilterContext(URLRequestHttpJob* job) 80 URLRequestHttpJob::HttpFilterContext::HttpFilterContext(URLRequestHttpJob* job)
85 : job_(job) { 81 : job_(job) {
86 DCHECK(job_); 82 DCHECK(job_);
87 } 83 }
(...skipping 25 matching lines...) Expand all
113 } 109 }
114 110
115 bool URLRequestHttpJob::HttpFilterContext::IsCachedContent() const { 111 bool URLRequestHttpJob::HttpFilterContext::IsCachedContent() const {
116 return job_->is_cached_content_; 112 return job_->is_cached_content_;
117 } 113 }
118 114
119 bool URLRequestHttpJob::HttpFilterContext::IsDownload() const { 115 bool URLRequestHttpJob::HttpFilterContext::IsDownload() const {
120 return (job_->request_info_.load_flags & LOAD_IS_DOWNLOAD) != 0; 116 return (job_->request_info_.load_flags & LOAD_IS_DOWNLOAD) != 0;
121 } 117 }
122 118
123 void URLRequestHttpJob::HttpFilterContext::ResetSdchResponseToFalse() { 119 SdchManager::DictionarySet*
124 DCHECK(job_->sdch_dictionary_advertised_); 120 URLRequestHttpJob::HttpFilterContext::SdchDictionariesAdvertised() const {
125 job_->sdch_dictionary_advertised_ = false; 121 return job_->dictionaries_advertised_.get();
126 }
127
128 bool URLRequestHttpJob::HttpFilterContext::SdchResponseExpected() const {
129 return job_->sdch_dictionary_advertised_;
130 } 122 }
131 123
132 int64 URLRequestHttpJob::HttpFilterContext::GetByteReadCount() const { 124 int64 URLRequestHttpJob::HttpFilterContext::GetByteReadCount() const {
133 return job_->filter_input_byte_count(); 125 return job_->filter_input_byte_count();
134 } 126 }
135 127
136 int URLRequestHttpJob::HttpFilterContext::GetResponseCode() const { 128 int URLRequestHttpJob::HttpFilterContext::GetResponseCode() const {
137 return job_->GetResponseCode(); 129 return job_->GetResponseCode();
138 } 130 }
139 131
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
183 response_cookies_save_index_(0), 175 response_cookies_save_index_(0),
184 proxy_auth_state_(AUTH_STATE_DONT_NEED_AUTH), 176 proxy_auth_state_(AUTH_STATE_DONT_NEED_AUTH),
185 server_auth_state_(AUTH_STATE_DONT_NEED_AUTH), 177 server_auth_state_(AUTH_STATE_DONT_NEED_AUTH),
186 start_callback_(base::Bind(&URLRequestHttpJob::OnStartCompleted, 178 start_callback_(base::Bind(&URLRequestHttpJob::OnStartCompleted,
187 base::Unretained(this))), 179 base::Unretained(this))),
188 notify_before_headers_sent_callback_( 180 notify_before_headers_sent_callback_(
189 base::Bind(&URLRequestHttpJob::NotifyBeforeSendHeadersCallback, 181 base::Bind(&URLRequestHttpJob::NotifyBeforeSendHeadersCallback,
190 base::Unretained(this))), 182 base::Unretained(this))),
191 read_in_progress_(false), 183 read_in_progress_(false),
192 throttling_entry_(NULL), 184 throttling_entry_(NULL),
193 sdch_dictionary_advertised_(false),
194 sdch_test_activated_(false), 185 sdch_test_activated_(false),
195 sdch_test_control_(false), 186 sdch_test_control_(false),
196 is_cached_content_(false), 187 is_cached_content_(false),
197 request_creation_time_(), 188 request_creation_time_(),
198 packet_timing_enabled_(false), 189 packet_timing_enabled_(false),
199 done_(false), 190 done_(false),
200 bytes_observed_in_packets_(0), 191 bytes_observed_in_packets_(0),
201 request_time_snapshot_(), 192 request_time_snapshot_(),
202 final_packet_time_(), 193 final_packet_time_(),
203 filter_context_(new HttpFilterContext(this)), 194 filter_context_(new HttpFilterContext(this)),
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 if (!is_cached_content_ && throttling_entry_.get()) { 304 if (!is_cached_content_ && throttling_entry_.get()) {
314 URLRequestThrottlerHeaderAdapter response_adapter(GetResponseHeaders()); 305 URLRequestThrottlerHeaderAdapter response_adapter(GetResponseHeaders());
315 throttling_entry_->UpdateWithResponse(request_info_.url.host(), 306 throttling_entry_->UpdateWithResponse(request_info_.url.host(),
316 &response_adapter); 307 &response_adapter);
317 } 308 }
318 309
319 // The ordering of these calls is not important. 310 // The ordering of these calls is not important.
320 ProcessStrictTransportSecurityHeader(); 311 ProcessStrictTransportSecurityHeader();
321 ProcessPublicKeyPinsHeader(); 312 ProcessPublicKeyPinsHeader();
322 313
314 // Handle the server notification of a new SDCH dictionary.
323 SdchManager* sdch_manager(request()->context()->sdch_manager()); 315 SdchManager* sdch_manager(request()->context()->sdch_manager());
324 if (sdch_manager && sdch_manager->IsInSupportedDomain(request_->url())) { 316 if (sdch_manager && sdch_manager->IsInSupportedDomain(request_->url())) {
325 const std::string name = "Get-Dictionary"; 317 const std::string name = "Get-Dictionary";
326 std::string url_text; 318 std::string url_text;
327 void* iter = NULL; 319 void* iter = NULL;
328 // TODO(jar): We need to not fetch dictionaries the first time they are 320 // TODO(jar): We need to not fetch dictionaries the first time they are
329 // seen, but rather wait until we can justify their usefulness. 321 // seen, but rather wait until we can justify their usefulness.
330 // For now, we will only fetch the first dictionary, which will at least 322 // For now, we will only fetch the first dictionary, which will at least
331 // require multiple suggestions before we get additional ones for this site. 323 // require multiple suggestions before we get additional ones for this site.
332 // Eventually we should wait until a dictionary is requested several times 324 // Eventually we should wait until a dictionary is requested several times
333 // before we even download it (so that we don't waste memory or bandwidth). 325 // before we even download it (so that we don't waste memory or bandwidth).
334 if (GetResponseHeaders()->EnumerateHeader(&iter, name, &url_text)) { 326 if (GetResponseHeaders()->EnumerateHeader(&iter, name, &url_text)) {
335 // Resolve suggested URL relative to request url. 327 // Resolve suggested URL relative to request url.
336 GURL sdch_dictionary_url = request_->url().Resolve(url_text); 328 GURL sdch_dictionary_url = request_->url().Resolve(url_text);
337 if (sdch_dictionary_url.is_valid()) { 329 if (sdch_dictionary_url.is_valid()) {
338 sdch_manager->OnGetDictionary(request_->url(), sdch_dictionary_url); 330 sdch_manager->OnGetDictionary(request_->url(), sdch_dictionary_url);
339 } 331 }
340 } 332 }
341 } 333 }
342 334
335 // Handle the server signalling no SDCH encoding.
336 if (dictionaries_advertised_.get()) {
337 // We are wary of proxies that discard or damage SDCH encoding. If a server
338 // explicitly states that this is not SDCH content, then we can correct our
339 // assumption that this is an SDCH response, and avoid the need to recover
340 // as though the content is corrupted (when we discover it is not SDCH
341 // encoded).
342 std::string sdch_response_status;
343 void* iter = NULL;
344 while (GetResponseHeaders()->EnumerateHeader(&iter, "X-Sdch-Encode",
345 &sdch_response_status)) {
346 if (sdch_response_status == "0") {
347 dictionaries_advertised_.reset();
348 break;
349 }
350 }
351 }
352
343 // The HTTP transaction may be restarted several times for the purposes 353 // The HTTP transaction may be restarted several times for the purposes
344 // of sending authorization information. Each time it restarts, we get 354 // of sending authorization information. Each time it restarts, we get
345 // notified of the headers completion so that we can update the cookie store. 355 // notified of the headers completion so that we can update the cookie store.
346 if (transaction_->IsReadyToRestartForAuth()) { 356 if (transaction_->IsReadyToRestartForAuth()) {
347 DCHECK(!response_info_->auth_challenge.get()); 357 DCHECK(!response_info_->auth_challenge.get());
348 // TODO(battre): This breaks the webrequest API for 358 // TODO(battre): This breaks the webrequest API for
349 // URLRequestTestHTTP.BasicAuthWithCookies 359 // URLRequestTestHTTP.BasicAuthWithCookies
350 // where OnBeforeSendHeaders -> OnSendHeaders -> OnBeforeSendHeaders 360 // where OnBeforeSendHeaders -> OnSendHeaders -> OnBeforeSendHeaders
351 // occurs. 361 // occurs.
352 RestartTransactionWithAuth(AuthCredentials()); 362 RestartTransactionWithAuth(AuthCredentials());
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
483 // simple_data_source. 493 // simple_data_source.
484 if (!request_info_.extra_headers.HasHeader( 494 if (!request_info_.extra_headers.HasHeader(
485 HttpRequestHeaders::kAcceptEncoding)) { 495 HttpRequestHeaders::kAcceptEncoding)) {
486 bool advertise_sdch = sdch_manager && 496 bool advertise_sdch = sdch_manager &&
487 // We don't support SDCH responses to POST as there is a possibility 497 // We don't support SDCH responses to POST as there is a possibility
488 // of having SDCH encoded responses returned (e.g. by the cache) 498 // of having SDCH encoded responses returned (e.g. by the cache)
489 // which we cannot decode, and in those situations, we will need 499 // which we cannot decode, and in those situations, we will need
490 // to retransmit the request without SDCH, which is illegal for a POST. 500 // to retransmit the request without SDCH, which is illegal for a POST.
491 request()->method() != "POST" && 501 request()->method() != "POST" &&
492 sdch_manager->IsInSupportedDomain(request_->url()); 502 sdch_manager->IsInSupportedDomain(request_->url());
493 std::string avail_dictionaries;
494 if (advertise_sdch) { 503 if (advertise_sdch) {
495 sdch_manager->GetAvailDictionaryList(request_->url(), 504 dictionaries_advertised_ =
496 &avail_dictionaries); 505 sdch_manager->GetDictionarySet(request_->url());
506 }
497 507
498 // The AllowLatencyExperiment() is only true if we've successfully done a 508 // The AllowLatencyExperiment() is only true if we've successfully done a
499 // full SDCH compression recently in this browser session for this host. 509 // full SDCH compression recently in this browser session for this host.
500 // Note that for this path, there might be no applicable dictionaries, 510 // Note that for this path, there might be no applicable dictionaries,
501 // and hence we can't participate in the experiment. 511 // and hence we can't participate in the experiment.
502 if (!avail_dictionaries.empty() && 512 if (dictionaries_advertised_.get() &&
503 sdch_manager->AllowLatencyExperiment(request_->url())) { 513 sdch_manager->AllowLatencyExperiment(request_->url())) {
504 // We are participating in the test (or control), and hence we'll 514 // We are participating in the test (or control), and hence we'll
505 // eventually record statistics via either SDCH_EXPERIMENT_DECODE or 515 // eventually record statistics via either SDCH_EXPERIMENT_DECODE or
506 // SDCH_EXPERIMENT_HOLDBACK, and we'll need some packet timing data. 516 // SDCH_EXPERIMENT_HOLDBACK, and we'll need some packet timing data.
507 packet_timing_enabled_ = true; 517 packet_timing_enabled_ = true;
508 if (base::RandDouble() < .01) { 518 if (base::RandDouble() < .01) {
509 sdch_test_control_ = true; // 1% probability. 519 sdch_test_control_ = true; // 1% probability.
510 advertise_sdch = false; 520 dictionaries_advertised_.reset();
511 } else { 521 advertise_sdch = false;
512 sdch_test_activated_ = true; 522 } else {
513 } 523 sdch_test_activated_ = true;
514 } 524 }
515 } 525 }
516 526
517 // Supply Accept-Encoding headers first so that it is more likely that they 527 // Supply Accept-Encoding headers first so that it is more likely that they
518 // will be in the first transmitted packet. This can sometimes make it 528 // will be in the first transmitted packet. This can sometimes make it
519 // easier to filter and analyze the streams to assure that a proxy has not 529 // easier to filter and analyze the streams to assure that a proxy has not
520 // damaged these headers. Some proxies deliberately corrupt Accept-Encoding 530 // damaged these headers. Some proxies deliberately corrupt Accept-Encoding
521 // headers. 531 // headers.
522 if (!advertise_sdch) { 532 if (!advertise_sdch) {
523 // Tell the server what compression formats we support (other than SDCH). 533 // Tell the server what compression formats we support (other than SDCH).
524 request_info_.extra_headers.SetHeader( 534 request_info_.extra_headers.SetHeader(
525 HttpRequestHeaders::kAcceptEncoding, "gzip, deflate"); 535 HttpRequestHeaders::kAcceptEncoding, "gzip, deflate");
526 } else { 536 } else {
527 // Include SDCH in acceptable list. 537 // Include SDCH in acceptable list.
528 request_info_.extra_headers.SetHeader( 538 request_info_.extra_headers.SetHeader(
529 HttpRequestHeaders::kAcceptEncoding, "gzip, deflate, sdch"); 539 HttpRequestHeaders::kAcceptEncoding, "gzip, deflate, sdch");
530 if (!avail_dictionaries.empty()) { 540 if (dictionaries_advertised_.get()) {
541 std::string avail_dictionaries;
542 dictionaries_advertised_->GetDictionaryClientHashList(
543 &avail_dictionaries);
544
531 request_info_.extra_headers.SetHeader( 545 request_info_.extra_headers.SetHeader(
532 kAvailDictionaryHeader, 546 kAvailDictionaryHeader,
533 avail_dictionaries); 547 avail_dictionaries);
534 sdch_dictionary_advertised_ = true;
535 // Since we're tagging this transaction as advertising a dictionary, 548 // Since we're tagging this transaction as advertising a dictionary,
536 // we'll definitely employ an SDCH filter (or tentative sdch filter) 549 // we'll definitely employ an SDCH filter (or tentative sdch filter)
537 // when we get a response. When done, we'll record histograms via 550 // when we get a response. When done, we'll record histograms via
538 // SDCH_DECODE or SDCH_PASSTHROUGH. Hence we need to record packet 551 // SDCH_DECODE or SDCH_PASSTHROUGH. Hence we need to record packet
539 // arrival times. 552 // arrival times.
540 packet_timing_enabled_ = true; 553 packet_timing_enabled_ = true;
541 } 554 }
542 } 555 }
543 } 556 }
544 557
(...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after
1023 return NULL; 1036 return NULL;
1024 1037
1025 std::vector<Filter::FilterType> encoding_types; 1038 std::vector<Filter::FilterType> encoding_types;
1026 std::string encoding_type; 1039 std::string encoding_type;
1027 HttpResponseHeaders* headers = GetResponseHeaders(); 1040 HttpResponseHeaders* headers = GetResponseHeaders();
1028 void* iter = NULL; 1041 void* iter = NULL;
1029 while (headers->EnumerateHeader(&iter, "Content-Encoding", &encoding_type)) { 1042 while (headers->EnumerateHeader(&iter, "Content-Encoding", &encoding_type)) {
1030 encoding_types.push_back(Filter::ConvertEncodingToType(encoding_type)); 1043 encoding_types.push_back(Filter::ConvertEncodingToType(encoding_type));
1031 } 1044 }
1032 1045
1033 if (filter_context_->SdchResponseExpected()) {
1034 // We are wary of proxies that discard or damage SDCH encoding. If a server
1035 // explicitly states that this is not SDCH content, then we can correct our
1036 // assumption that this is an SDCH response, and avoid the need to recover
1037 // as though the content is corrupted (when we discover it is not SDCH
1038 // encoded).
1039 std::string sdch_response_status;
1040 iter = NULL;
1041 while (headers->EnumerateHeader(&iter, "X-Sdch-Encode",
1042 &sdch_response_status)) {
1043 if (sdch_response_status == "0") {
1044 filter_context_->ResetSdchResponseToFalse();
1045 break;
1046 }
1047 }
1048 }
1049
1050 // Even if encoding types are empty, there is a chance that we need to add 1046 // Even if encoding types are empty, there is a chance that we need to add
1051 // some decoding, as some proxies strip encoding completely. In such cases, 1047 // some decoding, as some proxies strip encoding completely. In such cases,
1052 // we may need to add (for example) SDCH filtering (when the context suggests 1048 // we may need to add (for example) SDCH filtering (when the context suggests
1053 // it is appropriate). 1049 // it is appropriate).
1054 Filter::FixupEncodingTypes(*filter_context_, &encoding_types); 1050 Filter::FixupEncodingTypes(*filter_context_, &encoding_types);
1055 1051
1056 return !encoding_types.empty() 1052 return !encoding_types.empty()
1057 ? Filter::Factory(encoding_types, *filter_context_) : NULL; 1053 ? Filter::Factory(encoding_types, *filter_context_) : NULL;
1058 } 1054 }
1059 1055
(...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after
1528 return override_response_headers_.get() ? 1524 return override_response_headers_.get() ?
1529 override_response_headers_.get() : 1525 override_response_headers_.get() :
1530 transaction_->GetResponseInfo()->headers.get(); 1526 transaction_->GetResponseInfo()->headers.get();
1531 } 1527 }
1532 1528
1533 void URLRequestHttpJob::NotifyURLRequestDestroyed() { 1529 void URLRequestHttpJob::NotifyURLRequestDestroyed() {
1534 awaiting_callback_ = false; 1530 awaiting_callback_ = false;
1535 } 1531 }
1536 1532
1537 } // namespace net 1533 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698