// 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 <set>
#include "base/memory/scoped_ptr.h"
#include "net/base/net_log.h"
#include "net/http/http_stream_factory_impl.h"
#include "net/socket/ssl_client_socket.h"
#include "net/spdy/spdy_session_key.h"
#include "url/gurl.h"

namespace net {

class ClientSocketHandle;
class HttpStream;
class SpdySession;

class HttpStreamFactoryImpl::Request : public HttpStreamRequest {
 public:
  Request(const GURL& url,
          HttpStreamFactoryImpl* factory,
          HttpStreamRequest::Delegate* delegate,
          WebSocketHandshakeStreamBase::CreateHelper*
              websocket_handshake_stream_create_helper,
          const BoundNetLog& net_log);
  ~Request() override;

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

  // Called when the Job 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;

  // Attaches |job| to this request. Does not mean that Request will use |job|,
  // but Request will own |job|.
  void AttachJob(HttpStreamFactoryImpl::Job* job);

  // Marks completion of the request. Must be called before OnStreamReady().
  // |job_net_log| is the BoundNetLog of the Job that fulfilled this request.
  void Complete(bool was_npn_negotiated,
                NextProto protocol_negotiated,
                bool using_spdy,
                const BoundNetLog& job_net_log);

  // If this Request has a |spdy_session_key_|, remove this session from the
  // SpdySessionRequestMap.
  void RemoveRequestFromSpdySessionRequestMap();

  // Called by an attached Job if it sets up a SpdySession.
  void OnNewSpdySessionReady(Job* job,
                             scoped_ptr<HttpStream> stream,
                             const base::WeakPtr<SpdySession>& spdy_session,
                             bool direct);

  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(Job* job,
                     const SSLConfig& used_ssl_config,
                     const ProxyInfo& used_proxy_info,
                     HttpStreamBase* stream);
  void OnWebSocketHandshakeStreamReady(Job* job,
                                       const SSLConfig& used_ssl_config,
                                       const ProxyInfo& used_proxy_info,
                                       WebSocketHandshakeStreamBase* stream);
  void OnStreamFailed(Job* job, int status, const SSLConfig& used_ssl_config);
  void OnCertificateError(Job* job,
                          int status,
                          const SSLConfig& used_ssl_config,
                          const SSLInfo& ssl_info);
  void OnNeedsProxyAuth(Job* job,
                        const HttpResponseInfo& proxy_response,
                        const SSLConfig& used_ssl_config,
                        const ProxyInfo& used_proxy_info,
                        HttpAuthController* auth_controller);
  void OnNeedsClientAuth(Job* job,
                         const SSLConfig& used_ssl_config,
                         SSLCertRequestInfo* cert_info);
  void OnHttpsProxyTunnelResponse(
      Job *job,
      const HttpResponseInfo& response_info,
      const SSLConfig& used_ssl_config,
      const ProxyInfo& used_proxy_info,
      HttpStreamBase* 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;

 private:
  // Used to orphan all jobs in |jobs_| other than |job| which becomes "bound"
  // to the request.
  void OrphanJobsExcept(Job* job);

  // Used to orphan all jobs in |jobs_|.
  void OrphanJobs();

  // Called when a Job succeeds.
  void OnJobSucceeded(Job* job);

  const GURL url_;
  HttpStreamFactoryImpl* const factory_;
  WebSocketHandshakeStreamBase::CreateHelper* const
      websocket_handshake_stream_create_helper_;
  HttpStreamRequest::Delegate* const delegate_;
  const BoundNetLog net_log_;

  // At the point where Job is irrevocably tied to the Request, we set this.
  scoped_ptr<Job> bound_job_;
  std::set<HttpStreamFactoryImpl::Job*> jobs_;
  scoped_ptr<const SpdySessionKey> spdy_session_key_;

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

  DISALLOW_COPY_AND_ASSIGN(Request);
};

}  // namespace net

#endif  // NET_HTTP_HTTP_STREAM_FACTORY_IMPL_REQUEST_H_
