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 "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 cache for |
| 26 // an installed ServiceWorker main script. If there is no existing cache entry, |
| 27 // this class always writes supplied data back to the cache; if there is an |
| 28 // existing cache entry, this class only writes supplied data back if there is a |
| 29 // 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 StateMachine |
| 36 // inner class below for the mechanics of 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 |WriteHeaders| and |WriteData|. |
| 54 ServiceWorkerCacheWriter(const ResponseReaderCreator& reader_creator, |
| 55 const ResponseWriterCreator& writer_creator); |
| 56 |
| 57 virtual ~ServiceWorkerCacheWriter(); |
| 58 |
| 59 // Writes the supplied |headers| back to the cache. Returns ERR_IO_PENDING if |
| 60 // the write will complete asynchronously, in which case |callback| will be |
| 61 // called when it completes. Otherwise, returns a code other than |
| 62 // ERR_IO_PENDING and does not invoke |callback|. |
| 63 net::Error WriteHeaders(HttpResponseInfoIOBuffer* headers, |
| 64 const OnWriteCompleteCallback& callback); |
| 65 |
| 66 // Writes the supplied body data |data| back to the cache. Returns |
| 67 // ERR_IO_PENDING if the write will complete asynchronously, in which case |
| 68 // |callback| will be called when it completes. Otherwise, returns a code |
| 69 // other than ERR_IO_PENDING and does not invoke |callback|. |
| 70 net::Error WriteData(net::IOBuffer* buf, |
| 71 size_t buf_size, |
| 72 const OnWriteCompleteCallback& callback); |
| 73 |
| 74 // Returns a count of bytes written back to the cache. |
| 75 size_t BytesWritten() const; |
| 76 |
| 77 private: |
| 78 // This class provides an abstract state machine with states named by numeric |
| 79 // IDs and human-readable string names. Each state has a handler, which is run |
| 80 // whenever the state machine is in that state; handlers are responsible for |
| 81 // producing the next state for the machine (via the |next_state| argument), |
| 82 // deciding whether to pause the state machine (via the |pause| argument), and |
| 83 // also generating the next status field, which is passed untouched into the |
| 84 // next state's handler. |
| 85 class StateMachine { |
| 86 public: |
| 87 enum { |
| 88 // Builtin states. All states are allowed to transition to STATE_DONE and |
| 89 // the machine starts in STATE_DONE, but these are otherwise not special. |
| 90 STATE_START = -1, |
| 91 STATE_DONE = -2, |
| 92 }; |
| 93 |
| 94 // The state handler type. The arguments are: |
| 95 // int* next_state - state the machine should move to next |
| 96 // bool* pause - whether the machine should pause (return from Run) or not |
| 97 // int status - status from the previous state's Handler |
| 98 using Handler = base::Callback<int(int*, bool*, int)>; |
| 99 |
| 100 StateMachine(); |
| 101 ~StateMachine(); |
| 102 |
| 103 // Add a new state to the machine. All states must be registered with this |
| 104 // function before transitions are added referencing them. The |name| is an |
| 105 // arbitrary string, used only for debugging. |
| 106 void AddState(int id, const std::string& name, const Handler& handler); |
| 107 |
| 108 // Add an allowed transition from state |from_id| to state |to_id|. In debug |
| 109 // builds, allowed transitions are enforced by the state machine. |
| 110 void AddTransition(int from_id, int to_id); |
| 111 |
| 112 // In debug builds, DCHECK() that |from_id| and |to_id| are both valid |
| 113 // states, and that a transition from |from_id| to |to_id| is allowed. |
| 114 void CheckValidTransition(int from_id, int to_id); |
| 115 |
| 116 // Runs the state machine. This function executes the handlers for |
| 117 // successive states of the machine until: |
| 118 // a) The machine enters STATE_DONE |
| 119 // b) A handler returns a negative value, indicating an error |
| 120 // c) A handler pauses the machine |
| 121 // This function returns the return value of the last handler that was run. |
| 122 int Run(int status); |
| 123 |
| 124 private: |
| 125 // Internal representation of individual states. The |allowed_to| set is a |
| 126 // set of states that a machine in this state may transition to. |
| 127 struct State { |
| 128 State(); |
| 129 State(int id, const std::string& name, const Handler& handler); |
| 130 ~State(); |
| 131 int id; |
| 132 std::string name; |
| 133 Handler handler; |
| 134 std::set<int> allowed_to; |
| 135 }; |
| 136 std::map<int, State> states_; |
| 137 int state_; |
| 138 }; |
| 139 |
| 140 // State handlers. See function comments in the corresponding source file for |
| 141 // details on these. |
| 142 int Start(int* next_state, bool* pause, int result); |
| 143 int ReadHeadersForCompare(int* next_state, bool* pause, int result); |
| 144 int ReadHeadersForCompareDone(int* next_state, bool* pause, int result); |
| 145 int ReadDataForCompare(int* next_state, bool* pause, int result); |
| 146 int ReadDataForCompareDone(int* next_state, bool* pause, int result); |
| 147 int ReadHeadersForCopy(int* next_state, bool* pause, int result); |
| 148 int ReadHeadersForCopyDone(int* next_state, bool* pause, int result); |
| 149 int WriteHeadersForCopy(int* next_state, bool* pause, int result); |
| 150 int WriteHeadersForCopyDone(int* next_state, bool* pause, int result); |
| 151 int ReadDataForCopy(int* next_state, bool* pause, int result); |
| 152 int ReadDataForCopyDone(int* next_state, bool* pause, int result); |
| 153 int WriteDataForCopy(int* next_state, bool* pause, int result); |
| 154 int WriteDataForCopyDone(int* next_state, bool* pause, int result); |
| 155 int WriteHeadersForPassthrough(int* next_state, bool* pause, int result); |
| 156 int WriteHeadersForPassthroughDone(int* next_state, bool* pause, int result); |
| 157 int WriteDataForPassthrough(int* next_state, bool* pause, int result); |
| 158 int WriteDataForPassthroughDone(int* next_state, bool* pause, int result); |
| 159 int Done(int* next_state, bool* pause, int result); |
| 160 |
| 161 // Wrappers for asynchronous calls. These are responsible for scheduling a |
| 162 // callback to drive the state machine if needed. These either: |
| 163 // a) Return ERR_IO_PENDING, and schedule a callback to run the state |
| 164 // machine's Run() later, or |
| 165 // b) Return some other value and do not schedule a callback. |
| 166 int ReadInfoHelper(const scoped_ptr<ServiceWorkerResponseReader>& reader, |
| 167 HttpResponseInfoIOBuffer* buf); |
| 168 int ReadDataHelper(const scoped_ptr<ServiceWorkerResponseReader>& reader, |
| 169 net::IOBuffer* buf, |
| 170 int buf_len); |
| 171 int WriteInfoHelper(const scoped_ptr<ServiceWorkerResponseWriter>& writer, |
| 172 HttpResponseInfoIOBuffer* buf); |
| 173 int WriteDataHelper(const scoped_ptr<ServiceWorkerResponseWriter>& writer, |
| 174 net::IOBuffer* buf, |
| 175 int buf_len); |
| 176 |
| 177 // Callback used by the above helpers. |
| 178 void AsyncRunStateMachine(int result); |
| 179 |
| 180 StateMachine state_machine_; |
| 181 |
| 182 scoped_refptr<HttpResponseInfoIOBuffer> headers_to_read_; |
| 183 scoped_refptr<HttpResponseInfoIOBuffer> headers_to_write_; |
| 184 scoped_refptr<net::IOBuffer> data_to_read_; |
| 185 int len_to_read_; |
| 186 scoped_refptr<net::IOBuffer> data_to_copy_; |
| 187 scoped_refptr<net::IOBuffer> data_to_write_; |
| 188 int len_to_write_; |
| 189 OnWriteCompleteCallback pending_callback_; |
| 190 |
| 191 size_t cached_length_; |
| 192 size_t net_length_; |
| 193 |
| 194 size_t bytes_compared_; |
| 195 size_t bytes_copied_; |
| 196 size_t bytes_written_; |
| 197 |
| 198 size_t compare_offset_; |
| 199 |
| 200 ResponseReaderCreator reader_creator_; |
| 201 ResponseWriterCreator writer_creator_; |
| 202 scoped_ptr<ServiceWorkerResponseReader> compare_reader_; |
| 203 scoped_ptr<ServiceWorkerResponseReader> copy_reader_; |
| 204 scoped_ptr<ServiceWorkerResponseWriter> writer_; |
| 205 base::WeakPtrFactory<ServiceWorkerCacheWriter> weak_factory_; |
| 206 }; |
| 207 |
| 208 } // namespace content |
| 209 |
| 210 #endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_CACHE_WRITER_H_ |
OLD | NEW |