| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
| 10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
| 11 #include "base/file_version_info.h" | 11 #include "base/file_version_info.h" |
| 12 #include "base/message_loop.h" | 12 #include "base/message_loop.h" |
| 13 #include "base/rand_util.h" |
| 13 #include "base/string_util.h" | 14 #include "base/string_util.h" |
| 14 #include "net/base/cookie_monster.h" | 15 #include "net/base/cookie_monster.h" |
| 15 #include "net/base/filter.h" | 16 #include "net/base/filter.h" |
| 16 #include "net/base/load_flags.h" | 17 #include "net/base/load_flags.h" |
| 17 #include "net/base/net_errors.h" | 18 #include "net/base/net_errors.h" |
| 18 #include "net/base/net_util.h" | 19 #include "net/base/net_util.h" |
| 19 #include "net/base/sdch_manager.h" | 20 #include "net/base/sdch_manager.h" |
| 20 #include "net/http/http_response_headers.h" | 21 #include "net/http/http_response_headers.h" |
| 21 #include "net/http/http_response_info.h" | 22 #include "net/http/http_response_info.h" |
| 22 #include "net/http/http_transaction.h" | 23 #include "net/http/http_transaction.h" |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 56 : URLRequestJob(request), | 57 : URLRequestJob(request), |
| 57 transaction_(NULL), | 58 transaction_(NULL), |
| 58 response_info_(NULL), | 59 response_info_(NULL), |
| 59 proxy_auth_state_(net::AUTH_STATE_DONT_NEED_AUTH), | 60 proxy_auth_state_(net::AUTH_STATE_DONT_NEED_AUTH), |
| 60 server_auth_state_(net::AUTH_STATE_DONT_NEED_AUTH), | 61 server_auth_state_(net::AUTH_STATE_DONT_NEED_AUTH), |
| 61 ALLOW_THIS_IN_INITIALIZER_LIST( | 62 ALLOW_THIS_IN_INITIALIZER_LIST( |
| 62 start_callback_(this, &URLRequestHttpJob::OnStartCompleted)), | 63 start_callback_(this, &URLRequestHttpJob::OnStartCompleted)), |
| 63 ALLOW_THIS_IN_INITIALIZER_LIST( | 64 ALLOW_THIS_IN_INITIALIZER_LIST( |
| 64 read_callback_(this, &URLRequestHttpJob::OnReadCompleted)), | 65 read_callback_(this, &URLRequestHttpJob::OnReadCompleted)), |
| 65 read_in_progress_(false), | 66 read_in_progress_(false), |
| 66 context_(request->context()) { | 67 context_(request->context()), |
| 68 sdch_dictionary_advertised_(false), |
| 69 sdch_test_activated_(false), |
| 70 sdch_test_control_(false) { |
| 67 } | 71 } |
| 68 | 72 |
| 69 URLRequestHttpJob::~URLRequestHttpJob() { | 73 URLRequestHttpJob::~URLRequestHttpJob() { |
| 74 DCHECK(!sdch_test_control_ || !sdch_test_activated_); |
| 75 if (sdch_test_control_) |
| 76 RecordPacketStats(SDCH_EXPERIMENT_HOLDBACK); |
| 77 if (sdch_test_activated_) |
| 78 RecordPacketStats(SDCH_EXPERIMENT_DECODE); |
| 79 |
| 70 if (sdch_dictionary_url_.is_valid()) { | 80 if (sdch_dictionary_url_.is_valid()) { |
| 71 // Prior to reaching the destructor, request_ has been set to a NULL | 81 // Prior to reaching the destructor, request_ has been set to a NULL |
| 72 // pointer, so request_->url() is no longer valid in the destructor, and we | 82 // pointer, so request_->url() is no longer valid in the destructor, and we |
| 73 // use an alternate copy |request_info_.url|. | 83 // use an alternate copy |request_info_.url|. |
| 74 SdchManager* manager = SdchManager::Global(); | 84 SdchManager* manager = SdchManager::Global(); |
| 75 // To be extra safe, since this is a "different time" from when we decided | 85 // To be extra safe, since this is a "different time" from when we decided |
| 76 // to get the dictionary, we'll validate that an SdchManager is available. | 86 // to get the dictionary, we'll validate that an SdchManager is available. |
| 77 // At shutdown time, care is taken to be sure that we don't delete this | 87 // At shutdown time, care is taken to be sure that we don't delete this |
| 78 // globally useful instance "too soon," so this check is just defensive | 88 // globally useful instance "too soon," so this check is just defensive |
| 79 // coding to assure that IF the system is shutting down, we don't have any | 89 // coding to assure that IF the system is shutting down, we don't have any |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 // Even if encoding types are empty, there is a chance that we need to add | 218 // Even if encoding types are empty, there is a chance that we need to add |
| 209 // some decoding, as some proxies strip encoding completely. In such cases, | 219 // some decoding, as some proxies strip encoding completely. In such cases, |
| 210 // we may need to add (for example) SDCH filtering (when the context suggests | 220 // we may need to add (for example) SDCH filtering (when the context suggests |
| 211 // it is appropriate). | 221 // it is appropriate). |
| 212 Filter::FixupEncodingTypes(*this, encoding_types); | 222 Filter::FixupEncodingTypes(*this, encoding_types); |
| 213 | 223 |
| 214 return !encoding_types->empty(); | 224 return !encoding_types->empty(); |
| 215 } | 225 } |
| 216 | 226 |
| 217 bool URLRequestHttpJob::IsSdchResponse() const { | 227 bool URLRequestHttpJob::IsSdchResponse() const { |
| 218 return response_info_ && | 228 return sdch_dictionary_advertised_; |
| 219 (request_info_.load_flags & net::LOAD_SDCH_DICTIONARY_ADVERTISED); | |
| 220 } | 229 } |
| 221 | 230 |
| 222 bool URLRequestHttpJob::IsRedirectResponse(GURL* location, | 231 bool URLRequestHttpJob::IsRedirectResponse(GURL* location, |
| 223 int* http_status_code) { | 232 int* http_status_code) { |
| 224 if (!response_info_) | 233 if (!response_info_) |
| 225 return false; | 234 return false; |
| 226 | 235 |
| 227 std::string value; | 236 std::string value; |
| 228 if (!response_info_->headers->IsRedirect(&value)) | 237 if (!response_info_->headers->IsRedirect(&value)) |
| 229 return false; | 238 return false; |
| (...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 539 rv = net::ERR_FAILED; | 548 rv = net::ERR_FAILED; |
| 540 } | 549 } |
| 541 | 550 |
| 542 // The transaction started synchronously, but we need to notify the | 551 // The transaction started synchronously, but we need to notify the |
| 543 // URLRequest delegate via the message loop. | 552 // URLRequest delegate via the message loop. |
| 544 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( | 553 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod( |
| 545 this, &URLRequestHttpJob::OnStartCompleted, rv)); | 554 this, &URLRequestHttpJob::OnStartCompleted, rv)); |
| 546 } | 555 } |
| 547 | 556 |
| 548 void URLRequestHttpJob::AddExtraHeaders() { | 557 void URLRequestHttpJob::AddExtraHeaders() { |
| 558 // TODO(jar): Consider optimizing away SDCH advertising bytes when the URL is |
| 559 // probably an img or such (and SDCH encoding is not likely). |
| 560 bool advertise_sdch = SdchManager::Global() && |
| 561 SdchManager::Global()->IsInSupportedDomain(request_->url()); |
| 562 std::string avail_dictionaries; |
| 563 if (advertise_sdch) { |
| 564 SdchManager::Global()->GetAvailDictionaryList(request_->url(), |
| 565 &avail_dictionaries); |
| 566 |
| 567 // The AllowLatencyExperiment() is only true if we've successfully done a |
| 568 // full SDCH compression recently in this browser session for this host. |
| 569 // Note that for this path, there might be no applicable dictionaries, and |
| 570 // hence we can't participate in the experiment. |
| 571 if (!avail_dictionaries.empty() && |
| 572 SdchManager::Global()->AllowLatencyExperiment(request_->url())) { |
| 573 // We are participating in the test (or control), and hence we'll |
| 574 // eventually record statistics via either SDCH_EXPERIMENT_DECODE or |
| 575 // SDCH_EXPERIMENT_HOLDBACK, and we'll need some packet timing data. |
| 576 EnablePacketCounting(kSdchPacketHistogramCount); |
| 577 if (base::RandDouble() < .5) { |
| 578 sdch_test_control_ = true; |
| 579 advertise_sdch = false; |
| 580 } else { |
| 581 sdch_test_activated_ = true; |
| 582 } |
| 583 } |
| 584 } |
| 585 |
| 549 // Supply Accept-Encoding headers first so that it is more likely that they | 586 // Supply Accept-Encoding headers first so that it is more likely that they |
| 550 // will be in the first transmitted packet. This can sometimes make it easier | 587 // will be in the first transmitted packet. This can sometimes make it easier |
| 551 // to filter and analyze the streams to assure that a proxy has not damaged | 588 // to filter and analyze the streams to assure that a proxy has not damaged |
| 552 // these headers. Some proxies deliberately corrupt Accept-Encoding headers. | 589 // these headers. Some proxies deliberately corrupt Accept-Encoding headers. |
| 553 if (!SdchManager::Global() || | 590 if (!advertise_sdch) { |
| 554 !SdchManager::Global()->IsInSupportedDomain(request_->url())) { | |
| 555 // Tell the server what compression formats we support (other than SDCH). | 591 // Tell the server what compression formats we support (other than SDCH). |
| 556 request_info_.extra_headers += "Accept-Encoding: gzip,deflate,bzip2\r\n"; | 592 request_info_.extra_headers += "Accept-Encoding: gzip,deflate,bzip2\r\n"; |
| 557 } else { | 593 } else { |
| 558 // Supply SDCH related headers, as well as accepting that encoding. | 594 // Include SDCH in acceptable list. |
| 559 // Tell the server what compression formats we support. | |
| 560 request_info_.extra_headers += "Accept-Encoding: " | 595 request_info_.extra_headers += "Accept-Encoding: " |
| 561 "gzip,deflate,bzip2,sdch\r\n"; | 596 "gzip,deflate,bzip2,sdch\r\n"; |
| 562 | |
| 563 // TODO(jar): See if it is worth optimizing away these bytes when the URL is | |
| 564 // probably an img or such. (and SDCH encoding is not likely). | |
| 565 std::string avail_dictionaries; | |
| 566 SdchManager::Global()->GetAvailDictionaryList(request_->url(), | |
| 567 &avail_dictionaries); | |
| 568 if (!avail_dictionaries.empty()) { | 597 if (!avail_dictionaries.empty()) { |
| 569 request_info_.extra_headers += "Avail-Dictionary: " | 598 request_info_.extra_headers += "Avail-Dictionary: " |
| 570 + avail_dictionaries + "\r\n"; | 599 + avail_dictionaries + "\r\n"; |
| 571 request_info_.load_flags |= net::LOAD_SDCH_DICTIONARY_ADVERTISED; | 600 sdch_dictionary_advertised_ = true; |
| 601 // Since we're tagging this transaction as advertising a dictionary, we'll |
| 602 // definately employ an SDCH filter (or tentative sdch filter) when we get |
| 603 // a response. When done, we'll record histograms via SDCH_DECODE or |
| 604 // SDCH_PASSTHROUGH. Hence we need to record packet arrival times. |
| 605 EnablePacketCounting(kSdchPacketHistogramCount); |
| 572 } | 606 } |
| 573 } | 607 } |
| 574 | 608 |
| 575 URLRequestContext* context = request_->context(); | 609 URLRequestContext* context = request_->context(); |
| 576 if (context) { | 610 if (context) { |
| 577 request_info_.extra_headers += AssembleRequestCookies(); | 611 request_info_.extra_headers += AssembleRequestCookies(); |
| 578 if (!context->accept_language().empty()) | 612 if (!context->accept_language().empty()) |
| 579 request_info_.extra_headers += "Accept-Language: " + | 613 request_info_.extra_headers += "Accept-Language: " + |
| 580 context->accept_language() + "\r\n"; | 614 context->accept_language() + "\r\n"; |
| 581 if (!context->accept_charset().empty()) | 615 if (!context->accept_charset().empty()) |
| (...skipping 24 matching lines...) Expand all Loading... |
| 606 DCHECK(response_info_); | 640 DCHECK(response_info_); |
| 607 DCHECK(response_cookies_.empty()); | 641 DCHECK(response_cookies_.empty()); |
| 608 | 642 |
| 609 std::string name = "Set-Cookie"; | 643 std::string name = "Set-Cookie"; |
| 610 std::string value; | 644 std::string value; |
| 611 | 645 |
| 612 void* iter = NULL; | 646 void* iter = NULL; |
| 613 while (response_info_->headers->EnumerateHeader(&iter, name, &value)) | 647 while (response_info_->headers->EnumerateHeader(&iter, name, &value)) |
| 614 response_cookies_.push_back(value); | 648 response_cookies_.push_back(value); |
| 615 } | 649 } |
| OLD | NEW |