url_request_http_job.cc revision c7f5f8508d98d5952d42ed7648c2a8f30a4da156
1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright (c) 2010 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"
13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/rand_util.h"
14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/string_util.h"
15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/cert_status_flags.h"
16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/cookie_policy.h"
17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/filter.h"
18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/https_prober.h"
19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/transport_security_state.h"
20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/load_flags.h"
21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_errors.h"
22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_util.h"
23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/sdch_manager.h"
24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/ssl_cert_request_info.h"
25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/http/http_response_headers.h"
26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/http/http_response_info.h"
27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/http/http_transaction.h"
28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/http/http_transaction_factory.h"
29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/http/http_util.h"
30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/url_request/url_request.h"
31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/url_request/url_request_context.h"
32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/url_request/url_request_error_job.h"
33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/url_request/url_request_redirect_job.h"
34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// TODO(darin): make sure the port blocking code is not lost
36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static
37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottURLRequestJob* URLRequestHttpJob::Factory(URLRequest* request,
38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                          const std::string& scheme) {
39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(scheme == "http" || scheme == "https");
40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int port = request->url().IntPort();
42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!net::IsPortAllowedByDefault(port) && !net::IsPortAllowedByOverride(port))
43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return new URLRequestErrorJob(request, net::ERR_UNSAFE_PORT);
44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!request->context() ||
46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      !request->context()->http_transaction_factory()) {
47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NOTREACHED() << "requires a valid context";
48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return new URLRequestErrorJob(request, net::ERR_INVALID_ARGUMENT);
49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  net::TransportSecurityState::DomainState domain_state;
52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (scheme == "http" &&
53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      (request->url().port().empty() || port == 80) &&
54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      request->context()->transport_security_state() &&
55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      request->context()->transport_security_state()->IsEnabledForHost(
56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          &domain_state, request->url().host())) {
57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (domain_state.mode ==
58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         net::TransportSecurityState::DomainState::MODE_STRICT) {
59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      DCHECK_EQ(request->url().scheme(), "http");
60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      url_canon::Replacements<char> replacements;
61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      static const char kNewScheme[] = "https";
62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      replacements.SetScheme(kNewScheme,
63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                             url_parse::Component(0, strlen(kNewScheme)));
64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      GURL new_location = request->url().ReplaceComponents(replacements);
65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return new URLRequestRedirectJob(request, new_location);
66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    } else {
67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // TODO(agl): implement opportunistic HTTPS upgrade.
68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return new URLRequestHttpJob(request);
72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottURLRequestHttpJob::URLRequestHttpJob(URLRequest* request)
75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    : URLRequestJob(request),
76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      context_(request->context()),
77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      response_info_(NULL),
78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      response_cookies_save_index_(0),
79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      proxy_auth_state_(net::AUTH_STATE_DONT_NEED_AUTH),
80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      server_auth_state_(net::AUTH_STATE_DONT_NEED_AUTH),
81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ALLOW_THIS_IN_INITIALIZER_LIST(can_get_cookies_callback_(
82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          this, &URLRequestHttpJob::OnCanGetCookiesCompleted)),
83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ALLOW_THIS_IN_INITIALIZER_LIST(can_set_cookie_callback_(
84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          this, &URLRequestHttpJob::OnCanSetCookieCompleted)),
85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ALLOW_THIS_IN_INITIALIZER_LIST(start_callback_(
86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          this, &URLRequestHttpJob::OnStartCompleted)),
87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ALLOW_THIS_IN_INITIALIZER_LIST(read_callback_(
88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          this, &URLRequestHttpJob::OnReadCompleted)),
89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      read_in_progress_(false),
90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      transaction_(NULL),
91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      sdch_dictionary_advertised_(false),
92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      sdch_test_activated_(false),
93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      sdch_test_control_(false),
94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      is_cached_content_(false) {
95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottURLRequestHttpJob::~URLRequestHttpJob() {
98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!sdch_test_control_ || !sdch_test_activated_);
99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!IsCachedContent()) {
100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (sdch_test_control_)
101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      RecordPacketStats(SDCH_EXPERIMENT_HOLDBACK);
102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (sdch_test_activated_)
103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      RecordPacketStats(SDCH_EXPERIMENT_DECODE);
104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Make sure SDCH filters are told to emit histogram data while this class
106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // can still service the IsCachedContent() call.
107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DestroyFilters();
108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (sdch_dictionary_url_.is_valid()) {
110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Prior to reaching the destructor, request_ has been set to a NULL
111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // pointer, so request_->url() is no longer valid in the destructor, and we
112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // use an alternate copy |request_info_.url|.
113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SdchManager* manager = SdchManager::Global();
114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // To be extra safe, since this is a "different time" from when we decided
115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // to get the dictionary, we'll validate that an SdchManager is available.
116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // At shutdown time, care is taken to be sure that we don't delete this
117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // globally useful instance "too soon," so this check is just defensive
118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // coding to assure that IF the system is shutting down, we don't have any
119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // problem if the manager was deleted ahead of time.
120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (manager)  // Defensive programming.
121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      manager->FetchDictionary(request_info_.url, sdch_dictionary_url_);
122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::SetUpload(net::UploadData* upload) {
126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!transaction_.get()) << "cannot change once started";
127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  request_info_.upload_data = upload;
128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::SetExtraRequestHeaders(
131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const std::string& headers) {
132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!transaction_.get()) << "cannot change once started";
133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  request_info_.extra_headers = headers;
134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::Start() {
137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!transaction_.get());
138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Ensure that we do not send username and password fields in the referrer.
140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  GURL referrer(request_->GetSanitizedReferrer());
141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  request_info_.url = request_->url();
143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  request_info_.referrer = referrer;
144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  request_info_.method = request_->method();
145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  request_info_.load_flags = request_->load_flags();
146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  request_info_.priority = request_->priority();
147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (request_->context()) {
149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    request_info_.user_agent =
150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        request_->context()->GetUserAgent(request_->url());
151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AddExtraHeaders();
154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AddCookieHeaderAndStart();
155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::Kill() {
158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!transaction_.get())
159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DestroyTransaction();
162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  URLRequestJob::Kill();
163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnet::LoadState URLRequestHttpJob::GetLoadState() const {
166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return transaction_.get() ?
167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      transaction_->GetLoadState() : net::LOAD_STATE_IDLE;
168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottuint64 URLRequestHttpJob::GetUploadProgress() const {
171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return transaction_.get() ? transaction_->GetUploadProgress() : 0;
172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool URLRequestHttpJob::GetMimeType(std::string* mime_type) const {
175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(transaction_.get());
176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!response_info_)
178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return response_info_->headers->GetMimeType(mime_type);
181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool URLRequestHttpJob::GetCharset(std::string* charset) {
184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(transaction_.get());
185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!response_info_)
187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return response_info_->headers->GetCharset(charset);
190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::GetResponseInfo(net::HttpResponseInfo* info) {
193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(request_);
194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(transaction_.get());
195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (response_info_)
197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    *info = *response_info_;
198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool URLRequestHttpJob::GetResponseCookies(
201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    std::vector<std::string>* cookies) {
202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(transaction_.get());
203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!response_info_)
205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // TODO(darin): Why are we extracting response cookies again?  Perhaps we
208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // should just leverage response_cookies_.
209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  cookies->clear();
211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FetchResponseCookies(response_info_, cookies);
212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return true;
213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint URLRequestHttpJob::GetResponseCode() const {
216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(transaction_.get());
217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!response_info_)
219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return -1;
220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return response_info_->headers->response_code();
222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool URLRequestHttpJob::GetContentEncodings(
225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    std::vector<Filter::FilterType>* encoding_types) {
226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(transaction_.get());
227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!response_info_)
228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(encoding_types->empty());
230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string encoding_type;
232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void* iter = NULL;
233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  while (response_info_->headers->EnumerateHeader(&iter, "Content-Encoding",
234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                  &encoding_type)) {
235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    encoding_types->push_back(Filter::ConvertEncodingToType(encoding_type));
236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Even if encoding types are empty, there is a chance that we need to add
239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // some decoding, as some proxies strip encoding completely. In such cases,
240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // we may need to add (for example) SDCH filtering (when the context suggests
241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // it is appropriate).
242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Filter::FixupEncodingTypes(*this, encoding_types);
243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return !encoding_types->empty();
245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool URLRequestHttpJob::IsSdchResponse() const {
248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return sdch_dictionary_advertised_;
249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool URLRequestHttpJob::IsSafeRedirect(const GURL& location) {
252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We only allow redirects to certain "safe" protocols.  This does not
253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // restrict redirects to externally handled protocols.  Our consumer would
254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // need to take care of those.
255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!URLRequest::IsHandledURL(location))
257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return true;
258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const char* kSafeSchemes[] = {
260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "http",
261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "https",
262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    "ftp"
263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  };
264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  for (size_t i = 0; i < arraysize(kSafeSchemes); ++i) {
266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (location.SchemeIs(kSafeSchemes[i]))
267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return true;
268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return false;
271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool URLRequestHttpJob::NeedsAuth() {
274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int code = GetResponseCode();
275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (code == -1)
276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Check if we need either Proxy or WWW Authentication.  This could happen
279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // because we either provided no auth info, or provided incorrect info.
280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  switch (code) {
281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case 407:
282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (proxy_auth_state_ == net::AUTH_STATE_CANCELED)
283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return false;
284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      proxy_auth_state_ = net::AUTH_STATE_NEED_AUTH;
285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return true;
286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    case 401:
287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (server_auth_state_ == net::AUTH_STATE_CANCELED)
288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        return false;
289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      server_auth_state_ = net::AUTH_STATE_NEED_AUTH;
290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return true;
291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return false;
293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::GetAuthChallengeInfo(
296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    scoped_refptr<net::AuthChallengeInfo>* result) {
297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(transaction_.get());
298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(response_info_);
299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // sanity checks:
301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(proxy_auth_state_ == net::AUTH_STATE_NEED_AUTH ||
302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         server_auth_state_ == net::AUTH_STATE_NEED_AUTH);
303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(response_info_->headers->response_code() == 401 ||
304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott         response_info_->headers->response_code() == 407);
305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  *result = response_info_->auth_challenge;
307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::SetAuth(const std::wstring& username,
310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                const std::wstring& password) {
311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(transaction_.get());
312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Proxy gets set first, then WWW.
314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (proxy_auth_state_ == net::AUTH_STATE_NEED_AUTH) {
315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    proxy_auth_state_ = net::AUTH_STATE_HAVE_AUTH;
316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(server_auth_state_ == net::AUTH_STATE_NEED_AUTH);
318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    server_auth_state_ = net::AUTH_STATE_HAVE_AUTH;
319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  RestartTransactionWithAuth(username, password);
322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::RestartTransactionWithAuth(
325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const std::wstring& username,
326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const std::wstring& password) {
327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  username_ = username;
328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  password_ = password;
329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // These will be reset in OnStartCompleted.
331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  response_info_ = NULL;
332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  response_cookies_.clear();
333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Update the cookies, since the cookie store may have been updated from the
335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // headers in the 401/407. Since cookies were already appended to
336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // extra_headers, we need to strip them out before adding them again.
337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  static const char* const cookie_name[] = { "cookie" };
338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  request_info_.extra_headers = net::HttpUtil::StripHeaders(
339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      request_info_.extra_headers, cookie_name, arraysize(cookie_name));
340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AddCookieHeaderAndStart();
342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::CancelAuth() {
345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Proxy gets set first, then WWW.
346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (proxy_auth_state_ == net::AUTH_STATE_NEED_AUTH) {
347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    proxy_auth_state_ = net::AUTH_STATE_CANCELED;
348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(server_auth_state_ == net::AUTH_STATE_NEED_AUTH);
350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    server_auth_state_ = net::AUTH_STATE_CANCELED;
351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // These will be reset in OnStartCompleted.
354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  response_info_ = NULL;
355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  response_cookies_.clear();
356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // OK, let the consumer read the error page...
358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //
359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Because we set the AUTH_STATE_CANCELED flag, NeedsAuth will return false,
360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // which will cause the consumer to receive OnResponseStarted instead of
361c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // OnAuthRequired.
362c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //
363c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // We have to do this via InvokeLater to avoid "recursing" the consumer.
364c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  //
365c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
366c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      this, &URLRequestHttpJob::OnStartCompleted, net::OK));
367c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::ContinueWithCertificate(
370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    net::X509Certificate* client_cert) {
371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(transaction_.get());
372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!response_info_) << "should not have a response yet";
374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // No matter what, we want to report our status as IO pending since we will
376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // be notifying our consumer asynchronously via OnStartCompleted.
377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int rv = transaction_->RestartWithCertificate(client_cert, &start_callback_);
380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rv == net::ERR_IO_PENDING)
381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The transaction started synchronously, but we need to notify the
384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // URLRequest delegate via the message loop.
385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      this, &URLRequestHttpJob::OnStartCompleted, rv));
387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::ContinueDespiteLastError() {
390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If the transaction was destroyed, then the job was cancelled.
391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!transaction_.get())
392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!response_info_) << "should not have a response yet";
395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // No matter what, we want to report our status as IO pending since we will
397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // be notifying our consumer asynchronously via OnStartCompleted.
398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int rv = transaction_->RestartIgnoringLastError(&start_callback_);
401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rv == net::ERR_IO_PENDING)
402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The transaction started synchronously, but we need to notify the
405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // URLRequest delegate via the message loop.
406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      this, &URLRequestHttpJob::OnStartCompleted, rv));
408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool URLRequestHttpJob::ReadRawData(net::IOBuffer* buf, int buf_size,
411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                    int *bytes_read) {
412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK_NE(buf_size, 0);
413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(bytes_read);
414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!read_in_progress_);
415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int rv = transaction_->Read(buf, buf_size, &read_callback_);
417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rv >= 0) {
418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    *bytes_read = rv;
419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return true;
420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rv == net::ERR_IO_PENDING) {
423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    read_in_progress_ = true;
424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, rv));
427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
428c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
429c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return false;
430c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
432c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::OnCanGetCookiesCompleted(int policy) {
433c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If the request was destroyed, then there is no more work to do.
434c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (request_ && request_->delegate()) {
435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (policy == net::OK && request_->context()->cookie_store()) {
436c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      net::CookieOptions options;
437c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      options.set_include_httponly();
438c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      std::string cookies =
439c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          request_->context()->cookie_store()->GetCookiesWithOptions(
440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott              request_->url(), options);
441c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (request_->context()->InterceptRequestCookies(request_, cookies) &&
442c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          !cookies.empty())
443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        request_info_.extra_headers += "Cookie: " + cookies + "\r\n";
444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
445c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    StartTransaction();
446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
447c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Release();  // Balance AddRef taken in AddCookieHeaderAndStart
448c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
449c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
450c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::OnCanSetCookieCompleted(int policy) {
451c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If the request was destroyed, then there is no more work to do.
452c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (request_ && request_->delegate()) {
453c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (policy == net::OK && request_->context()->cookie_store()) {
454c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // OK to save the current response cookie now.
455c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      net::CookieOptions options;
456c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      options.set_include_httponly();
457c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      request_->context()->cookie_store()->SetCookieWithOptions(
458c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          request_->url(), response_cookies_[response_cookies_save_index_],
459c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          options);
460c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
461c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    response_cookies_save_index_++;
462c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SaveNextCookie();
463c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
464c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  Release();  // Balance AddRef taken in SaveNextCookie
465c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
466c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
467c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::OnStartCompleted(int result) {
468c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If the request was destroyed, then there is no more work to do.
469c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!request_ || !request_->delegate())
470c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
471c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
472c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If the transaction was destroyed, then the job was cancelled, and
473c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // we can just ignore this notification.
474c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!transaction_.get())
475c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
476c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
477c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Clear the IO_PENDING status
478c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SetStatus(URLRequestStatus());
479c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
480c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result == net::OK) {
481c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SaveCookiesAndNotifyHeadersComplete();
482c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else if (ShouldTreatAsCertificateError(result)) {
483c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // We encountered an SSL certificate error.  Ask our delegate to decide
484c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // what we should do.
485c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // TODO(wtc): also pass ssl_info.cert_status, or just pass the whole
486c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // ssl_info.
487c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    request_->delegate()->OnSSLCertificateError(
488c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        request_, result, transaction_->GetResponseInfo()->ssl_info.cert);
489c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else if (result == net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
490c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    request_->delegate()->OnCertificateRequested(
491c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        request_, transaction_->GetResponseInfo()->cert_request_info);
492c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
493c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result));
494c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
495c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
496c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
497c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::OnReadCompleted(int result) {
498c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  read_in_progress_ = false;
499c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
500c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (result == 0) {
501c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NotifyDone(URLRequestStatus());
502c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else if (result < 0) {
503c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NotifyDone(URLRequestStatus(URLRequestStatus::FAILED, result));
504c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
505c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Clear the IO_PENDING status
506c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SetStatus(URLRequestStatus());
507c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
508c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
509c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  NotifyReadComplete(result);
510c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
511c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
512c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool URLRequestHttpJob::ShouldTreatAsCertificateError(int result) {
513c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!net::IsCertificateError(result))
514c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return false;
515c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
516c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Check whether our context is using Strict-Transport-Security.
517c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!context_->transport_security_state())
518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return true;
519c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
520c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  net::TransportSecurityState::DomainState domain_state;
521c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // TODO(agl): don't ignore opportunistic mode.
522c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const bool r = context_->transport_security_state()->IsEnabledForHost(
523c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      &domain_state, request_info_.url.host());
524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  return !r || domain_state.mode ==
526c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott               net::TransportSecurityState::DomainState::MODE_OPPORTUNISTIC;
527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::NotifyHeadersComplete() {
530c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(!response_info_);
531c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
532c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  response_info_ = transaction_->GetResponseInfo();
533c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
534c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Save boolean, as we'll need this info at destruction time, and filters may
535c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // also need this info.
536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  is_cached_content_ = response_info_->was_cached;
537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  ProcessStrictTransportSecurityHeader();
539c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
540c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (SdchManager::Global() &&
541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      SdchManager::Global()->IsInSupportedDomain(request_->url())) {
542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    static const std::string name = "Get-Dictionary";
543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    std::string url_text;
544c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    void* iter = NULL;
545c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // TODO(jar): We need to not fetch dictionaries the first time they are
546c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // seen, but rather wait until we can justify their usefulness.
547c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // For now, we will only fetch the first dictionary, which will at least
548c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // require multiple suggestions before we get additional ones for this site.
549c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Eventually we should wait until a dictionary is requested several times
550c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // before we even download it (so that we don't waste memory or bandwidth).
551c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (response_info_->headers->EnumerateHeader(&iter, name, &url_text)) {
552c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // request_->url() won't be valid in the destructor, so we use an
553c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // alternate copy.
554c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      DCHECK(request_->url() == request_info_.url);
555c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Resolve suggested URL relative to request url.
556c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      sdch_dictionary_url_ = request_info_.url.Resolve(url_text);
557c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
558c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
559c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
560c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The HTTP transaction may be restarted several times for the purposes
561c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // of sending authorization information. Each time it restarts, we get
562c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // notified of the headers completion so that we can update the cookie store.
563c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (transaction_->IsReadyToRestartForAuth()) {
564c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(!response_info_->auth_challenge.get());
565c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    RestartTransactionWithAuth(std::wstring(), std::wstring());
566c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
567c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
568c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
569c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  URLRequestJob::NotifyHeadersComplete();
570c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
571c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
572c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
573c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma optimize("", off)
574c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma warning(disable:4748)
575c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
576c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::DestroyTransaction() {
577c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  CHECK(transaction_.get());
578c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // TODO(rvargas): remove this after finding the cause for bug 31723.
579c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  char local_obj[sizeof(*this)];
580c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  memcpy(local_obj, this, sizeof(local_obj));
581c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  transaction_.reset();
583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  response_info_ = NULL;
584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(OS_WIN)
586c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma warning(default:4748)
587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#pragma optimize("", on)
588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif
589c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
590c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::StartTransaction() {
591c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // NOTE: This method assumes that request_info_ is already setup properly.
592c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
593c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // If we already have a transaction, then we should restart the transaction
594c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // with auth provided by username_ and password_.
595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
596c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int rv;
597c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (transaction_.get()) {
598c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    rv = transaction_->RestartWithAuth(username_, password_, &start_callback_);
599c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    username_.clear();
600c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    password_.clear();
601c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
602c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(request_->context());
603c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    DCHECK(request_->context()->http_transaction_factory());
604c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
605c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    rv = request_->context()->http_transaction_factory()->CreateTransaction(
606c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        &transaction_);
607c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (rv == net::OK) {
608c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      rv = transaction_->Start(
609c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          &request_info_, &start_callback_, request_->load_log());
610c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
611c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
612c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
613c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (rv == net::ERR_IO_PENDING)
614c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
615c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
616c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The transaction started synchronously, but we need to notify the
617c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // URLRequest delegate via the message loop.
618c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(
619c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      this, &URLRequestHttpJob::OnStartCompleted, rv));
620c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
621c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
622c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::AddExtraHeaders() {
623c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // TODO(jar): Consider optimizing away SDCH advertising bytes when the URL is
624c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // probably an img or such (and SDCH encoding is not likely).
625c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool advertise_sdch = SdchManager::Global() &&
626c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      SdchManager::Global()->IsInSupportedDomain(request_->url());
627c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string avail_dictionaries;
628c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (advertise_sdch) {
629c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SdchManager::Global()->GetAvailDictionaryList(request_->url(),
630c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                  &avail_dictionaries);
631c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
632c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // The AllowLatencyExperiment() is only true if we've successfully done a
633c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // full SDCH compression recently in this browser session for this host.
634c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Note that for this path, there might be no applicable dictionaries, and
635c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // hence we can't participate in the experiment.
636c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!avail_dictionaries.empty() &&
637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        SdchManager::Global()->AllowLatencyExperiment(request_->url())) {
638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // We are participating in the test (or control), and hence we'll
639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // eventually record statistics via either SDCH_EXPERIMENT_DECODE or
640c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // SDCH_EXPERIMENT_HOLDBACK, and we'll need some packet timing data.
641c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EnablePacketCounting(kSdchPacketHistogramCount);
642c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      if (base::RandDouble() < .01) {
643c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        sdch_test_control_ = true;  // 1% probability.
644c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        advertise_sdch = false;
645c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      } else {
646c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        sdch_test_activated_ = true;
647c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      }
648c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
649c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Supply Accept-Encoding headers first so that it is more likely that they
652c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // will be in the first transmitted packet.  This can sometimes make it easier
653c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // to filter and analyze the streams to assure that a proxy has not damaged
654c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // these headers.  Some proxies deliberately corrupt Accept-Encoding headers.
655c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!advertise_sdch) {
656c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Tell the server what compression formats we support (other than SDCH).
657c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    request_info_.extra_headers += "Accept-Encoding: gzip,deflate\r\n";
658c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else {
659c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Include SDCH in acceptable list.
660c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    request_info_.extra_headers += "Accept-Encoding: "
661c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        "gzip,deflate,sdch\r\n";
662c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!avail_dictionaries.empty()) {
663c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      request_info_.extra_headers += "Avail-Dictionary: "
664c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          + avail_dictionaries + "\r\n";
665c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      sdch_dictionary_advertised_ = true;
666c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // Since we're tagging this transaction as advertising a dictionary, we'll
667c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // definately employ an SDCH filter (or tentative sdch filter) when we get
668c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // a response.  When done, we'll record histograms via SDCH_DECODE or
669c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      // SDCH_PASSTHROUGH.  Hence we need to record packet arrival times.
670c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      EnablePacketCounting(kSdchPacketHistogramCount);
671c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
672c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
673c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
674c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  URLRequestContext* context = request_->context();
675c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (context) {
676c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // Only add default Accept-Language and Accept-Charset if the request
677c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // didn't have them specified.
678c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    net::HttpUtil::AppendHeaderIfMissing("Accept-Language",
679c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                         context->accept_language(),
680c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                         &request_info_.extra_headers);
681c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    net::HttpUtil::AppendHeaderIfMissing("Accept-Charset",
682c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                         context->accept_charset(),
683c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                         &request_info_.extra_headers);
684c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
685c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
686c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
687c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::AddCookieHeaderAndStart() {
688c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // No matter what, we want to report our status as IO pending since we will
689c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // be notifying our consumer asynchronously via OnStartCompleted.
690c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
691c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
692c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AddRef();  // Balanced in OnCanGetCookiesCompleted
693c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
694c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int policy = net::OK;
695c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
696c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (request_info_.load_flags & net::LOAD_DO_NOT_SEND_COOKIES) {
697c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    policy = net::ERR_ACCESS_DENIED;
698c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else if (request_->context()->cookie_policy()) {
699c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    policy = request_->context()->cookie_policy()->CanGetCookies(
700c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        request_->url(),
701c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        request_->first_party_for_cookies(),
702c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        &can_get_cookies_callback_);
703c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (policy == net::ERR_IO_PENDING)
704c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return;  // Wait for completion callback
705c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
706c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
707c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  OnCanGetCookiesCompleted(policy);
708c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
709c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
710c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::SaveCookiesAndNotifyHeadersComplete() {
711c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(transaction_.get());
712c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
713c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const net::HttpResponseInfo* response_info = transaction_->GetResponseInfo();
714c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(response_info);
715c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
716c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  response_cookies_.clear();
717c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  response_cookies_save_index_ = 0;
718c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
719c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  FetchResponseCookies(response_info, &response_cookies_);
720c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
721c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // Now, loop over the response cookies, and attempt to persist each.
722c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SaveNextCookie();
723c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
724c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
725c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::SaveNextCookie() {
726c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (response_cookies_save_index_ == response_cookies_.size()) {
727c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    response_cookies_.clear();
728c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    response_cookies_save_index_ = 0;
729c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    SetStatus(URLRequestStatus());  // Clear the IO_PENDING status
730c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    NotifyHeadersComplete();
731c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
732c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
733c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
734c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // No matter what, we want to report our status as IO pending since we will
735c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // be notifying our consumer asynchronously via OnStartCompleted.
736c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0));
737c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
738c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  AddRef();  // Balanced in OnCanSetCookieCompleted
739c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
740c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int policy = net::OK;
741c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
742c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (request_info_.load_flags & net::LOAD_DO_NOT_SAVE_COOKIES) {
743c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    policy = net::ERR_ACCESS_DENIED;
744c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  } else if (request_->context()->cookie_policy()) {
745c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    policy = request_->context()->cookie_policy()->CanSetCookie(
746c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        request_->url(),
747c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        request_->first_party_for_cookies(),
748c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        response_cookies_[response_cookies_save_index_],
749c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        &can_set_cookie_callback_);
750c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (policy == net::ERR_IO_PENDING)
751c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      return;  // Wait for completion callback
752c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
753c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
754c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  OnCanSetCookieCompleted(policy);
755c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
756c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
757c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::FetchResponseCookies(
758c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const net::HttpResponseInfo* response_info,
759c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    std::vector<std::string>* cookies) {
760c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string name = "Set-Cookie";
761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string value;
762c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
763c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void* iter = NULL;
764c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  while (response_info->headers->EnumerateHeader(&iter, name, &value)) {
765c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (request_->context()->InterceptResponseCookie(request_, value))
766c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      cookies->push_back(value);
767c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
768c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
769c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
770c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass HTTPSProberDelegate : public net::HTTPSProberDelegate {
771c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public:
772c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  HTTPSProberDelegate(const std::string& host, int max_age,
773c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                      bool include_subdomains,
774c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                      net::TransportSecurityState* sts)
775c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      : host_(host),
776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        max_age_(max_age),
777c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        include_subdomains_(include_subdomains),
778c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        sts_(sts) { }
779c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
780c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  virtual void ProbeComplete(bool result) {
781c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (result) {
782c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      base::Time current_time(base::Time::Now());
783c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      base::TimeDelta max_age_delta = base::TimeDelta::FromSeconds(max_age_);
784c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
785c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      net::TransportSecurityState::DomainState domain_state;
786c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      domain_state.expiry = current_time + max_age_delta;
787c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      domain_state.mode =
788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          net::TransportSecurityState::DomainState::MODE_OPPORTUNISTIC;
789c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      domain_state.include_subdomains = include_subdomains_;
790c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
791c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      sts_->EnableHost(host_, domain_state);
792c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
793c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
794c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    delete this;
795c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
796c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
797c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private:
798c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const std::string host_;
799c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const int max_age_;
800c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const bool include_subdomains_;
801c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  scoped_refptr<net::TransportSecurityState> sts_;
802c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott};
803c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
804c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid URLRequestHttpJob::ProcessStrictTransportSecurityHeader() {
805c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  DCHECK(response_info_);
806c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
807c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  URLRequestContext* ctx = request_->context();
808c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  if (!ctx || !ctx->transport_security_state())
809c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    return;
810c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
811c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const bool https = response_info_->ssl_info.is_valid();
812c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  const bool valid_https =
813c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      https &&
814c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      !(response_info_->ssl_info.cert_status & net::CERT_STATUS_ALL_ERRORS);
815c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
816c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string name = "Strict-Transport-Security";
817c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  std::string value;
818c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
819c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  int max_age;
820c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  bool include_subdomains;
821c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
822c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  void* iter = NULL;
823c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  while (response_info_->headers->EnumerateHeader(&iter, name, &value)) {
824c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const bool ok = net::TransportSecurityState::ParseHeader(
825c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        value, &max_age, &include_subdomains);
826c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!ok)
827c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      continue;
828c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // We will only accept strict mode if we saw the header from an HTTPS
829c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // connection with no certificate problems.
830c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!valid_https)
831c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      continue;
832c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    base::Time current_time(base::Time::Now());
833c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    base::TimeDelta max_age_delta = base::TimeDelta::FromSeconds(max_age);
834c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
835c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    net::TransportSecurityState::DomainState domain_state;
836c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    domain_state.expiry = current_time + max_age_delta;
837c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    domain_state.mode = net::TransportSecurityState::DomainState::MODE_STRICT;
838c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    domain_state.include_subdomains = include_subdomains;
839c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
840c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    ctx->transport_security_state()->EnableHost(request_info_.url.host(),
841c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                domain_state);
842c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
843c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
844c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // TODO(agl): change this over when we have fixed things at the server end.
845c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  // The string should be "Opportunistic-Transport-Security";
846c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  name = "X-Bodge-Transport-Security";
847c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
848c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  while (response_info_->headers->EnumerateHeader(&iter, name, &value)) {
849c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    const bool ok = net::TransportSecurityState::ParseHeader(
850c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        value, &max_age, &include_subdomains);
851c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!ok)
852c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      continue;
853c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // If we saw an opportunistic request over HTTPS, then clearly we can make
854c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // HTTPS connections to the host so we should remember this.
855c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (https) {
856c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      base::Time current_time(base::Time::Now());
857c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      base::TimeDelta max_age_delta = base::TimeDelta::FromSeconds(max_age);
858c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
859c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      net::TransportSecurityState::DomainState domain_state;
860c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      domain_state.expiry = current_time + max_age_delta;
861c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      domain_state.mode =
862c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott          net::TransportSecurityState::DomainState::MODE_SPDY_ONLY;
863c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      domain_state.include_subdomains = include_subdomains;
864c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
865c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      ctx->transport_security_state()->EnableHost(request_info_.url.host(),
866c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                                  domain_state);
867c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      continue;
868c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
869c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
870c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!request())
871c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      break;
872c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
873c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // At this point, we have a request for opportunistic encryption over HTTP.
874c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // In this case we need to probe to check that we can make HTTPS
875c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    // connections to that host.
876c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    net::HTTPSProber* const prober = Singleton<net::HTTPSProber>::get();
877c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (prober->HaveProbed(request_info_.url.host()) ||
878c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        prober->InFlight(request_info_.url.host())) {
879c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      continue;
880c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
881c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott
882c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    net::HTTPSProberDelegate* delegate =
883c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott        new HTTPSProberDelegate(request_info_.url.host(), max_age,
884c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                include_subdomains,
885c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                                ctx->transport_security_state());
886c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    if (!prober->ProbeHost(request_info_.url.host(), request()->context(),
887c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott                           delegate)) {
888c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott      delete delegate;
889c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott    }
890c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott  }
891c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}
892