text: // Copyright (c) 2016 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_QUIC_QUIC_CLIENT_PROMISED_INFO_H_
  #define NET_QUIC_QUIC_CLIENT_PROMISED_INFO_H_
  
  #include <sys/types.h>
  #include <string>
  
  #include "net/base/net_export.h"
  #include "net/quic/core/quic_alarm.h"
  #include "net/quic/core/quic_client_push_promise_index.h"
  #include "net/quic/core/quic_client_session_base.h"
  #include "net/quic/core/quic_protocol.h"
  #include "net/quic/core/quic_spdy_stream.h"
  #include "net/spdy/spdy_framer.h"
  
  namespace net {
  
  class QuicClientSessionBase;
  class QuicDataToResend;
  class QuicConnectionHelperInterface;
  
  namespace test {
  class QuicClientPromisedInfoPeer;
  }  // namespace test
  
  // QuicClientPromisedInfo tracks the client state of a server push
  // stream from the time a PUSH_PROMISE is received until rendezvous
  // between the promised response and the corresponding client request
  // is complete.
  class NET_EXPORT_PRIVATE QuicClientPromisedInfo
      : public QuicClientPushPromiseIndex::TryHandle {
   public:
    // Interface to QuicSpdyClientStream
    QuicClientPromisedInfo(QuicClientSessionBase* session,
                           QuicStreamId id,
                           std::string url);
    virtual ~QuicClientPromisedInfo();
  
    void Init();
  
    // Validate promise headers etc.
    void OnPromiseHeaders(const SpdyHeaderBlock& request_headers);
  
    // Store response, possibly proceed with final validation.
    void OnResponseHeaders(const SpdyHeaderBlock& response_headers);
  
    // Rendezvous between this promised stream and a client request that
    // has a matching URL.
    virtual QuicAsyncStatus HandleClientRequest(
        const SpdyHeaderBlock& headers,
        QuicClientPushPromiseIndex::Delegate* delegate);
  
    void Cancel() override;
  
    void Reset(QuicRstStreamErrorCode error_code);
  
    // Client requests are initially associated to promises by matching
    // URL in the client request against the URL in the promise headers,
    // uing the |promised_by_url| map.  The push can be cross-origin, so
    // the client should validate that the session is authoritative for
    // the promised URL.  If not, it should call |RejectUnauthorized|.
    QuicClientSessionBase* session() { return session_; }
  
    // If the promised response contains Vary header, then the fields
    // specified by Vary must match between the client request header
    // and the promise headers (see https://crbug.com//554220).  Vary
    // validation requires the response headers (for the actual Vary
    // field list), the promise headers (taking the role of the "cached"
    // request), and the client request headers.
    SpdyHeaderBlock* request_headers() { return request_headers_.get(); }
  
    SpdyHeaderBlock* response_headers() { return response_headers_.get(); }
  
    QuicStreamId id() const { return id_; }
  
    const std::string url() const { return url_; }
  
   private:
    friend class test::QuicClientPromisedInfoPeer;
  
    class CleanupAlarm : public QuicAlarm::Delegate {
     public:
      explicit CleanupAlarm(QuicClientPromisedInfo* promised)
          : promised_(promised) {}
  
      void OnAlarm() override;
  
      QuicClientPromisedInfo* promised_;
    };
  
    QuicAsyncStatus FinalValidation();
  
    QuicClientSessionBase* session_;
    QuicStreamId id_;
    std::string url_;
    std::unique_ptr<SpdyHeaderBlock> request_headers_;
    std::unique_ptr<SpdyHeaderBlock> response_headers_;
    std::unique_ptr<SpdyHeaderBlock> client_request_headers_;
    QuicClientPushPromiseIndex::Delegate* client_request_delegate_;
  
    // The promise will commit suicide eventually if it is not claimed
    // by a GET first.
    std::unique_ptr<QuicAlarm> cleanup_alarm_;
  
    DISALLOW_COPY_AND_ASSIGN(QuicClientPromisedInfo);
  };
  
  }  // namespace net
  
  #endif  // NET_QUIC_QUIC_CLIENT_PROMISED_INFO_H_
  