| 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/file_version_info.h" | 12 #include "base/file_version_info.h" | 
| 13 #include "base/message_loop/message_loop.h" | 13 #include "base/message_loop/message_loop.h" | 
| 14 #include "base/metrics/field_trial.h" | 14 #include "base/metrics/field_trial.h" | 
| 15 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" | 
| 16 #include "base/profiler/scoped_tracker.h" | 16 #include "base/profiler/scoped_tracker.h" | 
| 17 #include "base/rand_util.h" | 17 #include "base/rand_util.h" | 
| 18 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" | 
| 19 #include "base/time/time.h" | 19 #include "base/time/time.h" | 
| 20 #include "net/base/host_port_pair.h" | 20 #include "net/base/host_port_pair.h" | 
| 21 #include "net/base/load_flags.h" | 21 #include "net/base/load_flags.h" | 
| 22 #include "net/base/mime_util.h" | 22 #include "net/base/mime_util.h" | 
| 23 #include "net/base/net_errors.h" | 23 #include "net/base/net_errors.h" | 
| 24 #include "net/base/net_util.h" | 24 #include "net/base/net_util.h" | 
| 25 #include "net/base/network_delegate.h" | 25 #include "net/base/network_delegate.h" | 
| 26 #include "net/base/sdch_manager.h" | 26 #include "net/base/sdch_manager.h" | 
|  | 27 #include "net/base/sdch_net_log_params.h" | 
| 27 #include "net/cert/cert_status_flags.h" | 28 #include "net/cert/cert_status_flags.h" | 
| 28 #include "net/cookies/cookie_store.h" | 29 #include "net/cookies/cookie_store.h" | 
| 29 #include "net/http/http_content_disposition.h" | 30 #include "net/http/http_content_disposition.h" | 
| 30 #include "net/http/http_network_session.h" | 31 #include "net/http/http_network_session.h" | 
| 31 #include "net/http/http_request_headers.h" | 32 #include "net/http/http_request_headers.h" | 
| 32 #include "net/http/http_response_headers.h" | 33 #include "net/http/http_response_headers.h" | 
| 33 #include "net/http/http_response_info.h" | 34 #include "net/http/http_response_info.h" | 
| 34 #include "net/http/http_status_code.h" | 35 #include "net/http/http_status_code.h" | 
| 35 #include "net/http/http_transaction.h" | 36 #include "net/http/http_transaction.h" | 
| 36 #include "net/http/http_transaction_factory.h" | 37 #include "net/http/http_transaction_factory.h" | 
| (...skipping 26 matching lines...) Expand all  Loading... | 
| 63   bool GetURL(GURL* gurl) const override; | 64   bool GetURL(GURL* gurl) const override; | 
| 64   bool GetContentDisposition(std::string* disposition) const override; | 65   bool GetContentDisposition(std::string* disposition) const override; | 
| 65   base::Time GetRequestTime() const override; | 66   base::Time GetRequestTime() const override; | 
| 66   bool IsCachedContent() const override; | 67   bool IsCachedContent() const override; | 
| 67   bool IsDownload() const override; | 68   bool IsDownload() const override; | 
| 68   bool SdchResponseExpected() const override; | 69   bool SdchResponseExpected() const override; | 
| 69   int64 GetByteReadCount() const override; | 70   int64 GetByteReadCount() const override; | 
| 70   int GetResponseCode() const override; | 71   int GetResponseCode() const override; | 
| 71   const URLRequestContext* GetURLRequestContext() const override; | 72   const URLRequestContext* GetURLRequestContext() const override; | 
| 72   void RecordPacketStats(StatisticSelector statistic) const override; | 73   void RecordPacketStats(StatisticSelector statistic) const override; | 
|  | 74   const BoundNetLog& GetNetLog() const override; | 
| 73 | 75 | 
| 74   // Method to allow us to reset filter context for a response that should have | 76   // 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. | 77   // been SDCH encoded when there is an update due to an explicit HTTP header. | 
| 76   void ResetSdchResponseToFalse(); | 78   void ResetSdchResponseToFalse(); | 
| 77 | 79 | 
| 78  private: | 80  private: | 
| 79   URLRequestHttpJob* job_; | 81   URLRequestHttpJob* job_; | 
| 80 | 82 | 
|  | 83   // URLRequestHttpJob may be detached from URLRequest, but we still need to | 
|  | 84   // return something. | 
|  | 85   BoundNetLog dummy_log_; | 
|  | 86 | 
| 81   DISALLOW_COPY_AND_ASSIGN(HttpFilterContext); | 87   DISALLOW_COPY_AND_ASSIGN(HttpFilterContext); | 
| 82 }; | 88 }; | 
| 83 | 89 | 
| 84 URLRequestHttpJob::HttpFilterContext::HttpFilterContext(URLRequestHttpJob* job) | 90 URLRequestHttpJob::HttpFilterContext::HttpFilterContext(URLRequestHttpJob* job) | 
| 85     : job_(job) { | 91     : job_(job) { | 
| 86   DCHECK(job_); | 92   DCHECK(job_); | 
| 87 } | 93 } | 
| 88 | 94 | 
| 89 URLRequestHttpJob::HttpFilterContext::~HttpFilterContext() { | 95 URLRequestHttpJob::HttpFilterContext::~HttpFilterContext() { | 
| 90 } | 96 } | 
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 140 const URLRequestContext* | 146 const URLRequestContext* | 
| 141 URLRequestHttpJob::HttpFilterContext::GetURLRequestContext() const { | 147 URLRequestHttpJob::HttpFilterContext::GetURLRequestContext() const { | 
| 142   return job_->request() ? job_->request()->context() : NULL; | 148   return job_->request() ? job_->request()->context() : NULL; | 
| 143 } | 149 } | 
| 144 | 150 | 
| 145 void URLRequestHttpJob::HttpFilterContext::RecordPacketStats( | 151 void URLRequestHttpJob::HttpFilterContext::RecordPacketStats( | 
| 146     StatisticSelector statistic) const { | 152     StatisticSelector statistic) const { | 
| 147   job_->RecordPacketStats(statistic); | 153   job_->RecordPacketStats(statistic); | 
| 148 } | 154 } | 
| 149 | 155 | 
|  | 156 const BoundNetLog& URLRequestHttpJob::HttpFilterContext::GetNetLog() const { | 
|  | 157   return job_->request() ? job_->request()->net_log() : dummy_log_; | 
|  | 158 } | 
|  | 159 | 
| 150 // TODO(darin): make sure the port blocking code is not lost | 160 // TODO(darin): make sure the port blocking code is not lost | 
| 151 // static | 161 // static | 
| 152 URLRequestJob* URLRequestHttpJob::Factory(URLRequest* request, | 162 URLRequestJob* URLRequestHttpJob::Factory(URLRequest* request, | 
| 153                                           NetworkDelegate* network_delegate, | 163                                           NetworkDelegate* network_delegate, | 
| 154                                           const std::string& scheme) { | 164                                           const std::string& scheme) { | 
| 155   DCHECK(scheme == "http" || scheme == "https" || scheme == "ws" || | 165   DCHECK(scheme == "http" || scheme == "https" || scheme == "ws" || | 
| 156          scheme == "wss"); | 166          scheme == "wss"); | 
| 157 | 167 | 
| 158   if (!request->context()->http_transaction_factory()) { | 168   if (!request->context()->http_transaction_factory()) { | 
| 159     NOTREACHED() << "requires a valid context"; | 169     NOTREACHED() << "requires a valid context"; | 
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 314     URLRequestThrottlerHeaderAdapter response_adapter(GetResponseHeaders()); | 324     URLRequestThrottlerHeaderAdapter response_adapter(GetResponseHeaders()); | 
| 315     throttling_entry_->UpdateWithResponse(request_info_.url.host(), | 325     throttling_entry_->UpdateWithResponse(request_info_.url.host(), | 
| 316                                           &response_adapter); | 326                                           &response_adapter); | 
| 317   } | 327   } | 
| 318 | 328 | 
| 319   // The ordering of these calls is not important. | 329   // The ordering of these calls is not important. | 
| 320   ProcessStrictTransportSecurityHeader(); | 330   ProcessStrictTransportSecurityHeader(); | 
| 321   ProcessPublicKeyPinsHeader(); | 331   ProcessPublicKeyPinsHeader(); | 
| 322 | 332 | 
| 323   SdchManager* sdch_manager(request()->context()->sdch_manager()); | 333   SdchManager* sdch_manager(request()->context()->sdch_manager()); | 
| 324   if (sdch_manager && sdch_manager->IsInSupportedDomain(request_->url())) { | 334   if (sdch_manager) { | 
| 325     const std::string name = "Get-Dictionary"; | 335     SdchProblemCode rv = sdch_manager->IsInSupportedDomain(request()->url()); | 
| 326     std::string url_text; | 336     if (rv != SDCH_OK) { | 
| 327     void* iter = NULL; | 337       // If SDCH is just disabled, it is not a real error. | 
| 328     // TODO(jar): We need to not fetch dictionaries the first time they are | 338       if (rv != SDCH_DISABLED && rv != SDCH_SECURE_SCHEME_NOT_SUPPORTED) { | 
| 329     // seen, but rather wait until we can justify their usefulness. | 339         SdchManager::SdchErrorRecovery(rv); | 
| 330     // For now, we will only fetch the first dictionary, which will at least | 340         request()->net_log().AddEvent( | 
| 331     // require multiple suggestions before we get additional ones for this site. | 341             NetLog::TYPE_SDCH_DECODING_ERROR, | 
| 332     // Eventually we should wait until a dictionary is requested several times | 342             base::Bind(&NetLogSdchResourceProblemCallback, rv)); | 
| 333     // before we even download it (so that we don't waste memory or bandwidth). | 343       } | 
| 334     if (GetResponseHeaders()->EnumerateHeader(&iter, name, &url_text)) { | 344     } else { | 
| 335       // Resolve suggested URL relative to request url. | 345       const std::string name = "Get-Dictionary"; | 
| 336       GURL sdch_dictionary_url = request_->url().Resolve(url_text); | 346       std::string url_text; | 
| 337       if (sdch_dictionary_url.is_valid()) { | 347       void* iter = NULL; | 
| 338         sdch_manager->OnGetDictionary(request_->url(), sdch_dictionary_url); | 348       // TODO(jar): We need to not fetch dictionaries the first time they are | 
|  | 349       // seen, but rather wait until we can justify their usefulness. | 
|  | 350       // For now, we will only fetch the first dictionary, which will at least | 
|  | 351       // require multiple suggestions before we get additional ones for this | 
|  | 352       // site. Eventually we should wait until a dictionary is requested | 
|  | 353       // several times | 
|  | 354       // before we even download it (so that we don't waste memory or | 
|  | 355       // bandwidth). | 
|  | 356       if (GetResponseHeaders()->EnumerateHeader(&iter, name, &url_text)) { | 
|  | 357         // Resolve suggested URL relative to request url. | 
|  | 358         GURL sdch_dictionary_url = request_->url().Resolve(url_text); | 
|  | 359         if (sdch_dictionary_url.is_valid()) { | 
|  | 360           rv = sdch_manager->OnGetDictionary(request_->url(), | 
|  | 361                                              sdch_dictionary_url); | 
|  | 362           if (rv != SDCH_OK) { | 
|  | 363             SdchManager::SdchErrorRecovery(rv); | 
|  | 364             request_->net_log().AddEvent( | 
|  | 365                 NetLog::TYPE_SDCH_DICTIONARY_ERROR, | 
|  | 366                 base::Bind(&NetLogSdchDictionaryFetchProblemCallback, rv, | 
|  | 367                            sdch_dictionary_url, false)); | 
|  | 368           } | 
|  | 369         } | 
| 339       } | 370       } | 
| 340     } | 371     } | 
| 341   } | 372   } | 
| 342 | 373 | 
| 343   // The HTTP transaction may be restarted several times for the purposes | 374   // The HTTP transaction may be restarted several times for the purposes | 
| 344   // of sending authorization information. Each time it restarts, we get | 375   // of sending authorization information. Each time it restarts, we get | 
| 345   // notified of the headers completion so that we can update the cookie store. | 376   // notified of the headers completion so that we can update the cookie store. | 
| 346   if (transaction_->IsReadyToRestartForAuth()) { | 377   if (transaction_->IsReadyToRestartForAuth()) { | 
| 347     DCHECK(!response_info_->auth_challenge.get()); | 378     DCHECK(!response_info_->auth_challenge.get()); | 
| 348     // TODO(battre): This breaks the webrequest API for | 379     // TODO(battre): This breaks the webrequest API for | 
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 476 | 507 | 
| 477   // Supply Accept-Encoding field only if it is not already provided. | 508   // Supply Accept-Encoding field only if it is not already provided. | 
| 478   // It should be provided IF the content is known to have restrictions on | 509   // It should be provided IF the content is known to have restrictions on | 
| 479   // potential encoding, such as streaming multi-media. | 510   // potential encoding, such as streaming multi-media. | 
| 480   // For details see bug 47381. | 511   // For details see bug 47381. | 
| 481   // TODO(jar, enal): jpeg files etc. should set up a request header if | 512   // TODO(jar, enal): jpeg files etc. should set up a request header if | 
| 482   // possible. Right now it is done only by buffered_resource_loader and | 513   // possible. Right now it is done only by buffered_resource_loader and | 
| 483   // simple_data_source. | 514   // simple_data_source. | 
| 484   if (!request_info_.extra_headers.HasHeader( | 515   if (!request_info_.extra_headers.HasHeader( | 
| 485       HttpRequestHeaders::kAcceptEncoding)) { | 516       HttpRequestHeaders::kAcceptEncoding)) { | 
| 486     bool advertise_sdch = sdch_manager && | 517     // We don't support SDCH responses to POST as there is a possibility | 
| 487         // We don't support SDCH responses to POST as there is a possibility | 518     // of having SDCH encoded responses returned (e.g. by the cache) | 
| 488         // of having SDCH encoded responses returned (e.g. by the cache) | 519     // which we cannot decode, and in those situations, we will need | 
| 489         // which we cannot decode, and in those situations, we will need | 520     // to retransmit the request without SDCH, which is illegal for a POST. | 
| 490         // to retransmit the request without SDCH, which is illegal for a POST. | 521     bool advertise_sdch = sdch_manager != NULL && request()->method() != "POST"; | 
| 491         request()->method() != "POST" && | 522     if (advertise_sdch) { | 
| 492         sdch_manager->IsInSupportedDomain(request_->url()); | 523       SdchProblemCode rv = sdch_manager->IsInSupportedDomain(request()->url()); | 
|  | 524       if (rv != SDCH_OK) { | 
|  | 525         advertise_sdch = false; | 
|  | 526         // If SDCH is just disabled, it is not a real error. | 
|  | 527         if (rv != SDCH_DISABLED && rv != SDCH_SECURE_SCHEME_NOT_SUPPORTED) { | 
|  | 528           SdchManager::SdchErrorRecovery(rv); | 
|  | 529           request()->net_log().AddEvent( | 
|  | 530               NetLog::TYPE_SDCH_DECODING_ERROR, | 
|  | 531               base::Bind(&NetLogSdchResourceProblemCallback, rv)); | 
|  | 532         } | 
|  | 533       } | 
|  | 534     } | 
| 493     std::string avail_dictionaries; | 535     std::string avail_dictionaries; | 
| 494     if (advertise_sdch) { | 536     if (advertise_sdch) { | 
| 495       sdch_manager->GetAvailDictionaryList(request_->url(), | 537       sdch_manager->GetAvailDictionaryList(request_->url(), | 
| 496                                            &avail_dictionaries); | 538                                            &avail_dictionaries); | 
| 497 | 539 | 
| 498       // The AllowLatencyExperiment() is only true if we've successfully done a | 540       // The AllowLatencyExperiment() is only true if we've successfully done a | 
| 499       // full SDCH compression recently in this browser session for this host. | 541       // full SDCH compression recently in this browser session for this host. | 
| 500       // Note that for this path, there might be no applicable dictionaries, | 542       // Note that for this path, there might be no applicable dictionaries, | 
| 501       // and hence we can't participate in the experiment. | 543       // and hence we can't participate in the experiment. | 
| 502       if (!avail_dictionaries.empty() && | 544       if (!avail_dictionaries.empty() && | 
| (...skipping 1025 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1528   return override_response_headers_.get() ? | 1570   return override_response_headers_.get() ? | 
| 1529              override_response_headers_.get() : | 1571              override_response_headers_.get() : | 
| 1530              transaction_->GetResponseInfo()->headers.get(); | 1572              transaction_->GetResponseInfo()->headers.get(); | 
| 1531 } | 1573 } | 
| 1532 | 1574 | 
| 1533 void URLRequestHttpJob::NotifyURLRequestDestroyed() { | 1575 void URLRequestHttpJob::NotifyURLRequestDestroyed() { | 
| 1534   awaiting_callback_ = false; | 1576   awaiting_callback_ = false; | 
| 1535 } | 1577 } | 
| 1536 | 1578 | 
| 1537 }  // namespace net | 1579 }  // namespace net | 
| OLD | NEW | 
|---|