15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_proxy_client_socket.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
97d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_util.h"
107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/stringprintf.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/auth.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/host_port_pair.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "net/base/proxy_delegate.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_basic_stream.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_network_session.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_request_info.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_stream_parser.h"
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "net/http/proxy_connect_redirect_http_stream.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/client_socket_handle.h"
247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpProxyClientSocket::HttpProxyClientSocket(
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ClientSocketHandle* transport_socket,
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& request_url,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& user_agent,
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HostPortPair& endpoint,
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HostPortPair& proxy_server,
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpAuthCache* http_auth_cache,
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpAuthHandlerFactory* http_auth_handler_factory,
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool tunnel,
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool using_spdy,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NextProto protocol_negotiated,
391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    ProxyDelegate* proxy_delegate,
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool is_https_proxy)
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : io_callback_(base::Bind(&HttpProxyClientSocket::OnIOComplete,
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                              base::Unretained(this))),
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_state_(STATE_NONE),
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      transport_(transport_socket),
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      endpoint_(endpoint),
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      auth_(tunnel ?
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          new HttpAuthController(HttpAuth::AUTH_PROXY,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 GURL((is_https_proxy ? "https://" : "http://")
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      + proxy_server.ToString()),
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 http_auth_cache,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 http_auth_handler_factory)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          : NULL),
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tunnel_(tunnel),
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      using_spdy_(using_spdy),
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      protocol_negotiated_(protocol_negotiated),
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_https_proxy_(is_https_proxy),
57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      redirect_has_load_timing_info_(false),
581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      proxy_server_(proxy_server),
591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      proxy_delegate_(proxy_delegate),
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net_log_(transport_socket->socket()->NetLog()) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Synthesize the bits of a request that we actually use.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_.url = request_url;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_.method = "GET";
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!user_agent.empty())
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_.extra_headers.SetHeader(HttpRequestHeaders::kUserAgent,
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     user_agent);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpProxyClientSocket::~HttpProxyClientSocket() {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Disconnect();
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::RestartWithAuth(const CompletionCallback& callback) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_state_);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_callback_.is_null());
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = PrepareForAuthRestart();
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != OK)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return rv;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  rv = DoLoop(OK);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING) {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!callback.is_null())
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      user_callback_ =  callback;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const scoped_refptr<HttpAuthController>&
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpProxyClientSocket::GetAuthController() const {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return auth_;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpProxyClientSocket::IsUsingSpdy() const {
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return using_spdy_;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NextProto HttpProxyClientSocket::GetProtocolNegotiated() const {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return protocol_negotiated_;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const HttpResponseInfo* HttpProxyClientSocket::GetConnectResponseInfo() const {
104868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return response_.headers.get() ? &response_ : NULL;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpStream* HttpProxyClientSocket::CreateConnectResponseStream() {
108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return new ProxyConnectRedirectHttpStream(
109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      redirect_has_load_timing_info_ ? &redirect_load_timing_info_ : NULL);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::Connect(const CompletionCallback& callback) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(transport_.get());
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(transport_->socket());
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_callback_.is_null());
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(rch): figure out the right way to set up a tunnel with SPDY.
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This approach sends the complete HTTPS request to the proxy
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // which allows the proxy to see "private" data.  Instead, we should
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // create an SSL tunnel to the origin server using the CONNECT method
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // inside a single SPDY stream.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (using_spdy_ || !tunnel_)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_DONE;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (next_state_ == STATE_DONE)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_NONE, next_state_);
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_GENERATE_AUTH_TOKEN;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoLoop(OK);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == ERR_IO_PENDING)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user_callback_ = callback;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpProxyClientSocket::Disconnect() {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_.get())
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transport_->socket()->Disconnect();
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reset other states to make sure they aren't mistakenly used later.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These are the states initialized by Connect().
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_NONE;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_callback_.Reset();
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpProxyClientSocket::IsConnected() const {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return next_state_ == STATE_DONE && transport_->socket()->IsConnected();
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpProxyClientSocket::IsConnectedAndIdle() const {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return next_state_ == STATE_DONE &&
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transport_->socket()->IsConnectedAndIdle();
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BoundNetLog& HttpProxyClientSocket::NetLog() const {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return net_log_;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpProxyClientSocket::SetSubresourceSpeculation() {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_.get() && transport_->socket()) {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transport_->socket()->SetSubresourceSpeculation();
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpProxyClientSocket::SetOmniboxSpeculation() {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_.get() && transport_->socket()) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transport_->socket()->SetOmniboxSpeculation();
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpProxyClientSocket::WasEverUsed() const {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_.get() && transport_->socket()) {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return transport_->socket()->WasEverUsed();
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpProxyClientSocket::UsingTCPFastOpen() const {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_.get() && transport_->socket()) {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return transport_->socket()->UsingTCPFastOpen();
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpProxyClientSocket::WasNpnNegotiated() const {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_.get() && transport_->socket()) {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return transport_->socket()->WasNpnNegotiated();
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NextProto HttpProxyClientSocket::GetNegotiatedProtocol() const {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_.get() && transport_->socket()) {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return transport_->socket()->GetNegotiatedProtocol();
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return kProtoUnknown;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpProxyClientSocket::GetSSLInfo(SSLInfo* ssl_info) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (transport_.get() && transport_->socket()) {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return transport_->socket()->GetSSLInfo(ssl_info);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::Read(IOBuffer* buf, int buf_len,
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const CompletionCallback& callback) {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_callback_.is_null());
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (next_state_ != STATE_DONE) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We're trying to read the body of the response but we're still trying
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to establish an SSL tunnel through the proxy.  We can't read these
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // bytes when establishing a tunnel because they might be controlled by
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // an active network attacker.  We don't worry about this for HTTP
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // because an active network attacker can already control HTTP sessions.
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We reach this case when the user cancels a 407 proxy auth prompt.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // See http://crbug.com/8473.
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(407, response_.headers->response_code());
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogBlockedTunnelResponse();
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_TUNNEL_CONNECTION_FAILED;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_->socket()->Read(buf, buf_len, callback);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::Write(IOBuffer* buf, int buf_len,
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const CompletionCallback& callback) {
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_DONE, next_state_);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(user_callback_.is_null());
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_->socket()->Write(buf, buf_len, callback);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
244c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochint HttpProxyClientSocket::SetReceiveBufferSize(int32 size) {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_->socket()->SetReceiveBufferSize(size);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
248c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochint HttpProxyClientSocket::SetSendBufferSize(int32 size) {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_->socket()->SetSendBufferSize(size);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::GetPeerAddress(IPEndPoint* address) const {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_->socket()->GetPeerAddress(address);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::GetLocalAddress(IPEndPoint* address) const {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_->socket()->GetLocalAddress(address);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::PrepareForAuthRestart() {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!response_.headers.get())
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_CONNECTION_RESET;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool keep_alive = false;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (response_.headers->IsKeepAlive() &&
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      http_stream_parser_->CanFindEndOfResponse()) {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!http_stream_parser_->IsResponseBodyComplete()) {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_state_ = STATE_DRAIN_BODY;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      drain_buf_ = new IOBuffer(kDrainBodyBufferSize);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return OK;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    keep_alive = true;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't need to drain the response body, so we act as if we had drained
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the response body.
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return DidDrainBodyForAuthRestart(keep_alive);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::DidDrainBodyForAuthRestart(bool keep_alive) {
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (keep_alive && transport_->socket()->IsConnectedAndIdle()) {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_GENERATE_AUTH_TOKEN;
28323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    transport_->set_reuse_type(ClientSocketHandle::REUSED_IDLE);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This assumes that the underlying transport socket is a TCP socket,
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // since only TCP sockets are restartable.
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_TCP_RESTART;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    transport_->socket()->Disconnect();
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reset the other member variables.
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  drain_buf_ = NULL;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parser_buf_ = NULL;
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  http_stream_parser_.reset();
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_line_.clear();
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_headers_.Clear();
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response_ = HttpResponseInfo();
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpProxyClientSocket::LogBlockedTunnelResponse() const {
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProxyClientSocket::LogBlockedTunnelResponse(
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response_.headers->response_code(),
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request_.url,
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_https_proxy_);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpProxyClientSocket::DoCallback(int result) {
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(ERR_IO_PENDING, result);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!user_callback_.is_null());
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since Run() may result in Read being called,
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // clear user_callback_ up front.
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompletionCallback c = user_callback_;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  user_callback_.Reset();
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  c.Run(result);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpProxyClientSocket::OnIOComplete(int result) {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(STATE_NONE, next_state_);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(STATE_DONE, next_state_);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = DoLoop(result);
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != ERR_IO_PENDING)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DoCallback(rv);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::DoLoop(int last_io_result) {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(next_state_, STATE_NONE);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(next_state_, STATE_DONE);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = last_io_result;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    State state = next_state_;
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_NONE;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (state) {
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_GENERATE_AUTH_TOKEN:
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoGenerateAuthToken();
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_GENERATE_AUTH_TOKEN_COMPLETE:
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoGenerateAuthTokenComplete(rv);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_SEND_REQUEST:
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net_log_.BeginEvent(
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoSendRequest();
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_SEND_REQUEST_COMPLETE:
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoSendRequestComplete(rv);
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net_log_.EndEventWithNetErrorCode(
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_SEND_REQUEST, rv);
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_READ_HEADERS:
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net_log_.BeginEvent(
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoReadHeaders();
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_READ_HEADERS_COMPLETE:
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoReadHeadersComplete(rv);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        net_log_.EndEventWithNetErrorCode(
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            NetLog::TYPE_HTTP_TRANSACTION_TUNNEL_READ_HEADERS, rv);
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_DRAIN_BODY:
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoDrainBody();
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_DRAIN_BODY_COMPLETE:
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoDrainBodyComplete(rv);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_TCP_RESTART:
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK_EQ(OK, rv);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoTCPRestart();
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_TCP_RESTART_COMPLETE:
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = DoTCPRestartComplete(rv);
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case STATE_DONE:
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED() << "bad state";
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rv = ERR_UNEXPECTED;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE &&
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           next_state_ != STATE_DONE);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::DoGenerateAuthToken() {
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_GENERATE_AUTH_TOKEN_COMPLETE;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return auth_->MaybeGenerateAuthToken(&request_, io_callback_, net_log_);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::DoGenerateAuthTokenComplete(int result) {
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(ERR_IO_PENDING, result);
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result == OK)
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_state_ = STATE_SEND_REQUEST;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::DoSendRequest() {
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_SEND_REQUEST_COMPLETE;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is constructed lazily (instead of within our Start method), so that
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we have proxy info available.
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request_line_.empty()) {
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(request_headers_.IsEmpty());
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpRequestHeaders authorization_headers;
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (auth_->HaveAuth())
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      auth_->AddAuthorizationHeader(&authorization_headers);
4121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (proxy_delegate_) {
4131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      proxy_delegate_->OnBeforeTunnelRequest(proxy_server_,
4141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                             &authorization_headers);
4151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BuildTunnelRequest(request_, authorization_headers, endpoint_,
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       &request_line_, &request_headers_);
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net_log_.AddEvent(
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NetLog::TYPE_HTTP_TRANSACTION_SEND_TUNNEL_HEADERS,
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&HttpRequestHeaders::NetLogCallback,
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   base::Unretained(&request_headers_),
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   &request_line_));
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parser_buf_ = new GrowableIOBuffer();
427868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  http_stream_parser_.reset(new HttpStreamParser(
428868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      transport_.get(), &request_, parser_buf_.get(), net_log_));
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return http_stream_parser_->SendRequest(
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      request_line_, request_headers_, &response_, io_callback_);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::DoSendRequestComplete(int result) {
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result < 0)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_READ_HEADERS;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::DoReadHeaders() {
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_READ_HEADERS_COMPLETE;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return http_stream_parser_->ReadResponseHeaders(io_callback_);
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::DoReadHeadersComplete(int result) {
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result < 0)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Require the "HTTP/1.x" status line for SSL CONNECT.
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (response_.headers->GetParsedHttpVersion() < HttpVersion(1, 0))
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_TUNNEL_CONNECTION_FAILED;
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net_log_.AddEvent(
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NetLog::TYPE_HTTP_TRANSACTION_READ_TUNNEL_RESPONSE_HEADERS,
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&HttpResponseHeaders::NetLogCallback, response_.headers));
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (proxy_delegate_) {
4591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    proxy_delegate_->OnTunnelHeadersReceived(
4601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        HostPortPair::FromURL(request_.url),
4611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        proxy_server_,
4621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        *response_.headers);
4631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
4641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (response_.headers->response_code()) {
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 200:  // OK
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (http_stream_parser_->IsMoreDataBuffered())
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // The proxy sent extraneous data after the headers.
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return ERR_TUNNEL_CONNECTION_FAILED;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_state_ = STATE_DONE;
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return OK;
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We aren't able to CONNECT to the remote host through the proxy.  We
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // need to be very suspicious about the response because an active network
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // attacker can force us into this state by masquerading as the proxy.
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The only safe thing to do here is to fail the connection because our
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // client is expecting an SSL protected response.
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // See http://crbug.com/7338.
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 302:  // Found / Moved Temporarily
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Attempt to follow redirects from HTTPS proxies, but only if we can
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // sanitize the response.  This still allows a rogue HTTPS proxy to
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // redirect an HTTPS site load to a similar-looking site, but no longer
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // allows it to impersonate the site the user requested.
486eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (is_https_proxy_ && SanitizeProxyRedirect(&response_, request_.url)) {
487eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        bool is_connection_reused = http_stream_parser_->IsConnectionReused();
488eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        redirect_has_load_timing_info_ =
489eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch            transport_->GetLoadTimingInfo(
490eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                is_connection_reused, &redirect_load_timing_info_);
491eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        transport_.reset();
492eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        http_stream_parser_.reset();
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return ERR_HTTPS_PROXY_TUNNEL_RESPONSE;
494eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      }
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We're not using an HTTPS proxy, or we couldn't sanitize the redirect.
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LogBlockedTunnelResponse();
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_TUNNEL_CONNECTION_FAILED;
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 407:  // Proxy Authentication Required
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We need this status code to allow proxy authentication.  Our
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // authentication code is smart enough to avoid being tricked by an
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // active network attacker.
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The next state is intentionally not set as it should be STATE_NONE;
505868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return HandleProxyAuthChallenge(auth_.get(), &response_, net_log_);
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Ignore response to avoid letting the proxy impersonate the target
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // server.  (See http://crbug.com/137891.)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We lose something by doing this.  We have seen proxy 403, 404, and
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // 501 response bodies that contain a useful error message.  For
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // example, Squid uses a 404 response to report the DNS error: "The
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // domain name does not exist."
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LogBlockedTunnelResponse();
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_TUNNEL_CONNECTION_FAILED;
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::DoDrainBody() {
520868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(drain_buf_.get());
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(transport_->is_initialized());
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_DRAIN_BODY_COMPLETE;
523868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return http_stream_parser_->ReadResponseBody(
524868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      drain_buf_.get(), kDrainBodyBufferSize, io_callback_);
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::DoDrainBodyComplete(int result) {
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result < 0)
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (http_stream_parser_->IsResponseBodyComplete())
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return DidDrainBodyForAuthRestart(true);
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Keep draining.
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_DRAIN_BODY;
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return OK;
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::DoTCPRestart() {
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_TCP_RESTART_COMPLETE;
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return transport_->socket()->Connect(
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&HttpProxyClientSocket::OnIOComplete, base::Unretained(this)));
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HttpProxyClientSocket::DoTCPRestartComplete(int result) {
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != OK)
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_state_ = STATE_GENERATE_AUTH_TOKEN;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
554