// 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_HTTP_STREAM_FACTORY_IMPL_REQUEST_H_
#define NET_HTTP_HTTP_STREAM_FACTORY_IMPL_REQUEST_H_

#include <memory>
#include <set>

#include "base/macros.h"
#include "net/base/net_export.h"
#include "net/http/http_stream_factory_impl.h"
#include "net/log/net_log.h"
#include "net/socket/connection_attempts.h"
#include "net/socket/ssl_client_socket.h"
#include "net/spdy/spdy_session_key.h"
#include "url/gurl.h"

namespace net {

class BidirectionalStreamImpl;
class ClientSocketHandle;
class HttpStream;
class SpdySession;

class HttpStreamFactoryImpl::Request : public HttpStreamRequest {
 public:
  class NET_EXPORT_PRIVATE Helper {
   public:
    virtual ~Helper() {}

    // Returns the LoadState for Request.
    virtual LoadState GetLoadState() const = 0;

    // Called when Request is destructed.
    virtual void OnRequestComplete() = 0;

    // Called to resume the HttpStream creation process when necessary
    // Proxy authentication credentials are collected.
    virtual int RestartTunnelWithProxyAuth(
        const AuthCredentials& credentials) = 0;

    // Called when the priority of transaction changes.
    virtual void SetPriority(RequestPriority priority) = 0;
  };

  // Request will notify |job_controller| when it's destructed.
  // Thus |job_controller| is valid for the lifetime of the |this| Request.
  Request(const GURL& url,
          Helper* helper,
          HttpStreamRequest::Delegate* delegate,
          WebSocketHandshakeStreamBase::CreateHelper*
              websocket_handshake_stream_create_helper,
          const BoundNetLog& net_log,
          StreamType stream_type);

  ~Request() override;

  // The GURL from the HttpRequestInfo the started the Request.
  const GURL& url() const { return url_; }

  const BoundNetLog& net_log() const { return net_log_; }

  // Called when the |helper_| determines the appropriate |spdy_session_key|
  // for the Request. Note that this does not mean that SPDY is necessarily
  // supported for this SpdySessionKey, since we may need to wait for NPN to
  // complete before knowing if SPDY is available.
  void SetSpdySessionKey(const SpdySessionKey& spdy_session_key);
  bool HasSpdySessionKey() const;

  // Marks completion of the request. Must be called before OnStreamReady().
  void Complete(bool was_npn_negotiated,
                NextProto protocol_negotiated,
                bool using_spdy);

  void ResetSpdySessionKey();

  // Called by |helper_| to record connection attempts made by the socket
  // layer in an attached Job for this stream request.
  void AddConnectionAttempts(const ConnectionAttempts& attempts);

  WebSocketHandshakeStreamBase::CreateHelper*
  websocket_handshake_stream_create_helper() {
    return websocket_handshake_stream_create_helper_;
  }

  // HttpStreamRequest::Delegate methods which we implement. Note we don't
  // actually subclass HttpStreamRequest::Delegate.

  void OnStreamReady(const SSLConfig& used_ssl_config,
                     const ProxyInfo& used_proxy_info,
                     HttpStream* stream);
  void OnBidirectionalStreamImplReady(const SSLConfig& used_ssl_config,
                                      const ProxyInfo& used_proxy_info,
                                      BidirectionalStreamImpl* stream);

  void OnWebSocketHandshakeStreamReady(const SSLConfig& used_ssl_config,
                                       const ProxyInfo& used_proxy_info,
                                       WebSocketHandshakeStreamBase* stream);
  void OnStreamFailed(int status, const SSLConfig& used_ssl_config);
  void OnCertificateError(int status,
                          const SSLConfig& used_ssl_config,
                          const SSLInfo& ssl_info);
  void OnNeedsProxyAuth(const HttpResponseInfo& proxy_response,
                        const SSLConfig& used_ssl_config,
                        const ProxyInfo& used_proxy_info,
                        HttpAuthController* auth_controller);
  void OnNeedsClientAuth(const SSLConfig& used_ssl_config,
                         SSLCertRequestInfo* cert_info);
  void OnHttpsProxyTunnelResponse(
      const HttpResponseInfo& response_info,
      const SSLConfig& used_ssl_config,
      const ProxyInfo& used_proxy_info,
      HttpStream* stream);

  // HttpStreamRequest methods.

  int RestartTunnelWithProxyAuth(const AuthCredentials& credentials) override;
  void SetPriority(RequestPriority priority) override;
  LoadState GetLoadState() const override;
  bool was_npn_negotiated() const override;
  NextProto protocol_negotiated() const override;
  bool using_spdy() const override;
  const ConnectionAttempts& connection_attempts() const override;
  HttpStreamRequest::StreamType stream_type() const { return stream_type_; }
  const SpdySessionKey* spdy_session_key() const {
    return spdy_session_key_.get();
  }

 private:
  const GURL url_;

  // Unowned. The helper must outlive this request.
  Helper* helper_;

  WebSocketHandshakeStreamBase::CreateHelper* const
      websocket_handshake_stream_create_helper_;
  HttpStreamRequest::Delegate* const delegate_;
  const BoundNetLog net_log_;

  std::unique_ptr<const SpdySessionKey> spdy_session_key_;

  bool completed_;
  bool was_npn_negotiated_;
  // Protocol negotiated with the server.
  NextProto protocol_negotiated_;
  bool using_spdy_;
  ConnectionAttempts connection_attempts_;

  const HttpStreamRequest::StreamType stream_type_;
  DISALLOW_COPY_AND_ASSIGN(Request);
};

}  // namespace net

#endif  // NET_HTTP_HTTP_STREAM_FACTORY_IMPL_REQUEST_H_
