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