1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef NET_QUIC_QUIC_IN_MEMORY_CACHE_H_
6#define NET_QUIC_QUIC_IN_MEMORY_CACHE_H_
7
8#include <string>
9
10#include "base/containers/hash_tables.h"
11#include "base/files/file_util.h"
12#include "base/memory/singleton.h"
13#include "base/strings/string_piece.h"
14#include "net/http/http_response_headers.h"
15
16template <typename T> struct DefaultSingletonTraits;
17class GURL;
18
19namespace net {
20
21extern base::FilePath::StringType g_quic_in_memory_cache_dir;
22
23namespace test {
24class QuicInMemoryCachePeer;
25}  // namespace
26
27class QuicServer;
28
29// In-memory cache for HTTP responses.
30// Reads from disk cache generated by:
31// `wget -p --save_headers <url>`
32class QuicInMemoryCache {
33 public:
34  enum SpecialResponseType {
35    REGULAR_RESPONSE,  // Send the headers and body like a server should.
36    CLOSE_CONNECTION,  // Close the connection (sending the close packet).
37    IGNORE_REQUEST,    // Do nothing, expect the client to time out.
38  };
39
40  // Container for response header/body pairs.
41  class Response {
42   public:
43    Response();
44    ~Response();
45
46    SpecialResponseType response_type() const { return response_type_; }
47    const HttpResponseHeaders& headers() const { return *headers_.get(); }
48    const base::StringPiece body() const { return base::StringPiece(body_); }
49
50   private:
51    friend class QuicInMemoryCache;
52
53    void set_headers(scoped_refptr<HttpResponseHeaders> headers) {
54      headers_ = headers;
55    }
56    void set_body(base::StringPiece body) {
57      body.CopyToString(&body_);
58    }
59
60    SpecialResponseType response_type_;
61    scoped_refptr<HttpResponseHeaders> headers_;
62    std::string body_;
63
64    DISALLOW_COPY_AND_ASSIGN(Response);
65  };
66
67  // Returns the singleton instance of the cache.
68  static QuicInMemoryCache* GetInstance();
69
70  // Retrieve a response from this cache for a given request.
71  // If no appropriate response exists, NULL is returned.
72  // Currently, responses are selected based on request URI only.
73  const Response* GetResponse(const GURL& url) const;
74
75  // Adds a simple response to the cache.  The response headers will
76  // only contain the "content-length" header with the length of |body|.
77  void AddSimpleResponse(base::StringPiece path,
78                         base::StringPiece version,
79                         base::StringPiece response_code,
80                         base::StringPiece response_detail,
81                         base::StringPiece body);
82
83  // Add a response to the cache.
84  void AddResponse(const GURL& url,
85                   scoped_refptr<HttpResponseHeaders> response_headers,
86                   base::StringPiece response_body);
87
88  // Simulate a special behavior at a particular path.
89  void AddSpecialResponse(base::StringPiece path,
90                          SpecialResponseType response_type);
91
92 private:
93  typedef base::hash_map<std::string, Response*> ResponseMap;
94  friend struct DefaultSingletonTraits<QuicInMemoryCache>;
95  friend class test::QuicInMemoryCachePeer;
96
97  QuicInMemoryCache();
98  ~QuicInMemoryCache();
99
100  void ResetForTests();
101
102  void Initialize();
103
104  std::string GetKey(const GURL& url) const;
105
106  // Cached responses.
107  ResponseMap responses_;
108
109  DISALLOW_COPY_AND_ASSIGN(QuicInMemoryCache);
110};
111
112}  // namespace net
113
114#endif  // NET_QUIC_QUIC_IN_MEMORY_CACHE_H_
115