OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 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 CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_WRITER_H_ |
| 6 #define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_WRITER_H_ |
| 7 |
| 8 #include <map> |
| 9 #include <set> |
| 10 |
| 11 #include "base/callback.h" |
| 12 #include "base/memory/scoped_ptr.h" |
| 13 #include "base/memory/weak_ptr.h" |
| 14 #include "content/common/content_export.h" |
| 15 #include "net/base/io_buffer.h" |
| 16 #include "net/base/net_errors.h" |
| 17 |
| 18 namespace content { |
| 19 |
| 20 struct HttpResponseInfoIOBuffer; |
| 21 class ServiceWorkerCacheWriterCore; |
| 22 class ServiceWorkerResponseReader; |
| 23 class ServiceWorkerResponseWriter; |
| 24 class ServiceWorkerStorage; |
| 25 |
| 26 // This class is responsible for possibly updating the ServiceWorker script |
| 27 // cache for an installed ServiceWorker main script. If there is no existing |
| 28 // cache entry, this class always writes supplied data back to the cache; if |
| 29 // there is an existing cache entry, this class only writes supplied data back |
| 30 // if there is a cache mismatch. |
| 31 // |
| 32 // Note that writes done by this class cannot be "short" - ie, if they succeed, |
| 33 // they always write all the supplied data back. Therefore completions are |
| 34 // signalled with net::Error without a count of bytes written. |
| 35 // |
| 36 // This class's behavior is modelled as a state machine; see the DoLoop function |
| 37 // for comments about this. |
| 38 class CONTENT_EXPORT ServiceWorkerCacheWriter { |
| 39 public: |
| 40 using OnWriteCompleteCallback = base::Callback<void(net::Error)>; |
| 41 |
| 42 // The types for the factory functions passed into the constructor. These are |
| 43 // responsible for creating readers from the existing cache entry and writers |
| 44 // to the new cache entry when called. These are passed in as factories |
| 45 // instead of passing readers and writers in directly to avoid creating |
| 46 // writers to entries that won't be updated, and because this class may need |
| 47 // multiple readers internally. |
| 48 using ResponseReaderCreator = |
| 49 base::Callback<scoped_ptr<ServiceWorkerResponseReader>(void)>; |
| 50 using ResponseWriterCreator = |
| 51 base::Callback<scoped_ptr<ServiceWorkerResponseWriter>(void)>; |
| 52 |
| 53 // The existing reader may be null, in which case this instance will |
| 54 // unconditionally write back data supplied to |MaybeWriteHeaders| and |
| 55 // |MaybeWriteData|. |
| 56 ServiceWorkerCacheWriter(const ResponseReaderCreator& reader_creator, |
| 57 const ResponseWriterCreator& writer_creator); |
| 58 |
| 59 ~ServiceWorkerCacheWriter(); |
| 60 |
| 61 // Writes the supplied |headers| back to the cache. Returns ERR_IO_PENDING if |
| 62 // the write will complete asynchronously, in which case |callback| will be |
| 63 // called when it completes. Otherwise, returns a code other than |
| 64 // ERR_IO_PENDING and does not invoke |callback|. Note that this method will |
| 65 // not necessarily write data back to the cache if the incoming data is |
| 66 // equivalent to the existing cached data. See the source of this function for |
| 67 // details about how this function drives the state machine. |
| 68 net::Error MaybeWriteHeaders(HttpResponseInfoIOBuffer* headers, |
| 69 const OnWriteCompleteCallback& callback); |
| 70 |
| 71 // Writes the supplied body data |data| back to the cache. Returns |
| 72 // ERR_IO_PENDING if the write will complete asynchronously, in which case |
| 73 // |callback| will be called when it completes. Otherwise, returns a code |
| 74 // other than ERR_IO_PENDING and does not invoke |callback|. Note that this |
| 75 // method will not necessarily write data back to the cache if the incoming |
| 76 // data is equivalent to the existing cached data. See the source of this |
| 77 // function for details about how this function drives the state machine. |
| 78 net::Error MaybeWriteData(net::IOBuffer* buf, |
| 79 size_t buf_size, |
| 80 const OnWriteCompleteCallback& callback); |
| 81 |
| 82 // Returns a count of bytes written back to the cache. |
| 83 size_t bytes_written() const { return bytes_written_; } |
| 84 bool did_replace() const { return did_replace_; } |
| 85 |
| 86 private: |
| 87 // States for the state machine. |
| 88 // |
| 89 // The state machine flows roughly like this: if there is no existing cache |
| 90 // entry, incoming headers and data are written directly back to the cache |
| 91 // ("passthrough mode", the PASSTHROUGH states). If there is an existing cache |
| 92 // entry, incoming headers and data are compared to the existing cache entry |
| 93 // ("compare mode", the COMPARE states); if at any point the incoming |
| 94 // headers/data are not equal to the cached headers/data, this class copies |
| 95 // the cached data up to the point where the incoming data and the cached data |
| 96 // diverged ("copy mode", the COPY states), then switches to "passthrough |
| 97 // mode" to write the remainder of the incoming data. The overall effect is to |
| 98 // avoid rewriting the cache entry if the incoming data is identical to the |
| 99 // cached data. |
| 100 // |
| 101 // Note that after a call to MaybeWriteHeaders or MaybeWriteData completes, |
| 102 // the machine is always in STATE_DONE, indicating that the call is finished; |
| 103 // those methods are responsible for setting a new initial state. |
| 104 enum State { |
| 105 STATE_START, |
| 106 // Control flows linearly through these four states, then loops from |
| 107 // READ_DATA_FOR_COMPARE_DONE to READ_DATA_FOR_COMPARE, or exits to |
| 108 // READ_HEADERS_FOR_COPY. |
| 109 STATE_READ_HEADERS_FOR_COMPARE, |
| 110 STATE_READ_HEADERS_FOR_COMPARE_DONE, |
| 111 STATE_READ_DATA_FOR_COMPARE, |
| 112 STATE_READ_DATA_FOR_COMPARE_DONE, |
| 113 |
| 114 // Control flows linearly through these states, with each pass from |
| 115 // READ_DATA_FOR_COPY to WRITE_DATA_FOR_COPY_DONE copying one block of data |
| 116 // at a time. Control loops from WRITE_DATA_FOR_COPY_DONE back to |
| 117 // READ_DATA_FOR_COPY if there is more data to copy, or exits to |
| 118 // WRITE_DATA_FOR_PASSTHROUGH. |
| 119 STATE_READ_HEADERS_FOR_COPY, |
| 120 STATE_READ_HEADERS_FOR_COPY_DONE, |
| 121 STATE_WRITE_HEADERS_FOR_COPY, |
| 122 STATE_WRITE_HEADERS_FOR_COPY_DONE, |
| 123 STATE_READ_DATA_FOR_COPY, |
| 124 STATE_READ_DATA_FOR_COPY_DONE, |
| 125 STATE_WRITE_DATA_FOR_COPY, |
| 126 STATE_WRITE_DATA_FOR_COPY_DONE, |
| 127 |
| 128 // Control flows linearly through these states, with a loop between |
| 129 // WRITE_DATA_FOR_PASSTHROUGH and WRITE_DATA_FOR_PASSTHROUGH_DONE. |
| 130 STATE_WRITE_HEADERS_FOR_PASSTHROUGH, |
| 131 STATE_WRITE_HEADERS_FOR_PASSTHROUGH_DONE, |
| 132 STATE_WRITE_DATA_FOR_PASSTHROUGH, |
| 133 STATE_WRITE_DATA_FOR_PASSTHROUGH_DONE, |
| 134 |
| 135 // This state means "done with the current call; ready for another one." |
| 136 STATE_DONE, |
| 137 }; |
| 138 |
| 139 // Drives this class's state machine. This function steps the state machine |
| 140 // until one of: |
| 141 // a) One of the state functions returns an error |
| 142 // b) The state machine reaches STATE_DONE |
| 143 // A successful value (net::OK or greater) indicates that the requested |
| 144 // operation completed synchronously. A return value of ERR_IO_PENDING |
| 145 // indicates that some step had to submit asynchronous IO for later |
| 146 // completion, and the state machine will resume running (via AsyncDoLoop) |
| 147 // when that asynchronous IO completes. Any other return value indicates that |
| 148 // the requested operation failed synchronously. |
| 149 int DoLoop(int result); |
| 150 |
| 151 // State handlers. See function comments in the corresponding source file for |
| 152 // details on these. |
| 153 int DoStart(int result); |
| 154 int DoReadHeadersForCompare(int result); |
| 155 int DoReadHeadersForCompareDone(int result); |
| 156 int DoReadDataForCompare(int result); |
| 157 int DoReadDataForCompareDone(int result); |
| 158 int DoReadHeadersForCopy(int result); |
| 159 int DoReadHeadersForCopyDone(int result); |
| 160 int DoWriteHeadersForCopy(int result); |
| 161 int DoWriteHeadersForCopyDone(int result); |
| 162 int DoReadDataForCopy(int result); |
| 163 int DoReadDataForCopyDone(int result); |
| 164 int DoWriteDataForCopy(int result); |
| 165 int DoWriteDataForCopyDone(int result); |
| 166 int DoWriteHeadersForPassthrough(int result); |
| 167 int DoWriteHeadersForPassthroughDone(int result); |
| 168 int DoWriteDataForPassthrough(int result); |
| 169 int DoWriteDataForPassthroughDone(int result); |
| 170 int DoDone(int result); |
| 171 |
| 172 // Wrappers for asynchronous calls. These are responsible for scheduling a |
| 173 // callback to drive the state machine if needed. These either: |
| 174 // a) Return ERR_IO_PENDING, and schedule a callback to run the state |
| 175 // machine's Run() later, or |
| 176 // b) Return some other value and do not schedule a callback. |
| 177 int ReadInfoHelper(const scoped_ptr<ServiceWorkerResponseReader>& reader, |
| 178 HttpResponseInfoIOBuffer* buf); |
| 179 int ReadDataHelper(const scoped_ptr<ServiceWorkerResponseReader>& reader, |
| 180 net::IOBuffer* buf, |
| 181 int buf_len); |
| 182 int WriteInfoHelper(const scoped_ptr<ServiceWorkerResponseWriter>& writer, |
| 183 HttpResponseInfoIOBuffer* buf); |
| 184 int WriteDataHelper(const scoped_ptr<ServiceWorkerResponseWriter>& writer, |
| 185 net::IOBuffer* buf, |
| 186 int buf_len); |
| 187 |
| 188 // Callback used by the above helpers for their IO operations. This is only |
| 189 // run when those IO operations complete asynchronously, in which case it |
| 190 // invokes the synchronous DoLoop function and runs the client callback (the |
| 191 // one passed into MaybeWriteData/MaybeWriteHeaders) if that invocation |
| 192 // of DoLoop completes synchronously. |
| 193 void AsyncDoLoop(int result); |
| 194 |
| 195 State state_; |
| 196 // Note that this variable is only used for assertions; it reflects "state != |
| 197 // DONE && not in synchronous DoLoop". |
| 198 bool io_pending_; |
| 199 bool comparing_; |
| 200 |
| 201 scoped_refptr<HttpResponseInfoIOBuffer> headers_to_read_; |
| 202 scoped_refptr<HttpResponseInfoIOBuffer> headers_to_write_; |
| 203 scoped_refptr<net::IOBuffer> data_to_read_; |
| 204 int len_to_read_; |
| 205 scoped_refptr<net::IOBuffer> data_to_copy_; |
| 206 scoped_refptr<net::IOBuffer> data_to_write_; |
| 207 int len_to_write_; |
| 208 OnWriteCompleteCallback pending_callback_; |
| 209 |
| 210 size_t cached_length_; |
| 211 |
| 212 size_t bytes_compared_; |
| 213 size_t bytes_copied_; |
| 214 size_t bytes_written_; |
| 215 |
| 216 bool did_replace_; |
| 217 |
| 218 size_t compare_offset_; |
| 219 |
| 220 ResponseReaderCreator reader_creator_; |
| 221 ResponseWriterCreator writer_creator_; |
| 222 scoped_ptr<ServiceWorkerResponseReader> compare_reader_; |
| 223 scoped_ptr<ServiceWorkerResponseReader> copy_reader_; |
| 224 scoped_ptr<ServiceWorkerResponseWriter> writer_; |
| 225 base::WeakPtrFactory<ServiceWorkerCacheWriter> weak_factory_; |
| 226 }; |
| 227 |
| 228 } // namespace content |
| 229 |
| 230 #endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_WRITER_H_ |
OLD | NEW |