Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 # Architecture | |
| 2 This document descibes the browser-process implementation of the [Cache | |
| 3 Storage specification]( | |
| 4 https://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html). | |
| 5 | |
| 6 ## Major Classes and Ownership | |
| 7 ### Ownership | |
| 8 Where '->' represents ownership, '--' is a reference, and '-/-' is a weak | |
| 9 reference. | |
| 10 | |
| 11 #####`CacheStorageContextImpl`->`CacheStorageManager`-> `CacheStorage`->`CacheSt orageCache` | |
|
jsbell
2016/07/28 16:25:34
nit: consistent spacing
jkarlin
2016/07/28 16:37:18
Done.
| |
| 12 * A `CacheStorageManager` can own multiple `CacheStorage` objects. | |
| 13 * A `CacheStorage` can own multiple `CacheStorageCache` objects. | |
| 14 | |
| 15 #####`StoragePartitionImpl`--`CacheStorageContextImpl` | |
| 16 * `StoragePartitionImpl` effectively owns the `CacheStorageContextImpl` in the | |
| 17 sense that it calls `CacheStorageContextImpl::Shutdown()` on deletion which | |
| 18 resets its `CacheStorageManager`. | |
| 19 | |
| 20 #####`RenderProcessHost`--`CacheStorageDispatcherHost`--`CacheStorageContextImpl ` | |
| 21 | |
| 22 #####`CacheStorageDispatcherHost`->`CacheStorageCacheHandle`-/-`CacheStorageCach e` | |
| 23 * The `CacheStorageDispatcherHost` holds onto handles for: | |
| 24 * currently running operations | |
| 25 * JavaScript references to caches | |
| 26 * recently opened caches (to prevent open/close/open churn) | |
| 27 | |
| 28 #####`CacheStorageCacheDataHandle`->`CacheStorageCacheHandle`-/-`CacheStorageCac he` | |
| 29 * `CacheStorageCacheDataHandle` is the blob data handle for a response body | |
| 30 and it holds a `CacheStorageCacheHandle`. It streams from the | |
| 31 `disk_cache::Entry` response stream. It's necessary that the | |
| 32 `disk_cache::Backend` (owned by `CacheStorageCache`) stays open so long as | |
| 33 one of its `disk_cache::Entrys` is reachable. Otherwise, a new backend might | |
| 34 open and clobber the entry. | |
| 35 | |
| 36 ### CacheStorageDispatcherHost | |
| 37 1. Receives IPC messages from a render process and creates the appropriate | |
| 38 `CacheStorageManager` or `CacheStorageCache` operation. | |
| 39 2. For each operation, holds a `CacheStorageCacheHandle` to keep the cache | |
| 40 alive since the operation is asynchronous. | |
| 41 3. For each cache reference held by the render process, holds a | |
| 42 `CacheStorageCacheHandle`. | |
| 43 4. Holds a newly opened cache open for a few seconds (by storing a handle) to | |
| 44 mitigate rapid opening/closing/opening churn. | |
| 45 | |
| 46 ### CacheStorageManager | |
| 47 1. Forwards calls to the appropriate `CacheStorage` for a given origin, | |
| 48 loading `CacheStorage`s on demand. | |
| 49 2. Handles `QuotaManager` and `BrowsingData` calls. | |
| 50 | |
| 51 ### CacheStorage | |
| 52 1. Manages the caches for a single origin. | |
| 53 2. Handles creation/deletion of caches and updates the index on disk | |
| 54 accordingly. | |
| 55 3. Manages operations that span multiple caches (e.g., `CacheStorage::Match`). | |
| 56 4. Backend-specific information is handled by `CacheStorage::CacheLoader` | |
| 57 | |
| 58 ### CacheStorageCache | |
| 59 1. Creates or opens a net::disk_cache (either `SimpleCache` or `MemoryCache`) | |
| 60 on initialization. | |
| 61 2. Handles add/put/delete/match/keys calls. | |
| 62 3. Owned by `CacheStorage` and deleted either when `CacheStorage` deletes or | |
| 63 when the last `CacheStorageCacheHandle` for the cache is gone. | |
| 64 | |
| 65 ### CacheStorageCacheHandle | |
| 66 1. Holds a weak reference to a `CacheStorageCache`. | |
| 67 2. When the last `CacheStorageCacheHandle` to a `CacheStorageCache` is | |
| 68 deleted, so to is the `CacheStorageCache`. | |
| 69 3. The `CacheStorageCache` may be deleted before the `CacheStorageCacheHandle` | |
| 70 (on `CacheStorage` destruction), so it must be checked for validity before | |
| 71 use. | |
| 72 | |
| 73 ## Directory Structure | |
| 74 $PROFILE/Service Worker/CacheStorage/`origin`/`cache`/ | |
| 75 | |
| 76 Where `origin` is a hash of the origin and `cache` is a GUID generated at the | |
| 77 cache's creation time. | |
| 78 | |
| 79 The purpose of giving each cache a unique directory is so that a cache with | |
| 80 name `foo` can be doomed and still used by old references while another cache | |
| 81 with name `foo` is created. | |
| 82 | |
| 83 ### Directory Contents | |
| 84 `CacheStorage` creates its own index file (index.txt), which contains a | |
| 85 mapping of cache names to its path on disk. On `CacheStorage` initialization, | |
| 86 directories not in the index are deleted. | |
| 87 | |
| 88 Each `CacheStorageCache` has a `disk_cache::Backend` backend, which writes in | |
| 89 the `CacheStorageCache`'s directory. | |
| 90 | |
| 91 ## Layout of the disk_cache::Backend | |
| 92 A cache is represented by a `disk_cache::Backend`. The Request/Response pairs | |
| 93 referred to in the specification are stored as `disk_cache::Entry`s. Each | |
| 94 `disk_cache::Entry` has three streams: one for storing a protobuf with the | |
| 95 request/response metadata (e.g., the headers, the request URL, and opacity | |
| 96 information), another for storing the response body, and a final stream for | |
| 97 storing any additional data (e.g., compiled JavaScript). | |
| 98 | |
| 99 The entries are keyed by full URL. This has a few ramifications: | |
| 100 1. Multiple vary responses for a single request URL are not supported. | |
| 101 2. Operations that may require scanning multiple URLs (e.g., `ignoreSearch`) | |
| 102 must scan every entry in the cache. | |
| 103 | |
| 104 *The above could be fixed by changes to the backend or by introducing indirect | |
| 105 entries in the cache. The indirect entries would be for the query-stripped | |
| 106 request URL. It would point to entries to each query request/response pair and | |
| 107 for each vary request/response pair.* | |
| 108 | |
| 109 ## Threads | |
| 110 * CacheStorage classes live on the IO thread. Exceptions include: | |
| 111 * `CacheStorageContextImpl` which is created on UI but otherwise runs and is | |
| 112 deleted on IO. | |
| 113 * `CacheStorageDispatcherHost` which is created on UI but otherwise runs and | |
| 114 is deleted on IO. | |
| 115 * Index file manipulation and directory creation/deletion occurs on a | |
| 116 `SequencedTaskRunner` assigned at `CacheStorageContextImpl` creation. | |
| 117 * The disk cache is on the IO thread and uses its own worker pool to implement | |
| 118 async operations. | |
| 119 | |
| 120 ## Asynchronous Idioms in CacheStorage and CacheStorageCache | |
| 121 1. All async methods should asynchronously run their callbacks. | |
| 122 2. CacheStorage/ async methods often include several asynchronous steps. Each | |
| 123 step passes a continuation callback on to the next. The continuation | |
| 124 includes all of the necessary state for the operation. | |
| 125 3. Callbacks are guaranteed to run so long as the object | |
| 126 (`CacheStorageCacheCache` or `CacheStorage`) is still alive. Once the | |
| 127 object is deleted, the callbacks are dropped. We don't worry about dropped | |
| 128 callbacks on shutdown. Before closing a `CacheStorage` or | |
| 129 `CacheStorageCache` it should first be `Close()`d to ensure all callbacks | |
| 130 are run. | |
| 131 | |
| 132 ### Scheduling Operations | |
| 133 Operations are scheduled in a sequential scheduler (`CacheStorageScheduler`). | |
| 134 Each `CacheStorage` and `CacheStorageCache` has its own scheduler. If an | |
| 135 operation freezes, then the scheduler is frozen. If a CacheStorage call winds | |
|
jsbell
2016/07/28 16:25:34
Nit: backticks on `CacheStorage`, for consistency
jkarlin
2016/07/28 16:37:18
Done.
| |
| 136 up calling something from every `CacheStorageCache` (e.g., | |
| 137 `CacheStorage::Match`), then one frozen `CacheStorageCache` can freeze the | |
| 138 `CacheStorage` as well. This has happened in the past. Be careful to avoid | |
|
jsbell
2016/07/28 16:25:34
Maybe give example (e.g. a put() op checking quota
jkarlin
2016/07/28 16:37:18
Done.
| |
| 139 situations in which one operation triggers a dependency on another operation | |
| 140 from the same scheduler. | |
| 141 | |
| 142 At the end of an operation, the scheduler needs to be kicked to start the next | |
| 143 operation. The idiom for this in CacheStorage/ is to wrap the operation's | |
| 144 callback with a function that will run the callback as well as advance the | |
| 145 scheduler. So long as the operation runs its wrapped callback the scheduler | |
| 146 will advance. | |
| OLD | NEW |