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