http_proxy_client_socket.cc revision 21d179b334e59e9a3bfcaed4c4430bef1bc5759d
1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_proxy_client_socket.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/string_util.h"
83345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/stringprintf.h"
9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "googleurl/src/gurl.h"
103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/base/auth.h"
11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/host_port_pair.h"
12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/io_buffer.h"
13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_log.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/base/net_util.h"
1521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "net/http/http_basic_stream.h"
16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_net_log_params.h"
17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_network_session.h"
18731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/http/http_proxy_utils.h"
19c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/http/http_request_info.h"
20731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "net/http/http_response_headers.h"
213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "net/http/http_stream_parser.h"
22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "net/socket/client_socket_handle.h"
23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace net {
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochHttpProxyClientSocket::HttpProxyClientSocket(
273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    ClientSocketHandle* transport_socket,
283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const GURL& request_url,
293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const std::string& user_agent,
303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const HostPortPair& endpoint,
313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    const HostPortPair& proxy_server,
323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    HttpAuthCache* http_auth_cache,
333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    HttpAuthHandlerFactory* http_auth_handler_factory,
343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    bool tunnel,
3521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    bool using_spdy,
3621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    bool is_https_proxy)
37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : ALLOW_THIS_IN_INITIALIZER_LIST(
38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          io_callback_(this, &HttpProxyClientSocket::OnIOComplete)),
39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      next_state_(STATE_NONE),
40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      user_callback_(NULL),
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      transport_(transport_socket),
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      endpoint_(endpoint),
433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      auth_(tunnel ?
443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          new HttpAuthController(HttpAuth::AUTH_PROXY,
453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                 GURL("http://" + proxy_server.ToString()),
463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                 http_auth_cache,
473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                 http_auth_handler_factory)
483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick          : NULL),
49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      tunnel_(tunnel),
503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      using_spdy_(using_spdy),
5121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      is_https_proxy_(is_https_proxy),
52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      net_log_(transport_socket->socket()->NetLog()) {
53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Synthesize the bits of a request that we actually use.
54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_.url = request_url;
55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  request_.method = "GET";
563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (!user_agent.empty())
573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    request_.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                     user_agent);
59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
61c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochHttpProxyClientSocket::~HttpProxyClientSocket() {
62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Disconnect();
63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
6521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen<<<<<<< HEAD
667b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#ifdef ANDROID
677b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen// TODO(kristianm): handle the case when wait_for_connect is true
687b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen// (sync requests)
697b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#endif
707b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsenint HttpProxyClientSocket::Connect(CompletionCallback* callback
717b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#ifdef ANDROID
727b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen                                   , bool wait_for_connect
737b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#endif
747b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen                                  ) {
7521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen=======
7621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenHttpStream* HttpProxyClientSocket::CreateConnectResponseStream() {
7721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return new HttpBasicStream(transport_.release(),
7821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                             http_stream_parser_.release(), false);
7921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
8021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
8121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
8221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenint HttpProxyClientSocket::Connect(CompletionCallback* callback) {
8321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen>>>>>>> chromium.org at r10.0.621.0
84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(transport_.get());
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(transport_->socket());
86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!user_callback_);
87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
883345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // TODO(rch): figure out the right way to set up a tunnel with SPDY.
893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // This approach sends the complete HTTPS request to the proxy
903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // which allows the proxy to see "private" data.  Instead, we should
913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // create an SSL tunnel to the origin server using the CONNECT method
923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  // inside a single SPDY stream.
933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (using_spdy_ || !tunnel_)
94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    next_state_ = STATE_DONE;
95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (next_state_ == STATE_DONE)
96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return OK;
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_EQ(STATE_NONE, next_state_);
99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  next_state_ = STATE_GENERATE_AUTH_TOKEN;
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = DoLoop(OK);
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (rv == ERR_IO_PENDING)
103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    user_callback_ = callback;
104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return rv;
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::RestartWithAuth(CompletionCallback* callback) {
108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_EQ(STATE_NONE, next_state_);
109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!user_callback_);
110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = PrepareForAuthRestart();
112c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (rv != OK)
113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return rv;
114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  rv = DoLoop(OK);
116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (rv == ERR_IO_PENDING)
117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    user_callback_ = callback;
118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return rv;
119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::PrepareForAuthRestart() {
122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!response_.headers.get())
123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return ERR_CONNECTION_RESET;
124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  bool keep_alive = false;
126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (response_.headers->IsKeepAlive() &&
1273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      http_stream_parser_->CanFindEndOfResponse()) {
1283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    if (!http_stream_parser_->IsResponseBodyComplete()) {
129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      next_state_ = STATE_DRAIN_BODY;
130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      drain_buf_ = new IOBuffer(kDrainBodyBufferSize);
131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return OK;
132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    keep_alive = true;
134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // We don't need to drain the response body, so we act as if we had drained
137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // the response body.
138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return DidDrainBodyForAuthRestart(keep_alive);
139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::DidDrainBodyForAuthRestart(bool keep_alive) {
142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (keep_alive && transport_->socket()->IsConnectedAndIdle()) {
143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    next_state_ = STATE_GENERATE_AUTH_TOKEN;
144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    transport_->set_is_reused(true);
145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  } else {
1463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // This assumes that the underlying transport socket is a TCP socket,
1473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    // since only TCP sockets are restartable.
1483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    next_state_ = STATE_TCP_RESTART;
149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    transport_->socket()->Disconnect();
150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Reset the other member variables.
153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  drain_buf_ = NULL;
1543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  parser_buf_ = NULL;
1553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  http_stream_parser_.reset();
1564a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  request_line_.clear();
1574a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  request_headers_.Clear();
158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response_ = HttpResponseInfo();
1593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return OK;
160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HttpProxyClientSocket::LogBlockedTunnelResponse(int response_code) const {
163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  LOG(WARNING) << "Blocked proxy response with status " << response_code
164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               << " to CONNECT request for "
165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch               << GetHostAndPort(request_.url) << ".";
166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HttpProxyClientSocket::Disconnect() {
16921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  if (transport_.get())
17021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen    transport_->socket()->Disconnect();
171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Reset other states to make sure they aren't mistakenly used later.
173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // These are the states initialized by Connect().
174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  next_state_ = STATE_NONE;
175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  user_callback_ = NULL;
176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool HttpProxyClientSocket::IsConnected() const {
1793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return next_state_ == STATE_DONE && transport_->socket()->IsConnected();
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool HttpProxyClientSocket::IsConnectedAndIdle() const {
1833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return next_state_ == STATE_DONE &&
1843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    transport_->socket()->IsConnectedAndIdle();
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
18721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenconst BoundNetLog& HttpProxyClientSocket::NetLog() const {
18821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  return net_log_;
18921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}
19021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen
1913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid HttpProxyClientSocket::SetSubresourceSpeculation() {
1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (transport_.get() && transport_->socket()) {
1933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    transport_->socket()->SetSubresourceSpeculation();
1943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  } else {
1953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    NOTREACHED();
1963345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
1973345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
1983345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid HttpProxyClientSocket::SetOmniboxSpeculation() {
2003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (transport_.get() && transport_->socket()) {
2013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    transport_->socket()->SetOmniboxSpeculation();
2023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  } else {
2033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    NOTREACHED();
2043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
2063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
2073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool HttpProxyClientSocket::WasEverUsed() const {
2083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (transport_.get() && transport_->socket()) {
2093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return transport_->socket()->WasEverUsed();
2103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  }
2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  NOTREACHED();
2123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return false;
213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
215513209b27ff55e2841eac0e4120199c23acce758Ben Murdochbool HttpProxyClientSocket::UsingTCPFastOpen() const {
216513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  if (transport_.get() && transport_->socket()) {
217513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch    return transport_->socket()->UsingTCPFastOpen();
218513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  }
219513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  NOTREACHED();
220513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  return false;
221513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch}
222513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch
223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::Read(IOBuffer* buf, int buf_len,
2243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                CompletionCallback* callback) {
225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!user_callback_);
226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (next_state_ != STATE_DONE) {
227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We're trying to read the body of the response but we're still trying
228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // to establish an SSL tunnel through the proxy.  We can't read these
229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // bytes when establishing a tunnel because they might be controlled by
230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // an active network attacker.  We don't worry about this for HTTP
231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // because an active network attacker can already control HTTP sessions.
232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // We reach this case when the user cancels a 407 proxy auth prompt.
233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    // See http://crbug.com/8473.
234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DCHECK_EQ(407, response_.headers->response_code());
235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    LogBlockedTunnelResponse(response_.headers->response_code());
236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return ERR_TUNNEL_CONNECTION_FAILED;
238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return transport_->socket()->Read(buf, buf_len, callback);
241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::Write(IOBuffer* buf, int buf_len,
244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                                 CompletionCallback* callback) {
245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_EQ(STATE_DONE, next_state_);
246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(!user_callback_);
247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return transport_->socket()->Write(buf, buf_len, callback);
249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool HttpProxyClientSocket::SetReceiveBufferSize(int32 size) {
252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return transport_->socket()->SetReceiveBufferSize(size);
253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool HttpProxyClientSocket::SetSendBufferSize(int32 size) {
256c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return transport_->socket()->SetSendBufferSize(size);
257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
258c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::GetPeerAddress(AddressList* address) const {
260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return transport_->socket()->GetPeerAddress(address);
261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HttpProxyClientSocket::DoCallback(int result) {
264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_NE(ERR_IO_PENDING, result);
265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(user_callback_);
266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Since Run() may result in Read being called,
268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // clear user_callback_ up front.
269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  CompletionCallback* c = user_callback_;
270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  user_callback_ = NULL;
271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  c->Run(result);
272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid HttpProxyClientSocket::OnIOComplete(int result) {
275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_NE(STATE_NONE, next_state_);
276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_NE(STATE_DONE, next_state_);
277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = DoLoop(result);
278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (rv != ERR_IO_PENDING)
279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    DoCallback(rv);
280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::DoLoop(int last_io_result) {
283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_NE(next_state_, STATE_NONE);
284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_NE(next_state_, STATE_DONE);
285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = last_io_result;
286c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  do {
287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    State state = next_state_;
288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    next_state_ = STATE_NONE;
289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    switch (state) {
290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case STATE_GENERATE_AUTH_TOKEN:
291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        DCHECK_EQ(OK, rv);
292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        rv = DoGenerateAuthToken();
293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case STATE_GENERATE_AUTH_TOKEN_COMPLETE:
295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        rv = DoGenerateAuthTokenComplete(rv);
296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case STATE_SEND_REQUEST:
298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        DCHECK_EQ(OK, rv);
299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST,
300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            NULL);
301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        rv = DoSendRequest();
302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case STATE_SEND_REQUEST_COMPLETE:
304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        rv = DoSendRequestComplete(rv);
305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST,
306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          NULL);
307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case STATE_READ_HEADERS:
309c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        DCHECK_EQ(OK, rv);
310c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS,
311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                            NULL);
312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        rv = DoReadHeaders();
313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case STATE_READ_HEADERS_COMPLETE:
315c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        rv = DoReadHeadersComplete(rv);
316c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        net_log_.EndEvent(NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS,
317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                          NULL);
318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case STATE_DRAIN_BODY:
320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        DCHECK_EQ(OK, rv);
321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        rv = DoDrainBody();
322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case STATE_DRAIN_BODY_COMPLETE:
324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        rv = DoDrainBodyComplete(rv);
325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
3263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      case STATE_TCP_RESTART:
3273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        DCHECK_EQ(OK, rv);
3283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        rv = DoTCPRestart();
3293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        break;
3303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      case STATE_TCP_RESTART_COMPLETE:
3313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        rv = DoTCPRestartComplete(rv);
3323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick        break;
333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      case STATE_DONE:
334c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
335c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      default:
336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NOTREACHED() << "bad state";
337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        rv = ERR_UNEXPECTED;
338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        break;
339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
3403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE &&
3413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick           next_state_ != STATE_DONE);
342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return rv;
343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::DoGenerateAuthToken() {
346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  next_state_ = STATE_GENERATE_AUTH_TOKEN_COMPLETE;
347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return auth_->MaybeGenerateAuthToken(&request_, &io_callback_, net_log_);
348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::DoGenerateAuthTokenComplete(int result) {
351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK_NE(ERR_IO_PENDING, result);
352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (result == OK)
353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    next_state_ = STATE_SEND_REQUEST;
354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return result;
355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::DoSendRequest() {
358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  next_state_ = STATE_SEND_REQUEST_COMPLETE;
359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This is constructed lazily (instead of within our Start method), so that
361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // we have proxy info available.
3624a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  if (request_line_.empty()) {
3634a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch    DCHECK(request_headers_.IsEmpty());
364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    HttpRequestHeaders authorization_headers;
365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    if (auth_->HaveAuth())
366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      auth_->AddAuthorizationHeader(&authorization_headers);
367731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    BuildTunnelRequest(request_, authorization_headers, endpoint_,
3684a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch                       &request_line_, &request_headers_);
369731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick    if (net_log_.IsLoggingAllEvents()) {
370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      net_log_.AddEvent(
371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch          NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
372513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch          make_scoped_refptr(new NetLogHttpRequestParameter(
3734a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch              request_line_, request_headers_)));
374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    }
375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  parser_buf_ = new GrowableIOBuffer();
3783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  http_stream_parser_.reset(
3793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      new HttpStreamParser(transport_.get(), &request_, parser_buf_, net_log_));
3804a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch  return http_stream_parser_->SendRequest(request_line_, request_headers_, NULL,
3813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                          &response_, &io_callback_);
382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::DoSendRequestComplete(int result) {
385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (result < 0)
386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return result;
387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  next_state_ = STATE_READ_HEADERS;
389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return OK;
390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::DoReadHeaders() {
393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  next_state_ = STATE_READ_HEADERS_COMPLETE;
3943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return http_stream_parser_->ReadResponseHeaders(&io_callback_);
395c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
397c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::DoReadHeadersComplete(int result) {
398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (result < 0)
399c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return result;
400c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
401c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Require the "HTTP/1.x" status line for SSL CONNECT.
402c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (response_.headers->GetParsedHttpVersion() < HttpVersion(1, 0))
403c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return ERR_TUNNEL_CONNECTION_FAILED;
404c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
405731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick  if (net_log_.IsLoggingAllEvents()) {
406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    net_log_.AddEvent(
407c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
408513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch        make_scoped_refptr(new NetLogHttpResponseParameter(response_.headers)));
409c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
410c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
411c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  switch (response_.headers->response_code()) {
412c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case 200:  // OK
4133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick      if (http_stream_parser_->IsMoreDataBuffered())
414c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        // The proxy sent extraneous data after the headers.
415c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch        return ERR_TUNNEL_CONNECTION_FAILED;
416c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
417c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      next_state_ = STATE_DONE;
418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return OK;
419c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // We aren't able to CONNECT to the remote host through the proxy.  We
421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // need to be very suspicious about the response because an active network
422c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // attacker can force us into this state by masquerading as the proxy.
423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // The only safe thing to do here is to fail the connection because our
424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // client is expecting an SSL protected response.
425c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // See http://crbug.com/7338.
426c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    case 407:  // Proxy Authentication Required
427c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // We need this status code to allow proxy authentication.  Our
428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // authentication code is smart enough to avoid being tricked by an
429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // active network attacker.
430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // The next state is intentionally not set as it should be STATE_NONE;
431c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return HandleAuthChallenge();
432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    default:
43421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen      if (is_https_proxy_)
43521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen        return ERR_HTTPS_PROXY_TUNNEL_RESPONSE;
436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // For all other status codes, we conservatively fail the CONNECT
437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // request.
438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // We lose something by doing this.  We have seen proxy 403, 404, and
439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // 501 response bodies that contain a useful error message.  For
440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // example, Squid uses a 404 response to report the DNS error: "The
441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      // domain name does not exist."
442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      LogBlockedTunnelResponse(response_.headers->response_code());
443c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      return ERR_TUNNEL_CONNECTION_FAILED;
444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  }
445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
446c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::DoDrainBody() {
448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(drain_buf_);
449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(transport_->is_initialized());
450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  next_state_ = STATE_DRAIN_BODY_COMPLETE;
4513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return http_stream_parser_->ReadResponseBody(drain_buf_, kDrainBodyBufferSize,
4523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick                                               &io_callback_);
453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::DoDrainBodyComplete(int result) {
456c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (result < 0)
457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return result;
458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (http_stream_parser_->IsResponseBodyComplete())
460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return DidDrainBodyForAuthRestart(true);
461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // Keep draining.
463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  next_state_ = STATE_DRAIN_BODY;
464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return OK;
465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4677b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#ifdef ANDROID
4687b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen// TODO(kristianm): Check if we can find out if Connect should block
4697b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#endif
4703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint HttpProxyClientSocket::DoTCPRestart() {
4713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  next_state_ = STATE_TCP_RESTART_COMPLETE;
4727b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen  return transport_->socket()->Connect(&io_callback_
4737b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#ifdef ANDROID
4747b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen                                       , false
4757b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen#endif
4767b9ca917061470268bf3395c8925d4b9cc52d8e1Kristian Monsen                                      );
4773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
4783345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickint HttpProxyClientSocket::DoTCPRestartComplete(int result) {
4803345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  if (result != OK)
4813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick    return result;
4823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
4833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  next_state_ = STATE_GENERATE_AUTH_TOKEN;
4843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick  return result;
4853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick}
4863345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint HttpProxyClientSocket::HandleAuthChallenge() {
488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  DCHECK(response_.headers);
489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  int rv = auth_->HandleAuthChallenge(response_.headers, false, true, net_log_);
491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  response_.auth_challenge = auth_->auth_info();
492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (rv == OK)
493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return ERR_PROXY_AUTH_REQUESTED;
494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  return rv;
496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}  // namespace net
499