// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_HTTP_PROXY_CLIENT_SOCKET_H_
#define NET_HTTP_PROXY_CLIENT_SOCKET_H_

#include <string>

#include "net/socket/ssl_client_socket.h"
#include "net/socket/stream_socket.h"

class GURL;

namespace net {

class HostPortPair;
class HttpAuthController;
class HttpStream;
class HttpResponseInfo;
class HttpRequestHeaders;
struct HttpRequestInfo;
class HttpAuthController;

class NET_EXPORT_PRIVATE ProxyClientSocket : public StreamSocket {
 public:
  ProxyClientSocket() {}
  virtual ~ProxyClientSocket() {}

  // Returns the HttpResponseInfo (including HTTP Headers) from
  // the response to the CONNECT request.
  virtual const HttpResponseInfo* GetConnectResponseInfo() const = 0;

  // Transfers ownership of a newly created HttpStream to the caller
  // which can be used to read the response body.
  virtual HttpStream* CreateConnectResponseStream() = 0;

  // Returns the HttpAuthController which can be used
  // to interact with an HTTP Proxy Authorization Required (407) request.
  virtual const scoped_refptr<HttpAuthController>& GetAuthController() const
      = 0;

  // If Connect (or its callback) returns PROXY_AUTH_REQUESTED, then
  // credentials should be added to the HttpAuthController before calling
  // RestartWithAuth.  Not all ProxyClientSocket implementations will be
  // restartable.  Such implementations should disconnect themselves and
  // return OK.
  virtual int RestartWithAuth(const CompletionCallback& callback) = 0;

  // Returns true of the connection to the proxy is using SPDY.
  virtual bool IsUsingSpdy() const = 0;

  // Returns the protocol negotiated with the proxy.
  virtual NextProto GetProtocolNegotiated() const = 0;

 protected:
  // The HTTP CONNECT method for establishing a tunnel connection is documented
  // in draft-luotonen-web-proxy-tunneling-01.txt and RFC 2817, Sections 5.2
  // and 5.3.
  static void BuildTunnelRequest(const HttpRequestInfo& request_info,
                                 const HttpRequestHeaders& auth_headers,
                                 const HostPortPair& endpoint,
                                 std::string* request_line,
                                 HttpRequestHeaders* request_headers);

  // When an auth challenge (407 response) is received during tunnel
  // construction/ this method should be called.
  static int HandleProxyAuthChallenge(HttpAuthController* auth,
                                      HttpResponseInfo* response,
                                      const BoundNetLog& net_log);

  // Logs (to the log and in a histogram) a blocked CONNECT response.
  static void LogBlockedTunnelResponse(int http_response_code,
                                       const GURL& url,
                                       bool is_https_proxy);

  // When a redirect (e.g. 302 response) is received during tunnel
  // construction, this method should be called to strip everything
  // but the Location header from the redirect response.  If it returns
  // false, the response should be discarded and tunnel construction should
  // fail.  |url| is for logging purposes.
  static bool SanitizeProxyRedirect(HttpResponseInfo* response,
                                    const GURL& url);

 private:
  DISALLOW_COPY_AND_ASSIGN(ProxyClientSocket);
};

}  // namespace net

#endif  // NET_HTTP_PROXY_CLIENT_SOCKET_H_
