Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(64)

Side by Side Diff: content/browser/service_worker/service_worker_cache_writer.h

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

Powered by Google App Engine
This is Rietveld 408576698