• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 // This file declares a HttpTransactionFactory implementation that can be
6 // layered on top of another HttpTransactionFactory to add HTTP caching.  The
7 // caching logic follows RFC 2616 (any exceptions are called out in the code).
8 //
9 // The HttpCache takes a disk_cache::Backend as a parameter, and uses that for
10 // the cache storage.
11 //
12 // See HttpTransactionFactory and HttpTransaction for more details.
13 
14 #ifndef NET_HTTP_HTTP_CACHE_H_
15 #define NET_HTTP_HTTP_CACHE_H_
16 #pragma once
17 
18 #include <list>
19 #include <set>
20 #include <string>
21 
22 #include "base/basictypes.h"
23 #include "base/file_path.h"
24 #include "base/hash_tables.h"
25 #include "base/memory/scoped_ptr.h"
26 #include "base/memory/weak_ptr.h"
27 #include "base/message_loop_proxy.h"
28 #include "base/task.h"
29 #include "base/threading/non_thread_safe.h"
30 #include "net/base/cache_type.h"
31 #include "net/base/completion_callback.h"
32 #include "net/base/load_states.h"
33 #include "net/http/http_transaction_factory.h"
34 
35 class GURL;
36 
37 namespace disk_cache {
38 class Backend;
39 class Entry;
40 }
41 
42 namespace net {
43 
44 class CertVerifier;
45 class DnsCertProvenanceChecker;
46 class DnsRRResolver;
47 class HostResolver;
48 class HttpAuthHandlerFactory;
49 class HttpNetworkSession;
50 struct HttpRequestInfo;
51 class HttpResponseInfo;
52 class IOBuffer;
53 class NetLog;
54 class NetworkDelegate;
55 class ProxyService;
56 class SSLConfigService;
57 class ViewCacheHelper;
58 
59 class HttpCache : public HttpTransactionFactory,
60                   public base::SupportsWeakPtr<HttpCache>,
61                   public base::NonThreadSafe {
62  public:
63   // The cache mode of operation.
64   enum Mode {
65     // Normal mode just behaves like a standard web cache.
66     NORMAL = 0,
67     // Record mode caches everything for purposes of offline playback.
68     RECORD,
69     // Playback mode replays from a cache without considering any
70     // standard invalidations.
71     PLAYBACK,
72     // Disables reads and writes from the cache.
73     // Equivalent to setting LOAD_DISABLE_CACHE on every request.
74     DISABLE
75   };
76 
77   // A BackendFactory creates a backend object to be used by the HttpCache.
78   class BackendFactory {
79    public:
~BackendFactory()80     virtual ~BackendFactory() {}
81 
82     // The actual method to build the backend. Returns a net error code. If
83     // ERR_IO_PENDING is returned, the |callback| will be notified when the
84     // operation completes, and |backend| must remain valid until the
85     // notification arrives.
86     // The implementation must not access the factory object after invoking the
87     // |callback| because the object can be deleted from within the callback.
88     virtual int CreateBackend(NetLog* net_log,
89                               disk_cache::Backend** backend,
90                               CompletionCallback* callback) = 0;
91   };
92 
93   // A default backend factory for the common use cases.
94   class DefaultBackend : public BackendFactory {
95    public:
96     // |path| is the destination for any files used by the backend, and
97     // |cache_thread| is the thread where disk operations should take place. If
98     // |max_bytes| is  zero, a default value will be calculated automatically.
99     DefaultBackend(CacheType type, const FilePath& path, int max_bytes,
100                    base::MessageLoopProxy* thread);
101     virtual ~DefaultBackend();
102 
103     // Returns a factory for an in-memory cache.
104     static BackendFactory* InMemory(int max_bytes);
105 
106     // BackendFactory implementation.
107     virtual int CreateBackend(NetLog* net_log,
108                               disk_cache::Backend** backend,
109                               CompletionCallback* callback);
110 
111    private:
112     CacheType type_;
113     const FilePath path_;
114     int max_bytes_;
115     scoped_refptr<base::MessageLoopProxy> thread_;
116   };
117 
118   // The disk cache is initialized lazily (by CreateTransaction) in this case.
119   // The HttpCache takes ownership of the |backend_factory|.
120   HttpCache(HostResolver* host_resolver,
121             CertVerifier* cert_verifier,
122             DnsRRResolver* dnsrr_resolver,
123             DnsCertProvenanceChecker* dns_cert_checker,
124             ProxyService* proxy_service,
125             SSLConfigService* ssl_config_service,
126             HttpAuthHandlerFactory* http_auth_handler_factory,
127             NetworkDelegate* network_delegate,
128             NetLog* net_log,
129             BackendFactory* backend_factory);
130 
131   // The disk cache is initialized lazily (by CreateTransaction) in  this case.
132   // Provide an existing HttpNetworkSession, the cache can construct a
133   // network layer with a shared HttpNetworkSession in order for multiple
134   // network layers to share information (e.g. authentication data). The
135   // HttpCache takes ownership of the |backend_factory|.
136   HttpCache(HttpNetworkSession* session, BackendFactory* backend_factory);
137 
138   // Initialize the cache from its component parts, which is useful for
139   // testing.  The lifetime of the network_layer and backend_factory are managed
140   // by the HttpCache and will be destroyed using |delete| when the HttpCache is
141   // destroyed.
142   HttpCache(HttpTransactionFactory* network_layer,
143             NetLog* net_log,
144             BackendFactory* backend_factory);
145 
146   ~HttpCache();
147 
network_layer()148   HttpTransactionFactory* network_layer() { return network_layer_.get(); }
149 
150   // Retrieves the cache backend for this HttpCache instance. If the backend
151   // is not initialized yet, this method will initialize it. The return value is
152   // a network error code, and it could be ERR_IO_PENDING, in which case the
153   // |callback| will be notified when the operation completes. The pointer that
154   // receives the |backend| must remain valid until the operation completes.
155   int GetBackend(disk_cache::Backend** backend, CompletionCallback* callback);
156 
157   // Returns the current backend (can be NULL).
158   disk_cache::Backend* GetCurrentBackend();
159 
160   // Given a header data blob, convert it to a response info object.
161   static bool ParseResponseInfo(const char* data, int len,
162                                 HttpResponseInfo* response_info,
163                                 bool* response_truncated);
164 
165   // Writes |buf_len| bytes of metadata stored in |buf| to the cache entry
166   // referenced by |url|, as long as the entry's |expected_response_time| has
167   // not changed. This method returns without blocking, and the operation will
168   // be performed asynchronously without any completion notification.
169   void WriteMetadata(const GURL& url, base::Time expected_response_time,
170                      IOBuffer* buf, int buf_len);
171 
172   // Get/Set the cache's mode.
set_mode(Mode value)173   void set_mode(Mode value) { mode_ = value; }
mode()174   Mode mode() { return mode_; }
175 
176   // Close currently active sockets so that fresh page loads will not use any
177   // recycled connections.  For sockets currently in use, they may not close
178   // immediately, but they will not be reusable. This is for debugging.
179   void CloseAllConnections();
180 
181   // Close all idle connections. Will close all sockets not in active use.
182   void CloseIdleConnections();
183 
184   // HttpTransactionFactory implementation:
185   virtual int CreateTransaction(scoped_ptr<HttpTransaction>* trans);
186   virtual HttpCache* GetCache();
187   virtual HttpNetworkSession* GetSession();
188   virtual void Suspend(bool suspend);
189 
190  protected:
191   // Disk cache entry data indices.
192   enum {
193     kResponseInfoIndex = 0,
194     kResponseContentIndex,
195     kMetadataIndex,
196 
197     // Must remain at the end of the enum.
198     kNumCacheEntryDataIndices
199   };
200   friend class ViewCacheHelper;
201 
202  private:
203   // Types --------------------------------------------------------------------
204 
205   class BackendCallback;
206   class MetadataWriter;
207   class SSLHostInfoFactoryAdaptor;
208   class Transaction;
209   class WorkItem;
210   friend class Transaction;
211   struct PendingOp;  // Info for an entry under construction.
212 
213   typedef std::list<Transaction*> TransactionList;
214   typedef std::list<WorkItem*> WorkItemList;
215 
216   struct ActiveEntry {
217     explicit ActiveEntry(disk_cache::Entry* entry);
218     ~ActiveEntry();
219 
220     disk_cache::Entry* disk_entry;
221     Transaction*       writer;
222     TransactionList    readers;
223     TransactionList    pending_queue;
224     bool               will_process_pending_queue;
225     bool               doomed;
226   };
227 
228   typedef base::hash_map<std::string, ActiveEntry*> ActiveEntriesMap;
229   typedef base::hash_map<std::string, PendingOp*> PendingOpsMap;
230   typedef std::set<ActiveEntry*> ActiveEntriesSet;
231   typedef base::hash_map<std::string, int> PlaybackCacheMap;
232 
233   // Methods ------------------------------------------------------------------
234 
235   // Creates the |backend| object and notifies the |callback| when the operation
236   // completes. Returns an error code.
237   int CreateBackend(disk_cache::Backend** backend,
238                     CompletionCallback* callback);
239 
240   // Makes sure that the backend creation is complete before allowing the
241   // provided transaction to use the object. Returns an error code.  |trans|
242   // will be notified via its IO callback if this method returns ERR_IO_PENDING.
243   // The transaction is free to use the backend directly at any time after
244   // receiving the notification.
245   int GetBackendForTransaction(Transaction* trans);
246 
247   // Generates the cache key for this request.
248   std::string GenerateCacheKey(const HttpRequestInfo*);
249 
250   // Dooms the entry selected by |key|. |trans| will be notified via its IO
251   // callback if this method returns ERR_IO_PENDING. The entry can be
252   // currently in use or not.
253   int DoomEntry(const std::string& key, Transaction* trans);
254 
255   // Dooms the entry selected by |key|. |trans| will be notified via its IO
256   // callback if this method returns ERR_IO_PENDING. The entry should not
257   // be currently in use.
258   int AsyncDoomEntry(const std::string& key, Transaction* trans);
259 
260   // Closes a previously doomed entry.
261   void FinalizeDoomedEntry(ActiveEntry* entry);
262 
263   // Returns an entry that is currently in use and not doomed, or NULL.
264   ActiveEntry* FindActiveEntry(const std::string& key);
265 
266   // Creates a new ActiveEntry and starts tracking it. |disk_entry| is the disk
267   // cache entry.
268   ActiveEntry* ActivateEntry(disk_cache::Entry* disk_entry);
269 
270   // Deletes an ActiveEntry.
271   void DeactivateEntry(ActiveEntry* entry);
272 
273   // Deletes an ActiveEntry using an exhaustive search.
274   void SlowDeactivateEntry(ActiveEntry* entry);
275 
276   // Returns the PendingOp for the desired |key|. If an entry is not under
277   // construction already, a new PendingOp structure is created.
278   PendingOp* GetPendingOp(const std::string& key);
279 
280   // Deletes a PendingOp.
281   void DeletePendingOp(PendingOp* pending_op);
282 
283   // Opens the disk cache entry associated with |key|, returning an ActiveEntry
284   // in |*entry|. |trans| will be notified via its IO callback if this method
285   // returns ERR_IO_PENDING.
286   int OpenEntry(const std::string& key, ActiveEntry** entry,
287                 Transaction* trans);
288 
289   // Creates the disk cache entry associated with |key|, returning an
290   // ActiveEntry in |*entry|. |trans| will be notified via its IO callback if
291   // this method returns ERR_IO_PENDING.
292   int CreateEntry(const std::string& key, ActiveEntry** entry,
293                   Transaction* trans);
294 
295   // Destroys an ActiveEntry (active or doomed).
296   void DestroyEntry(ActiveEntry* entry);
297 
298   // Adds a transaction to an ActiveEntry. If this method returns ERR_IO_PENDING
299   // the transaction will be notified about completion via its IO callback. This
300   // method returns ERR_CACHE_RACE to signal the transaction that it cannot be
301   // added to the provided entry, and it should retry the process with another
302   // one (in this case, the entry is no longer valid).
303   int AddTransactionToEntry(ActiveEntry* entry, Transaction* trans);
304 
305   // Called when the transaction has finished working with this entry. |cancel|
306   // is true if the operation was cancelled by the caller instead of running
307   // to completion.
308   void DoneWithEntry(ActiveEntry* entry, Transaction* trans, bool cancel);
309 
310   // Called when the transaction has finished writting to this entry. |success|
311   // is false if the cache entry should be deleted.
312   void DoneWritingToEntry(ActiveEntry* entry, bool success);
313 
314   // Called when the transaction has finished reading from this entry.
315   void DoneReadingFromEntry(ActiveEntry* entry, Transaction* trans);
316 
317   // Convers the active writter transaction to a reader so that other
318   // transactions can start reading from this entry.
319   void ConvertWriterToReader(ActiveEntry* entry);
320 
321   // Returns the LoadState of the provided pending transaction.
322   LoadState GetLoadStateForPendingTransaction(const Transaction* trans);
323 
324   // Removes the transaction |trans|, from the pending list of an entry
325   // (PendingOp, active or doomed entry).
326   void RemovePendingTransaction(Transaction* trans);
327 
328   // Removes the transaction |trans|, from the pending list of |entry|.
329   bool RemovePendingTransactionFromEntry(ActiveEntry* entry,
330                                          Transaction* trans);
331 
332   // Removes the transaction |trans|, from the pending list of |pending_op|.
333   bool RemovePendingTransactionFromPendingOp(PendingOp* pending_op,
334                                              Transaction* trans);
335 
336   // Resumes processing the pending list of |entry|.
337   void ProcessPendingQueue(ActiveEntry* entry);
338 
339   // Events (called via PostTask) ---------------------------------------------
340 
341   void OnProcessPendingQueue(ActiveEntry* entry);
342 
343   // Callbacks ----------------------------------------------------------------
344 
345   // Processes BackendCallback notifications.
346   void OnIOComplete(int result, PendingOp* entry);
347 
348   // Processes the backend creation notification.
349   void OnBackendCreated(int result, PendingOp* pending_op);
350 
351 
352   // Variables ----------------------------------------------------------------
353 
354   NetLog* net_log_;
355 
356   // Used when lazily constructing the disk_cache_.
357   scoped_ptr<BackendFactory> backend_factory_;
358   bool building_backend_;
359 
360   Mode mode_;
361 
362   const scoped_ptr<SSLHostInfoFactoryAdaptor> ssl_host_info_factory_;
363 
364   const scoped_ptr<HttpTransactionFactory> network_layer_;
365   scoped_ptr<disk_cache::Backend> disk_cache_;
366 
367   // The set of active entries indexed by cache key.
368   ActiveEntriesMap active_entries_;
369 
370   // The set of doomed entries.
371   ActiveEntriesSet doomed_entries_;
372 
373   // The set of entries "under construction".
374   PendingOpsMap pending_ops_;
375 
376   ScopedRunnableMethodFactory<HttpCache> task_factory_;
377 
378   scoped_ptr<PlaybackCacheMap> playback_cache_map_;
379 
380   DISALLOW_COPY_AND_ASSIGN(HttpCache);
381 };
382 
383 }  // namespace net
384 
385 #endif  // NET_HTTP_HTTP_CACHE_H_
386