1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be
3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file.
4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/url_request/url_request_http_job.h"
6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/base_switches.h"
8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/command_line.h"
9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/compiler_specific.h"
10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/file_util.h"
11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/file_version_info.h"
12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/message_loop.h"
13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/metrics/field_trial.h"
14dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "base/metrics/histogram.h"
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/rand_util.h"
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/string_util.h"
17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/time.h"
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/cert_status_flags.h"
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/cookie_policy.h"
203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/base/cookie_store.h"
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/filter.h"
22dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/base/host_port_pair.h"
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/load_flags.h"
24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "net/base/mime_util.h"
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_errors.h"
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_util.h"
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/sdch_manager.h"
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/ssl_cert_request_info.h"
29dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "net/base/transport_security_state.h"
30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_request_headers.h"
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/http/http_response_headers.h"
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/http/http_response_info.h"
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/http/http_transaction.h"
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/http/http_transaction_factory.h"
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/http/http_util.h"
36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/url_request/https_prober.h"
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/url_request/url_request.h"
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/url_request/url_request_context.h"
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/url_request/url_request_error_job.h"
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/url_request/url_request_redirect_job.h"
41201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "net/url_request/url_request_throttler_header_adapter.h"
42201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch#include "net/url_request/url_request_throttler_manager.h"
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochstatic const char kAvailDictionaryHeader[] = "Avail-Dictionary";
45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// When histogramming results related to SDCH and/or an SDCH latency test, the
47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// number of packets for which we need to record arrival times so as to
48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// calculate interpacket latencies.  We currently are only looking at the
49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// first few packets, as we're monitoring the impact of the initial TCP
50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// congestion window on stalling of transmissions.
51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic const size_t kSdchPacketHistogramCount = 5;
52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
5321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsennamespace net {
5421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
5521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsennamespace {
5621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
5721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenclass HTTPSProberDelegateImpl : public HTTPSProberDelegate {
5821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen public:
5921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  HTTPSProberDelegateImpl(const std::string& host, int max_age,
6021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                          bool include_subdomains,
6121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                          TransportSecurityState* sts)
6221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      : host_(host),
6321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        max_age_(max_age),
6421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        include_subdomains_(include_subdomains),
6521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        sts_(sts) { }
6621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
6721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  virtual void ProbeComplete(bool result) {
6821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (result) {
6921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      base::Time current_time(base::Time::Now());
7021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      base::TimeDelta max_age_delta = base::TimeDelta::FromSeconds(max_age_);
7121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
7221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      TransportSecurityState::DomainState domain_state;
7321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      domain_state.expiry = current_time + max_age_delta;
7421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      domain_state.mode =
7521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          TransportSecurityState::DomainState::MODE_OPPORTUNISTIC;
7621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      domain_state.include_subdomains = include_subdomains_;
7721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
7821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      sts_->EnableHost(host_, domain_state);
7921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    }
8021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
8121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    delete this;
8221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  }
8321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
8421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen private:
8521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  const std::string host_;
8621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  const int max_age_;
8721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  const bool include_subdomains_;
8821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  scoped_refptr<TransportSecurityState> sts_;
8921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen};
9021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
9121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}  // namespace
9221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass URLRequestHttpJob::HttpFilterContext : public FilterContext {
94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen public:
95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  explicit HttpFilterContext(URLRequestHttpJob* job);
96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual ~HttpFilterContext();
97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // FilterContext implementation.
99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual bool GetMimeType(std::string* mime_type) const;
100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual bool GetURL(GURL* gurl) const;
101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual base::Time GetRequestTime() const;
102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual bool IsCachedContent() const;
103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual bool IsDownload() const;
104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual bool IsSdchResponse() const;
105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual int64 GetByteReadCount() const;
106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual int GetResponseCode() const;
107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  virtual void RecordPacketStats(StatisticSelector statistic) const;
108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen private:
110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  URLRequestHttpJob* job_;
111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DISALLOW_COPY_AND_ASSIGN(HttpFilterContext);
113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen};
114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenURLRequestHttpJob::HttpFilterContext::HttpFilterContext(URLRequestHttpJob* job)
116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    : job_(job) {
117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(job_);
118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenURLRequestHttpJob::HttpFilterContext::~HttpFilterContext() {
121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool URLRequestHttpJob::HttpFilterContext::GetMimeType(
124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    std::string* mime_type) const {
125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return job_->GetMimeType(mime_type);
126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool URLRequestHttpJob::HttpFilterContext::GetURL(GURL* gurl) const {
129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!job_->request())
130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return false;
131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  *gurl = job_->request()->url();
132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return true;
133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbase::Time URLRequestHttpJob::HttpFilterContext::GetRequestTime() const {
136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return job_->request() ? job_->request()->request_time() : base::Time();
137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool URLRequestHttpJob::HttpFilterContext::IsCachedContent() const {
140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return job_->is_cached_content_;
141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool URLRequestHttpJob::HttpFilterContext::IsDownload() const {
144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return (job_->request_info_.load_flags & LOAD_IS_DOWNLOAD) != 0;
145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool URLRequestHttpJob::HttpFilterContext::IsSdchResponse() const {
148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return job_->sdch_dictionary_advertised_;
149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint64 URLRequestHttpJob::HttpFilterContext::GetByteReadCount() const {
152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return job_->filter_input_byte_count();
153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenint URLRequestHttpJob::HttpFilterContext::GetResponseCode() const {
156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return job_->GetResponseCode();
157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid URLRequestHttpJob::HttpFilterContext::RecordPacketStats(
160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    StatisticSelector statistic) const {
161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  job_->RecordPacketStats(statistic);
162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// TODO(darin): make sure the port blocking code is not lost
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottURLRequestJob* URLRequestHttpJob::Factory(URLRequest* request,
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                          const std::string& scheme) {
168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(scheme == "http" || scheme == "https");
169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int port = request->url().IntPort();
17121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (!IsPortAllowedByDefault(port) && !IsPortAllowedByOverride(port))
17221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return new URLRequestErrorJob(request, ERR_UNSAFE_PORT);
173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!request->context() ||
175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      !request->context()->http_transaction_factory()) {
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NOTREACHED() << "requires a valid context";
17721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    return new URLRequestErrorJob(request, ERR_INVALID_ARGUMENT);
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
18021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  TransportSecurityState::DomainState domain_state;
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (scheme == "http" &&
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      request->context()->transport_security_state() &&
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      request->context()->transport_security_state()->IsEnabledForHost(
184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          &domain_state,
185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          request->url().host(),
186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          request->context()->IsSNIAvailable())) {
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (domain_state.mode ==
18821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen         TransportSecurityState::DomainState::MODE_STRICT) {
189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      DCHECK_EQ(request->url().scheme(), "http");
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      url_canon::Replacements<char> replacements;
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      static const char kNewScheme[] = "https";
192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      replacements.SetScheme(kNewScheme,
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             url_parse::Component(0, strlen(kNewScheme)));
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      GURL new_location = request->url().ReplaceComponents(replacements);
195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return new URLRequestRedirectJob(request, new_location);
196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // TODO(agl): implement opportunistic HTTPS upgrade.
198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return new URLRequestHttpJob(request);
202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
20472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottURLRequestHttpJob::URLRequestHttpJob(URLRequest* request)
206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : URLRequestJob(request),
207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      response_info_(NULL),
208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      response_cookies_save_index_(0),
20921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      proxy_auth_state_(AUTH_STATE_DONT_NEED_AUTH),
21021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      server_auth_state_(AUTH_STATE_DONT_NEED_AUTH),
211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ALLOW_THIS_IN_INITIALIZER_LIST(start_callback_(
212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          this, &URLRequestHttpJob::OnStartCompleted)),
213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ALLOW_THIS_IN_INITIALIZER_LIST(read_callback_(
214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          this, &URLRequestHttpJob::OnReadCompleted)),
215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      read_in_progress_(false),
216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      transaction_(NULL),
21721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      throttling_entry_(URLRequestThrottlerManager::GetInstance()->
218201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch          RegisterRequestUrl(request->url())),
219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      sdch_dictionary_advertised_(false),
220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      sdch_test_activated_(false),
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      sdch_test_control_(false),
22221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      is_cached_content_(false),
223dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen      request_creation_time_(),
224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      packet_timing_enabled_(false),
225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      bytes_observed_in_packets_(0),
226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      packet_times_(),
227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      request_time_snapshot_(),
228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      final_packet_time_(),
229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      observed_packet_count_(0),
230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ALLOW_THIS_IN_INITIALIZER_LIST(
231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          filter_context_(new HttpFilterContext(this))),
23221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
233dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ResetTimer();
234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
23672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid URLRequestHttpJob::NotifyHeadersComplete() {
23772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(!response_info_);
23872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
23972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  response_info_ = transaction_->GetResponseInfo();
24072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
24172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Save boolean, as we'll need this info at destruction time, and filters may
24272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // also need this info.
24372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  is_cached_content_ = response_info_->was_cached;
24472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
24572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!is_cached_content_) {
24672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    URLRequestThrottlerHeaderAdapter response_adapter(
24772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        response_info_->headers);
248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    throttling_entry_->UpdateWithResponse(request_info_.url.host(),
249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                          &response_adapter);
250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
25272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  ProcessStrictTransportSecurityHeader();
25372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
25472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (SdchManager::Global() &&
25572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      SdchManager::Global()->IsInSupportedDomain(request_->url())) {
25672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    static const std::string name = "Get-Dictionary";
25772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::string url_text;
25872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    void* iter = NULL;
25972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // TODO(jar): We need to not fetch dictionaries the first time they are
26072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // seen, but rather wait until we can justify their usefulness.
26172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // For now, we will only fetch the first dictionary, which will at least
26272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // require multiple suggestions before we get additional ones for this site.
26372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // Eventually we should wait until a dictionary is requested several times
26472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // before we even download it (so that we don't waste memory or bandwidth).
26572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (response_info_->headers->EnumerateHeader(&iter, name, &url_text)) {
26672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // request_->url() won't be valid in the destructor, so we use an
26772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // alternate copy.
268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      DCHECK_EQ(request_->url(), request_info_.url);
26972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // Resolve suggested URL relative to request url.
27072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      sdch_dictionary_url_ = request_info_.url.Resolve(url_text);
27172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
27472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // The HTTP transaction may be restarted several times for the purposes
27572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // of sending authorization information. Each time it restarts, we get
27672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // notified of the headers completion so that we can update the cookie store.
27772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (transaction_->IsReadyToRestartForAuth()) {
27872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    DCHECK(!response_info_->auth_challenge.get());
27972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    RestartTransactionWithAuth(string16(), string16());
28072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return;
28172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
28272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
28372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  URLRequestJob::NotifyHeadersComplete();
284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
286ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid URLRequestHttpJob::NotifyDone(const URLRequestStatus& status) {
287ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  RecordCompressionHistograms();
288ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  URLRequestJob::NotifyDone(status);
289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
29172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid URLRequestHttpJob::DestroyTransaction() {
29272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(transaction_.get());
29372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
29472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  transaction_.reset();
29572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  response_info_ = NULL;
29672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  context_ = NULL;
297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
29972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid URLRequestHttpJob::StartTransaction() {
30072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // NOTE: This method assumes that request_info_ is already setup properly.
301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
30272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // If we already have a transaction, then we should restart the transaction
30372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // with auth provided by username_ and password_.
304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
30572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int rv;
306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
30772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (transaction_.get()) {
30872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    rv = transaction_->RestartWithAuth(username_, password_, &start_callback_);
30972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    username_.clear();
31072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    password_.clear();
31172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  } else {
31272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    DCHECK(request_->context());
31372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    DCHECK(request_->context()->http_transaction_factory());
314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
31572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    rv = request_->context()->http_transaction_factory()->CreateTransaction(
31672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        &transaction_);
31772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (rv == OK) {
318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (!URLRequestThrottlerManager::GetInstance()->enforce_throttling() ||
319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          !throttling_entry_->IsDuringExponentialBackoff()) {
320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        rv = transaction_->Start(
321ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            &request_info_, &start_callback_, request_->net_log());
322ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      } else {
323ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        // Special error code for the exponential back-off module.
324ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        rv = ERR_TEMPORARILY_THROTTLED;
325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      }
32672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // Make sure the context is alive for the duration of the
32772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // transaction.
32872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      context_ = request_->context();
32972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
33072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
33272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (rv == ERR_IO_PENDING)
333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
33572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // The transaction started synchronously, but we need to notify the
33672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // URLRequest delegate via the message loop.
33772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  MessageLoop::current()->PostTask(
33872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      FROM_HERE,
33972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      method_factory_.NewRunnableMethod(
34072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          &URLRequestHttpJob::OnStartCompleted, rv));
341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
34372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid URLRequestHttpJob::AddExtraHeaders() {
34472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // TODO(jar): Consider optimizing away SDCH advertising bytes when the URL is
34572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // probably an img or such (and SDCH encoding is not likely).
34672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  bool advertise_sdch = SdchManager::Global() &&
34772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      SdchManager::Global()->IsInSupportedDomain(request_->url());
34872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::string avail_dictionaries;
34972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (advertise_sdch) {
35072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    SdchManager::Global()->GetAvailDictionaryList(request_->url(),
35172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                                  &avail_dictionaries);
352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
35372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // The AllowLatencyExperiment() is only true if we've successfully done a
35472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // full SDCH compression recently in this browser session for this host.
35572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // Note that for this path, there might be no applicable dictionaries, and
35672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // hence we can't participate in the experiment.
35772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (!avail_dictionaries.empty() &&
35872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        SdchManager::Global()->AllowLatencyExperiment(request_->url())) {
35972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // We are participating in the test (or control), and hence we'll
36072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // eventually record statistics via either SDCH_EXPERIMENT_DECODE or
36172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // SDCH_EXPERIMENT_HOLDBACK, and we'll need some packet timing data.
362ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      packet_timing_enabled_ = true;
36372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (base::RandDouble() < .01) {
36472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        sdch_test_control_ = true;  // 1% probability.
36572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        advertise_sdch = false;
36672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      } else {
36772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        sdch_test_activated_ = true;
36872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      }
36972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
37072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
37272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Supply Accept-Encoding headers first so that it is more likely that they
37372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // will be in the first transmitted packet.  This can sometimes make it easier
37472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // to filter and analyze the streams to assure that a proxy has not damaged
37572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // these headers.  Some proxies deliberately corrupt Accept-Encoding headers.
37672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!advertise_sdch) {
37772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // Tell the server what compression formats we support (other than SDCH).
37872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    request_info_.extra_headers.SetHeader(
37972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        HttpRequestHeaders::kAcceptEncoding, "gzip,deflate");
38072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  } else {
38172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // Include SDCH in acceptable list.
38272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    request_info_.extra_headers.SetHeader(
38372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        HttpRequestHeaders::kAcceptEncoding, "gzip,deflate,sdch");
38472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (!avail_dictionaries.empty()) {
38572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      request_info_.extra_headers.SetHeader(
38672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          kAvailDictionaryHeader,
38772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          avail_dictionaries);
38872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      sdch_dictionary_advertised_ = true;
38972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // Since we're tagging this transaction as advertising a dictionary, we'll
39072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // definately employ an SDCH filter (or tentative sdch filter) when we get
39172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // a response.  When done, we'll record histograms via SDCH_DECODE or
39272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      // SDCH_PASSTHROUGH.  Hence we need to record packet arrival times.
393ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      packet_timing_enabled_ = true;
39472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
39572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
39772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  URLRequestContext* context = request_->context();
39872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (context) {
39972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // Only add default Accept-Language and Accept-Charset if the request
40072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // didn't have them specified.
401ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!context->accept_language().empty()) {
402ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      request_info_.extra_headers.SetHeaderIfMissing(
403ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          HttpRequestHeaders::kAcceptLanguage,
404ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          context->accept_language());
405ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
406ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (!context->accept_charset().empty()) {
407ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      request_info_.extra_headers.SetHeaderIfMissing(
408ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          HttpRequestHeaders::kAcceptCharset,
409ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          context->accept_charset());
410ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
41172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
41472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid URLRequestHttpJob::AddCookieHeaderAndStart() {
41572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // No matter what, we want to report our status as IO pending since we will
41672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // be notifying our consumer asynchronously via OnStartCompleted.
41772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
41972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int policy = OK;
420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
42172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (request_info_.load_flags & LOAD_DO_NOT_SEND_COOKIES) {
42272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    policy = ERR_FAILED;
42372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  } else if (request_->context()->cookie_policy()) {
42472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    policy = request_->context()->cookie_policy()->CanGetCookies(
42572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        request_->url(),
426ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        request_->first_party_for_cookies());
42772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
42972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  OnCanGetCookiesCompleted(policy);
430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
43272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid URLRequestHttpJob::SaveCookiesAndNotifyHeadersComplete() {
433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(transaction_.get());
434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
43572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  const HttpResponseInfo* response_info = transaction_->GetResponseInfo();
43672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(response_info);
437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
43872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  response_cookies_.clear();
43972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  response_cookies_save_index_ = 0;
440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
44172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  FetchResponseCookies(response_info, &response_cookies_);
442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
44372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Now, loop over the response cookies, and attempt to persist each.
44472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  SaveNextCookie();
445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
44772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid URLRequestHttpJob::SaveNextCookie() {
44872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (response_cookies_save_index_ == response_cookies_.size()) {
44972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    response_cookies_.clear();
45072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    response_cookies_save_index_ = 0;
45172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    SetStatus(URLRequestStatus());  // Clear the IO_PENDING status
45272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    NotifyHeadersComplete();
45372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return;
454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
45672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // No matter what, we want to report our status as IO pending since we will
45772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // be notifying our consumer asynchronously via OnStartCompleted.
45872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
46072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int policy = OK;
461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
46272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (request_info_.load_flags & LOAD_DO_NOT_SAVE_COOKIES) {
46372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    policy = ERR_FAILED;
46472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  } else if (request_->context()->cookie_policy()) {
46572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    policy = request_->context()->cookie_policy()->CanSetCookie(
46672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        request_->url(),
46772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        request_->first_party_for_cookies(),
468ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        response_cookies_[response_cookies_save_index_]);
469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
47172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  OnCanSetCookieCompleted(policy);
472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
47472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid URLRequestHttpJob::FetchResponseCookies(
47572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const HttpResponseInfo* response_info,
47672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::vector<std::string>* cookies) {
47772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::string name = "Set-Cookie";
47872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::string value;
479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
48072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  void* iter = NULL;
48172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  while (response_info->headers->EnumerateHeader(&iter, name, &value)) {
48272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (!value.empty())
48372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      cookies->push_back(value);
484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
48772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid URLRequestHttpJob::ProcessStrictTransportSecurityHeader() {
488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(response_info_);
489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
49072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  URLRequestContext* ctx = request_->context();
49172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!ctx || !ctx->transport_security_state())
49272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return;
493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
49472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  const bool https = response_info_->ssl_info.is_valid();
49572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  const bool valid_https =
49672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      https && !IsCertStatusError(response_info_->ssl_info.cert_status);
497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
49872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::string name = "Strict-Transport-Security";
49972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::string value;
500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
50172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int max_age;
50272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  bool include_subdomains;
503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
50472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  void* iter = NULL;
50572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  while (response_info_->headers->EnumerateHeader(&iter, name, &value)) {
50672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const bool ok = TransportSecurityState::ParseHeader(
50772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        value, &max_age, &include_subdomains);
50872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (!ok)
50972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      continue;
51072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // We will only accept strict mode if we saw the header from an HTTPS
51172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // connection with no certificate problems.
51272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (!valid_https)
51372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      continue;
51472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    base::Time current_time(base::Time::Now());
51572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    base::TimeDelta max_age_delta = base::TimeDelta::FromSeconds(max_age);
516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
51772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    TransportSecurityState::DomainState domain_state;
51872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    domain_state.expiry = current_time + max_age_delta;
51972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    domain_state.mode = TransportSecurityState::DomainState::MODE_STRICT;
52072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    domain_state.include_subdomains = include_subdomains;
521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
52272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ctx->transport_security_state()->EnableHost(request_info_.url.host(),
52372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                                domain_state);
524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
52672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // TODO(agl): change this over when we have fixed things at the server end.
52772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // The string should be "Opportunistic-Transport-Security";
52872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  name = "X-Bodge-Transport-Security";
529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
53072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  while (response_info_->headers->EnumerateHeader(&iter, name, &value)) {
53172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const bool ok = TransportSecurityState::ParseHeader(
53272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        value, &max_age, &include_subdomains);
53372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (!ok)
53472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      continue;
53572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // If we saw an opportunistic request over HTTPS, then clearly we can make
53672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // HTTPS connections to the host so we should remember this.
53772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (https) {
53872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      base::Time current_time(base::Time::Now());
53972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      base::TimeDelta max_age_delta = base::TimeDelta::FromSeconds(max_age);
540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
54172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      TransportSecurityState::DomainState domain_state;
54272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      domain_state.expiry = current_time + max_age_delta;
54372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      domain_state.mode =
54472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          TransportSecurityState::DomainState::MODE_SPDY_ONLY;
54572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      domain_state.include_subdomains = include_subdomains;
546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
54772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      ctx->transport_security_state()->EnableHost(request_info_.url.host(),
54872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                                  domain_state);
54972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      continue;
55072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
55272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (!request())
55372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      break;
554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
55572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // At this point, we have a request for opportunistic encryption over HTTP.
55672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // In this case we need to probe to check that we can make HTTPS
55772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // connections to that host.
55872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    HTTPSProber* const prober = HTTPSProber::GetInstance();
55972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (prober->HaveProbed(request_info_.url.host()) ||
56072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        prober->InFlight(request_info_.url.host())) {
56172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      continue;
56272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
563c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
56472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    HTTPSProberDelegateImpl* delegate =
56572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        new HTTPSProberDelegateImpl(request_info_.url.host(), max_age,
56672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                    include_subdomains,
56772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                    ctx->transport_security_state());
56872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (!prober->ProbeHost(request_info_.url.host(), request()->context(),
56972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                           delegate)) {
57072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      delete delegate;
57172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    }
572c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::OnCanGetCookiesCompleted(int policy) {
576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If the request was destroyed, then there is no more work to do.
577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (request_ && request_->delegate()) {
57821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (request_->context()->cookie_store()) {
57921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      if (policy == ERR_ACCESS_DENIED) {
58021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        request_->delegate()->OnGetCookies(request_, true);
58121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      } else if (policy == OK) {
58221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        request_->delegate()->OnGetCookies(request_, false);
58321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        CookieOptions options;
58421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        options.set_include_httponly();
58521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        std::string cookies =
58621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen            request_->context()->cookie_store()->GetCookiesWithOptions(
58721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                request_->url(), options);
58821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        if (!cookies.empty()) {
58921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          request_info_.extra_headers.SetHeader(
59021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen              HttpRequestHeaders::kCookie, cookies);
59121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        }
592c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      }
593c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
594c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We may have been canceled within OnGetCookies.
595c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (GetStatus().is_success()) {
596c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      StartTransaction();
597c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
598c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NotifyCanceled();
599c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
600c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
602c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
603c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::OnCanSetCookieCompleted(int policy) {
604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If the request was destroyed, then there is no more work to do.
605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (request_ && request_->delegate()) {
60621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    if (request_->context()->cookie_store()) {
60721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      if (policy == ERR_ACCESS_DENIED) {
608ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        CookieOptions options;
609ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        options.set_include_httponly();
61021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        request_->delegate()->OnSetCookie(
61121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen            request_,
61221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen            response_cookies_[response_cookies_save_index_],
613ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            options,
61421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen            true);
61521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      } else if (policy == OK || policy == OK_FOR_SESSION_ONLY) {
61621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        // OK to save the current response cookie now.
61721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        CookieOptions options;
61821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        options.set_include_httponly();
61921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        if (policy == OK_FOR_SESSION_ONLY)
62021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen          options.set_force_session();
62121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        request_->context()->cookie_store()->SetCookieWithOptions(
62221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen            request_->url(), response_cookies_[response_cookies_save_index_],
62321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen            options);
62421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        request_->delegate()->OnSetCookie(
62521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen            request_,
62621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen            response_cookies_[response_cookies_save_index_],
62721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen            options,
62821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen            false);
62921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      }
630c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
631c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    response_cookies_save_index_++;
632c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We may have been canceled within OnSetCookie.
633c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (GetStatus().is_success()) {
634c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      SaveNextCookie();
635c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    } else {
636c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      NotifyCanceled();
637c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
640c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
641c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::OnStartCompleted(int result) {
642dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  RecordTimer();
643dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
644c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If the request was destroyed, then there is no more work to do.
645c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!request_ || !request_->delegate())
646c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
647c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
648c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If the transaction was destroyed, then the job was cancelled, and
649c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // we can just ignore this notification.
650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!transaction_.get())
651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
652c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
653c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Clear the IO_PENDING status
654c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SetStatus(URLRequestStatus());
655c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
656ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Take care of any mandates for public key pinning.
657ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // TODO(agl): we might have an issue here where a request for foo.example.com
658ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // merges into a SPDY connection to www.example.com, and gets a different
659ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // certificate.
660ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const SSLInfo& ssl_info = transaction_->GetResponseInfo()->ssl_info;
661ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (result == OK &&
662ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ssl_info.is_valid() &&
663ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      context_->transport_security_state()) {
664ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    TransportSecurityState::DomainState domain_state;
665ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (context_->transport_security_state()->IsEnabledForHost(
666ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            &domain_state,
667ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            request_->url().host(),
668ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen            context_->IsSNIAvailable()) &&
669ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        ssl_info.is_issued_by_known_root &&
670ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        !domain_state.IsChainOfPublicKeysPermitted(ssl_info.public_key_hashes)){
671ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      result = ERR_CERT_INVALID;
672ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
673ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
674ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
67521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (result == OK) {
676c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SaveCookiesAndNotifyHeadersComplete();
677c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else if (ShouldTreatAsCertificateError(result)) {
678c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // We encountered an SSL certificate error.  Ask our delegate to decide
679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // what we should do.
680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // TODO(wtc): also pass ssl_info.cert_status, or just pass the whole
681c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // ssl_info.
682c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    request_->delegate()->OnSSLCertificateError(
683c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        request_, result, transaction_->GetResponseInfo()->ssl_info.cert);
68421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
685c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    request_->delegate()->OnCertificateRequested(
686c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        request_, transaction_->GetResponseInfo()->cert_request_info);
687c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
688c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result));
689c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
691c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
692c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::OnReadCompleted(int result) {
693c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  read_in_progress_ = false;
694c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
69572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (result == 0) {
69672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    NotifyDone(URLRequestStatus());
69772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  } else if (result < 0) {
69872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result));
69972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  } else {
70072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // Clear the IO_PENDING status
70172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    SetStatus(URLRequestStatus());
70272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
70372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
70472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  NotifyReadComplete(result);
70572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
70672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
70772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool URLRequestHttpJob::ShouldTreatAsCertificateError(int result) {
70872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!IsCertificateError(result))
70972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
71072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
711ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Revocation check failures are always certificate errors, even if the host
712ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // is using Strict-Transport-Security.
713ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (result == ERR_CERT_UNABLE_TO_CHECK_REVOCATION)
714ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return true;
715ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
71672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Check whether our context is using Strict-Transport-Security.
71772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!context_->transport_security_state())
71872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return true;
71972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
72072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  TransportSecurityState::DomainState domain_state;
72172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // TODO(agl): don't ignore opportunistic mode.
72272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  const bool r = context_->transport_security_state()->IsEnabledForHost(
723ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      &domain_state, request_info_.url.host(), context_->IsSNIAvailable());
72472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
72572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return !r || domain_state.mode ==
72672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen               TransportSecurityState::DomainState::MODE_OPPORTUNISTIC;
72772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
72872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
72972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid URLRequestHttpJob::RestartTransactionWithAuth(
73072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const string16& username,
73172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const string16& password) {
73272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  username_ = username;
73372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  password_ = password;
73472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
73572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // These will be reset in OnStartCompleted.
73672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  response_info_ = NULL;
73772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  response_cookies_.clear();
73872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
739dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ResetTimer();
740dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
74172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Update the cookies, since the cookie store may have been updated from the
74272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // headers in the 401/407. Since cookies were already appended to
74372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // extra_headers, we need to strip them out before adding them again.
74472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  request_info_.extra_headers.RemoveHeader(
74572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      HttpRequestHeaders::kCookie);
74672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
74772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  AddCookieHeaderAndStart();
74872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
74972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
75072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid URLRequestHttpJob::SetUpload(UploadData* upload) {
75172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(!transaction_.get()) << "cannot change once started";
75272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  request_info_.upload_data = upload;
75372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
75472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
75572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid URLRequestHttpJob::SetExtraRequestHeaders(
75672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const HttpRequestHeaders& headers) {
75772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(!transaction_.get()) << "cannot change once started";
75872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  request_info_.extra_headers.CopyFrom(headers);
75972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
76072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
76172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid URLRequestHttpJob::Start() {
76272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(!transaction_.get());
76372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
76472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Ensure that we do not send username and password fields in the referrer.
76572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  GURL referrer(request_->GetSanitizedReferrer());
76672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
76772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  request_info_.url = request_->url();
76872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  request_info_.referrer = referrer;
76972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  request_info_.method = request_->method();
77072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  request_info_.load_flags = request_->load_flags();
77172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  request_info_.priority = request_->priority();
772ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  request_info_.request_id = request_->identifier();
77372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
77472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (request_->context()) {
77572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    request_info_.extra_headers.SetHeaderIfMissing(
77672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        HttpRequestHeaders::kUserAgent,
77772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        request_->context()->GetUserAgent(request_->url()));
778c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
779c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
78072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  AddExtraHeaders();
781e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma
782e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#ifdef ANDROID
783e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma  // Attribute network traffic to the UID of the caller
784e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma  request_info_.valid_uid = false;
785e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma  request_info_.calling_uid = 0;
786e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma
787e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma  if (request_->context()) {
788e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma    uid_t uid;
789e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma    if(request_->context()->getUID(&uid)) {
790e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma      request_info_.valid_uid = true;
791e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma      request_info_.calling_uid = uid;
792e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma    }
793e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma  }
794e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma#endif
795e14dcc5a172cad1c4716af7ab94121a73c0c698eAshish Sharma
79672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  AddCookieHeaderAndStart();
797c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
798c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
79972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid URLRequestHttpJob::Kill() {
80072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!transaction_.get())
80172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return;
802c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
80372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DestroyTransaction();
80472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  URLRequestJob::Kill();
80572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
806c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
80772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenLoadState URLRequestHttpJob::GetLoadState() const {
80872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return transaction_.get() ?
80972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      transaction_->GetLoadState() : LOAD_STATE_IDLE;
81072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
811c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
81272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenuint64 URLRequestHttpJob::GetUploadProgress() const {
81372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return transaction_.get() ? transaction_->GetUploadProgress() : 0;
814c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
815c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
81672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool URLRequestHttpJob::GetMimeType(std::string* mime_type) const {
81772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(transaction_.get());
818c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
81972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!response_info_)
82072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
821c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
82272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return response_info_->headers->GetMimeType(mime_type);
82372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
824c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
82572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool URLRequestHttpJob::GetCharset(std::string* charset) {
82672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(transaction_.get());
827201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
82872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!response_info_)
82972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
830c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
83172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return response_info_->headers->GetCharset(charset);
83272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
833c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
83472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid URLRequestHttpJob::GetResponseInfo(HttpResponseInfo* info) {
83572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(request_);
83672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(transaction_.get());
837c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
83872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (response_info_)
83972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    *info = *response_info_;
840c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
841c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
84272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool URLRequestHttpJob::GetResponseCookies(
84372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    std::vector<std::string>* cookies) {
844c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(transaction_.get());
845c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
84672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!response_info_)
84772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
84872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
84972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // TODO(darin): Why are we extracting response cookies again?  Perhaps we
85072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // should just leverage response_cookies_.
85172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
85272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  cookies->clear();
85372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  FetchResponseCookies(response_info_, cookies);
85472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return true;
855c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
856c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
85772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint URLRequestHttpJob::GetResponseCode() const {
85872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(transaction_.get());
859c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
86072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!response_info_)
86172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return -1;
862c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
86372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return response_info_->headers->response_code();
86472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
865201ade2fbba22bfb27ae029f4d23fca6ded109a0Ben Murdoch
866ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenFilter* URLRequestHttpJob::SetupFilter() const {
86772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(transaction_.get());
86872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!response_info_)
869ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return NULL;
870c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
871ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::vector<Filter::FilterType> encoding_types;
87272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  std::string encoding_type;
87372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  void* iter = NULL;
87472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  while (response_info_->headers->EnumerateHeader(&iter, "Content-Encoding",
87572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                                  &encoding_type)) {
876ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    encoding_types.push_back(Filter::ConvertEncodingToType(encoding_type));
877c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
878c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
87972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Even if encoding types are empty, there is a chance that we need to add
88072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // some decoding, as some proxies strip encoding completely. In such cases,
88172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // we may need to add (for example) SDCH filtering (when the context suggests
88272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // it is appropriate).
883ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  Filter::FixupEncodingTypes(*filter_context_, &encoding_types);
884c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
885ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return !encoding_types.empty()
886ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      ? Filter::Factory(encoding_types, *filter_context_) : NULL;
88772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
888c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
88972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool URLRequestHttpJob::IsSafeRedirect(const GURL& location) {
89072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // We only allow redirects to certain "safe" protocols.  This does not
89172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // restrict redirects to externally handled protocols.  Our consumer would
89272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // need to take care of those.
89372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
89472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!URLRequest::IsHandledURL(location))
89572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return true;
89672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
89772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  static const char* kSafeSchemes[] = {
89872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    "http",
89972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    "https",
90072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    "ftp"
90172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  };
90272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
90372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  for (size_t i = 0; i < arraysize(kSafeSchemes); ++i) {
90472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (location.SchemeIs(kSafeSchemes[i]))
90572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return true;
906c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
907c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
90872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return false;
90972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
91072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
91172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool URLRequestHttpJob::NeedsAuth() {
91272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int code = GetResponseCode();
91372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (code == -1)
91472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return false;
91572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
91672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Check if we need either Proxy or WWW Authentication.  This could happen
91772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // because we either provided no auth info, or provided incorrect info.
91872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  switch (code) {
91972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    case 407:
92072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (proxy_auth_state_ == AUTH_STATE_CANCELED)
92172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        return false;
92272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      proxy_auth_state_ = AUTH_STATE_NEED_AUTH;
92372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return true;
92472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    case 401:
92572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      if (server_auth_state_ == AUTH_STATE_CANCELED)
92672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        return false;
92772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      server_auth_state_ = AUTH_STATE_NEED_AUTH;
92872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      return true;
929c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
93072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return false;
931c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
932c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
93372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid URLRequestHttpJob::GetAuthChallengeInfo(
93472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    scoped_refptr<AuthChallengeInfo>* result) {
93572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(transaction_.get());
93672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(response_info_);
937c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
93872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // sanity checks:
93972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(proxy_auth_state_ == AUTH_STATE_NEED_AUTH ||
94072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen         server_auth_state_ == AUTH_STATE_NEED_AUTH);
94172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(response_info_->headers->response_code() == 401 ||
94272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen         response_info_->headers->response_code() == 407);
943c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
94472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  *result = response_info_->auth_challenge;
94572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
946c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
94772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid URLRequestHttpJob::SetAuth(const string16& username,
94872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                const string16& password) {
94972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(transaction_.get());
95072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
95172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Proxy gets set first, then WWW.
95272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (proxy_auth_state_ == AUTH_STATE_NEED_AUTH) {
95372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    proxy_auth_state_ = AUTH_STATE_HAVE_AUTH;
95472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  } else {
955ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DCHECK_EQ(server_auth_state_, AUTH_STATE_NEED_AUTH);
95672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    server_auth_state_ = AUTH_STATE_HAVE_AUTH;
957c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
958c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
95972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  RestartTransactionWithAuth(username, password);
960c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
961c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
96272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid URLRequestHttpJob::CancelAuth() {
96372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Proxy gets set first, then WWW.
96472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (proxy_auth_state_ == AUTH_STATE_NEED_AUTH) {
96572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    proxy_auth_state_ = AUTH_STATE_CANCELED;
96672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  } else {
967ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DCHECK_EQ(server_auth_state_, AUTH_STATE_NEED_AUTH);
96872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    server_auth_state_ = AUTH_STATE_CANCELED;
96972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
970c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
97172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // These will be reset in OnStartCompleted.
97272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  response_info_ = NULL;
973c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  response_cookies_.clear();
974c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
975dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ResetTimer();
976dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
97772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // OK, let the consumer read the error page...
97872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  //
97972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Because we set the AUTH_STATE_CANCELED flag, NeedsAuth will return false,
98072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // which will cause the consumer to receive OnResponseStarted instead of
98172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // OnAuthRequired.
98272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  //
98372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // We have to do this via InvokeLater to avoid "recursing" the consumer.
98472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  //
98572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  MessageLoop::current()->PostTask(
98672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      FROM_HERE,
98772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      method_factory_.NewRunnableMethod(
98872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          &URLRequestHttpJob::OnStartCompleted, OK));
989c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
990c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
99172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid URLRequestHttpJob::ContinueWithCertificate(
99272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    X509Certificate* client_cert) {
99372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(transaction_.get());
99472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
99572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(!response_info_) << "should not have a response yet";
996c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
997dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ResetTimer();
998dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
999c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // No matter what, we want to report our status as IO pending since we will
1000c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // be notifying our consumer asynchronously via OnStartCompleted.
1001c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
1002c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
100372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int rv = transaction_->RestartWithCertificate(client_cert, &start_callback_);
100472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (rv == ERR_IO_PENDING)
100572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return;
1006c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
100772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // The transaction started synchronously, but we need to notify the
100872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // URLRequest delegate via the message loop.
100972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  MessageLoop::current()->PostTask(
101072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      FROM_HERE,
101172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      method_factory_.NewRunnableMethod(
101272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          &URLRequestHttpJob::OnStartCompleted, rv));
1013c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
1014c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
101572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid URLRequestHttpJob::ContinueDespiteLastError() {
101672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // If the transaction was destroyed, then the job was cancelled.
101772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (!transaction_.get())
1018c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
1019c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
102072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(!response_info_) << "should not have a response yet";
1021c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1022dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  ResetTimer();
1023dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
102472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // No matter what, we want to report our status as IO pending since we will
102572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // be notifying our consumer asynchronously via OnStartCompleted.
102672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
1027c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
102872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int rv = transaction_->RestartIgnoringLastError(&start_callback_);
102972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (rv == ERR_IO_PENDING)
103072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return;
1031c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
103272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // The transaction started synchronously, but we need to notify the
103372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // URLRequest delegate via the message loop.
103472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  MessageLoop::current()->PostTask(
103572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      FROM_HERE,
103672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      method_factory_.NewRunnableMethod(
103772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen          &URLRequestHttpJob::OnStartCompleted, rv));
103872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
1039c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
104072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool URLRequestHttpJob::ReadRawData(IOBuffer* buf, int buf_size,
104172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                    int *bytes_read) {
104272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK_NE(buf_size, 0);
104372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(bytes_read);
104472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(!read_in_progress_);
1045c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
104672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  int rv = transaction_->Read(buf, buf_size, &read_callback_);
104772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (rv >= 0) {
104872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    *bytes_read = rv;
104972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    return true;
1050c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1051c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
105272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (rv == ERR_IO_PENDING) {
105372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    read_in_progress_ = true;
105472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
105572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  } else {
105672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv));
105772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
1058c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
105972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return false;
106072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
1061c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
106272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid URLRequestHttpJob::StopCaching() {
106372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (transaction_.get())
106472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    transaction_->StopCaching();
106572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
1066c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
1067dc0f95d653279beabeb9817299e2902918ba123eKristian MonsenHostPortPair URLRequestHttpJob::GetSocketAddress() const {
1068dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  return response_info_ ? response_info_->socket_address : HostPortPair();
1069dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
1070dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
107172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenURLRequestHttpJob::~URLRequestHttpJob() {
107272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK(!sdch_test_control_ || !sdch_test_activated_);
1073ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!is_cached_content_) {
107472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (sdch_test_control_)
1075ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      RecordPacketStats(FilterContext::SDCH_EXPERIMENT_HOLDBACK);
107672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (sdch_test_activated_)
1077ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      RecordPacketStats(FilterContext::SDCH_EXPERIMENT_DECODE);
107872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
1079ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Make sure SDCH filters are told to emit histogram data while
1080ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // filter_context_ is still alive.
108172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DestroyFilters();
1082c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
108372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (sdch_dictionary_url_.is_valid()) {
108472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // Prior to reaching the destructor, request_ has been set to a NULL
108572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // pointer, so request_->url() is no longer valid in the destructor, and we
108672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // use an alternate copy |request_info_.url|.
108772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    SdchManager* manager = SdchManager::Global();
108872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // To be extra safe, since this is a "different time" from when we decided
108972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // to get the dictionary, we'll validate that an SdchManager is available.
109072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // At shutdown time, care is taken to be sure that we don't delete this
109172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // globally useful instance "too soon," so this check is just defensive
109272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // coding to assure that IF the system is shutting down, we don't have any
109372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    // problem if the manager was deleted ahead of time.
109472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    if (manager)  // Defensive programming.
109572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      manager->FetchDictionary(request_info_.url, sdch_dictionary_url_);
1096c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
1097c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
109821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
1099dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid URLRequestHttpJob::RecordTimer() {
1100dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (request_creation_time_.is_null()) {
1101dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    NOTREACHED()
1102dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        << "The same transaction shouldn't start twice without new timing.";
1103dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return;
1104dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
1105dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1106dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  base::TimeDelta to_start = base::Time::Now() - request_creation_time_;
1107dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  request_creation_time_ = base::Time();
1108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  static const bool use_prefetch_histogram =
1110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      base::FieldTrialList::Find("Prefetch") &&
1111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      !base::FieldTrialList::Find("Prefetch")->group_name().empty();
1112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1113dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpTimeToFirstByte", to_start);
1114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (use_prefetch_histogram) {
1115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    UMA_HISTOGRAM_MEDIUM_TIMES(
1116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        base::FieldTrial::MakeName("Net.HttpTimeToFirstByte",
1117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                   "Prefetch"),
1118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        to_start);
1119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
1120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const bool is_prerender = !!(request_info_.load_flags & LOAD_PRERENDER);
1122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (is_prerender) {
1123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpTimeToFirstByte_Prerender",
1124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                               to_start);
1125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (use_prefetch_histogram) {
1126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      UMA_HISTOGRAM_MEDIUM_TIMES(
1127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          base::FieldTrial::MakeName("Net.HttpTimeToFirstByte_Prerender",
1128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                     "Prefetch"),
1129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          to_start);
1130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
1131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else {
1132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpTimeToFirstByte_NonPrerender",
1133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                               to_start);
1134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (use_prefetch_histogram) {
1135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      UMA_HISTOGRAM_MEDIUM_TIMES(
1136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          base::FieldTrial::MakeName("Net.HttpTimeToFirstByte_NonPrerender",
1137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                     "Prefetch"),
1138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          to_start);
1139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
1140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
1141dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
1142dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1143dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenvoid URLRequestHttpJob::ResetTimer() {
1144dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  if (!request_creation_time_.is_null()) {
1145dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    NOTREACHED()
1146dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen        << "The timer was reset before it was recorded.";
1147dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen    return;
1148dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  }
1149dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen  request_creation_time_ = base::Time::Now();
1150dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen}
1151dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen
1152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid URLRequestHttpJob::UpdatePacketReadTimes() {
1153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!packet_timing_enabled_)
1154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
1155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (filter_input_byte_count() <= bytes_observed_in_packets_) {
1157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    DCHECK_EQ(filter_input_byte_count(), bytes_observed_in_packets_);
1158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;  // No new bytes have arrived.
1159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
1160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!bytes_observed_in_packets_)
1162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    request_time_snapshot_ = request_ ? request_->request_time() : base::Time();
1163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  final_packet_time_ = base::Time::Now();
1165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const size_t kTypicalPacketSize = 1430;
1166ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  while (filter_input_byte_count() > bytes_observed_in_packets_) {
1167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    ++observed_packet_count_;
1168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (packet_times_.size() < kSdchPacketHistogramCount) {
1169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      packet_times_.push_back(final_packet_time_);
1170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      DCHECK_EQ(static_cast<size_t>(observed_packet_count_),
1171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                packet_times_.size());
1172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
1173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    bytes_observed_in_packets_ += kTypicalPacketSize;
1174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
1175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Since packets may not be full, we'll remember the number of bytes we've
1176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // accounted for in packets thus far.
1177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bytes_observed_in_packets_ = filter_input_byte_count();
1178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
1179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid URLRequestHttpJob::RecordPacketStats(
1181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    FilterContext::StatisticSelector statistic) const {
1182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!packet_timing_enabled_ || (final_packet_time_ == base::Time()))
1183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
1184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  base::TimeDelta duration = final_packet_time_ - request_time_snapshot_;
1186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  switch (statistic) {
1187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case FilterContext::SDCH_DECODE: {
1188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Decode_Latency_F_a", duration,
1189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromMilliseconds(20),
1190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromMinutes(10), 100);
1191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      UMA_HISTOGRAM_COUNTS_100("Sdch3.Network_Decode_Packets_b",
1192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                               static_cast<int>(observed_packet_count_));
1193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      UMA_HISTOGRAM_CUSTOM_COUNTS("Sdch3.Network_Decode_Bytes_Processed_b",
1194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen          static_cast<int>(bytes_observed_in_packets_), 500, 100000, 100);
1195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (packet_times_.empty())
1196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        return;
1197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Decode_1st_To_Last_a",
1198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  final_packet_time_ - packet_times_[0],
1199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromMilliseconds(20),
1200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromMinutes(10), 100);
1201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      DCHECK_GT(kSdchPacketHistogramCount, 4u);
1203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (packet_times_.size() <= 4)
1204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        return;
1205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Decode_1st_To_2nd_c",
1206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  packet_times_[1] - packet_times_[0],
1207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromMilliseconds(1),
1208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromSeconds(10), 100);
1209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Decode_2nd_To_3rd_c",
1210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  packet_times_[2] - packet_times_[1],
1211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromMilliseconds(1),
1212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromSeconds(10), 100);
1213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Decode_3rd_To_4th_c",
1214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  packet_times_[3] - packet_times_[2],
1215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromMilliseconds(1),
1216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromSeconds(10), 100);
1217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Decode_4th_To_5th_c",
1218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  packet_times_[4] - packet_times_[3],
1219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromMilliseconds(1),
1220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromSeconds(10), 100);
1221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return;
1222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
1223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case FilterContext::SDCH_PASSTHROUGH: {
1224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // Despite advertising a dictionary, we handled non-sdch compressed
1225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // content.
1226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Pass-through_Latency_F_a",
1227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  duration,
1228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromMilliseconds(20),
1229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromMinutes(10), 100);
1230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      UMA_HISTOGRAM_COUNTS_100("Sdch3.Network_Pass-through_Packets_b",
1231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                               observed_packet_count_);
1232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (packet_times_.empty())
1233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        return;
1234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Pass-through_1st_To_Last_a",
1235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  final_packet_time_ - packet_times_[0],
1236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromMilliseconds(20),
1237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromMinutes(10), 100);
1238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      DCHECK_GT(kSdchPacketHistogramCount, 4u);
1239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (packet_times_.size() <= 4)
1240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        return;
1241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Pass-through_1st_To_2nd_c",
1242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  packet_times_[1] - packet_times_[0],
1243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromMilliseconds(1),
1244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromSeconds(10), 100);
1245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Pass-through_2nd_To_3rd_c",
1246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  packet_times_[2] - packet_times_[1],
1247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromMilliseconds(1),
1248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromSeconds(10), 100);
1249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Pass-through_3rd_To_4th_c",
1250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  packet_times_[3] - packet_times_[2],
1251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromMilliseconds(1),
1252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromSeconds(10), 100);
1253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Network_Pass-through_4th_To_5th_c",
1254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  packet_times_[4] - packet_times_[3],
1255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromMilliseconds(1),
1256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromSeconds(10), 100);
1257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return;
1258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
1259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case FilterContext::SDCH_EXPERIMENT_DECODE: {
1261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Experiment_Decode",
1262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  duration,
1263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromMilliseconds(20),
1264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromMinutes(10), 100);
1265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // We already provided interpacket histograms above in the SDCH_DECODE
1266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      // case, so we don't need them here.
1267ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return;
1268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
1269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    case FilterContext::SDCH_EXPERIMENT_HOLDBACK: {
1270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Experiment_Holdback",
1271ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  duration,
1272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromMilliseconds(20),
1273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromMinutes(10), 100);
1274ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Experiment_Holdback_1st_To_Last_a",
1275ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  final_packet_time_ - packet_times_[0],
1276ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromMilliseconds(20),
1277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromMinutes(10), 100);
1278ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1279ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      DCHECK_GT(kSdchPacketHistogramCount, 4u);
1280ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      if (packet_times_.size() <= 4)
1281ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen        return;
1282ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Experiment_Holdback_1st_To_2nd_c",
1283ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  packet_times_[1] - packet_times_[0],
1284ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromMilliseconds(1),
1285ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromSeconds(10), 100);
1286ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Experiment_Holdback_2nd_To_3rd_c",
1287ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  packet_times_[2] - packet_times_[1],
1288ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromMilliseconds(1),
1289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromSeconds(10), 100);
1290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Experiment_Holdback_3rd_To_4th_c",
1291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  packet_times_[3] - packet_times_[2],
1292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromMilliseconds(1),
1293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromSeconds(10), 100);
1294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      UMA_HISTOGRAM_CLIPPED_TIMES("Sdch3.Experiment_Holdback_4th_To_5th_c",
1295ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  packet_times_[4] - packet_times_[3],
1296ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromMilliseconds(1),
1297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  base::TimeDelta::FromSeconds(10), 100);
1298ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return;
1299ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
1300ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    default:
1301ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      NOTREACHED();
1302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      return;
1303ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
1304ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
1305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// The common type of histogram we use for all compression-tracking histograms.
1307ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#define COMPRESSION_HISTOGRAM(name, sample) \
1308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    do { \
1309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      UMA_HISTOGRAM_CUSTOM_COUNTS("Net.Compress." name, sample, \
1310ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen                                  500, 1000000, 100); \
1311ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    } while(0)
1312ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1313ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid URLRequestHttpJob::RecordCompressionHistograms() {
1314ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  DCHECK(request_);
1315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!request_)
1316ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
1317ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (is_cached_content_ ||                // Don't record cached content
1319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      !GetStatus().is_success() ||         // Don't record failed content
1320ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      !IsCompressibleContent() ||          // Only record compressible content
1321ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      !prefilter_bytes_read())       // Zero-byte responses aren't useful.
1322ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
1323ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1324ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Miniature requests aren't really compressible.  Don't count them.
1325ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  const int kMinSize = 16;
1326ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (prefilter_bytes_read() < kMinSize)
1327ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
1328ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1329ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // Only record for http or https urls.
1330ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool is_http = request_->url().SchemeIs("http");
1331ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool is_https = request_->url().SchemeIs("https");
1332ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (!is_http && !is_https)
1333ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
1334ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1335ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int compressed_B = prefilter_bytes_read();
1336ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  int decompressed_B = postfilter_bytes_read();
1337ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  bool was_filtered = HasFilter();
1338ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1339ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // We want to record how often downloaded resources are compressed.
1340ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // But, we recognize that different protocols may have different
1341ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // properties.  So, for each request, we'll put it into one of 3
1342ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // groups:
1343ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  //      a) SSL resources
1344ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  //         Proxies cannot tamper with compression headers with SSL.
1345ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  //      b) Non-SSL, loaded-via-proxy resources
1346ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  //         In this case, we know a proxy might have interfered.
1347ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  //      c) Non-SSL, loaded-without-proxy resources
1348ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  //         In this case, we know there was no explicit proxy.  However,
1349ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  //         it is possible that a transparent proxy was still interfering.
1350ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  //
1351ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  // For each group, we record the same 3 histograms.
1352ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1353ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (is_https) {
1354ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (was_filtered) {
1355ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      COMPRESSION_HISTOGRAM("SSL.BytesBeforeCompression", compressed_B);
1356ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      COMPRESSION_HISTOGRAM("SSL.BytesAfterCompression", decompressed_B);
1357ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    } else {
1358ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      COMPRESSION_HISTOGRAM("SSL.ShouldHaveBeenCompressed", decompressed_B);
1359ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
1360ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
1361ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
1362ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1363ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (request_->was_fetched_via_proxy()) {
1364ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    if (was_filtered) {
1365ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      COMPRESSION_HISTOGRAM("Proxy.BytesBeforeCompression", compressed_B);
1366ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      COMPRESSION_HISTOGRAM("Proxy.BytesAfterCompression", decompressed_B);
1367ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    } else {
1368ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      COMPRESSION_HISTOGRAM("Proxy.ShouldHaveBeenCompressed", decompressed_B);
1369ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    }
1370ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    return;
1371ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
1372ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1373ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  if (was_filtered) {
1374ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    COMPRESSION_HISTOGRAM("NoProxy.BytesBeforeCompression", compressed_B);
1375ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    COMPRESSION_HISTOGRAM("NoProxy.BytesAfterCompression", decompressed_B);
1376ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  } else {
1377ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen    COMPRESSION_HISTOGRAM("NoProxy.ShouldHaveBeenCompressed", decompressed_B);
1378ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  }
1379ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
1380ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
1381ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool URLRequestHttpJob::IsCompressibleContent() const {
1382ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  std::string mime_type;
1383ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  return GetMimeType(&mime_type) &&
1384ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      (IsSupportedJavascriptMimeType(mime_type.c_str()) ||
1385ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen       IsSupportedNonImageMimeType(mime_type.c_str()));
1386ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}
1387ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
138821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}  // namespace net
1389