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 #include "content/browser/service_worker/service_worker_disk_cache_migrator.h" | |
6 | |
7 #include "base/memory/ref_counted.h" | |
8 #include "base/strings/string_number_conversions.h" | |
9 #include "content/common/service_worker/service_worker_types.h" | |
10 #include "net/base/io_buffer.h" | |
11 #include "net/base/net_errors.h" | |
12 #include "net/disk_cache/disk_cache.h" | |
13 | |
14 namespace content { | |
15 | |
16 // A task to move a cached resource from the src DiskCache to the dest | |
17 // DiskCache. This is owned by ServiceWorkerDiskCacheMigrator. | |
18 class ServiceWorkerDiskCacheMigrator::Task { | |
19 public: | |
20 Task(InflightTaskMap::KeyType task_id, | |
21 int64 resource_id, | |
22 disk_cache::Entry* entry, | |
23 ServiceWorkerDiskCache* src, | |
24 ServiceWorkerDiskCache* dest, | |
25 const base::WeakPtr<ServiceWorkerDiskCacheMigrator>& owner); | |
26 ~Task(); | |
27 | |
28 void Run(); | |
29 | |
30 private: | |
31 void ReadResponseInfo(); | |
32 void OnReadResponseInfo( | |
33 const scoped_refptr<HttpResponseInfoIOBuffer>& info_buffer, | |
34 int result); | |
35 void OnWriteResponseInfo( | |
36 const scoped_refptr<HttpResponseInfoIOBuffer>& info_buffer, | |
37 int result); | |
38 void WriteResponseMetadata( | |
39 const scoped_refptr<HttpResponseInfoIOBuffer>& info_buffer); | |
40 void OnWriteResponseMetadata(int result); | |
41 void ReadResponseData(); | |
42 void OnReadResponseData(const scoped_refptr<net::IOBuffer>& buffer, | |
43 int result); | |
44 void OnWriteResponseData(int result); | |
45 void Finish(ServiceWorkerStatusCode status); | |
46 | |
47 InflightTaskMap::KeyType task_id_; | |
48 int64 resource_id_; | |
49 disk_cache::Entry* entry_; | |
50 base::WeakPtr<ServiceWorkerDiskCacheMigrator> owner_; | |
51 | |
52 scoped_ptr<ServiceWorkerResponseReader> reader_; | |
53 scoped_ptr<ServiceWorkerResponseWriter> writer_; | |
54 scoped_ptr<ServiceWorkerResponseMetadataWriter> metadata_writer_; | |
55 | |
56 base::WeakPtrFactory<Task> weak_factory_; | |
57 | |
58 DISALLOW_COPY_AND_ASSIGN(Task); | |
59 }; | |
60 | |
61 ServiceWorkerDiskCacheMigrator::Task::Task( | |
62 InflightTaskMap::KeyType task_id, | |
63 int64 resource_id, | |
64 disk_cache::Entry* entry, | |
65 ServiceWorkerDiskCache* src, | |
66 ServiceWorkerDiskCache* dest, | |
67 const base::WeakPtr<ServiceWorkerDiskCacheMigrator>& owner) | |
68 : task_id_(task_id), | |
69 resource_id_(resource_id), | |
70 entry_(entry), | |
71 owner_(owner), | |
72 weak_factory_(this) { | |
73 DCHECK(entry_); | |
74 reader_.reset(new ServiceWorkerResponseReader(resource_id, src)); | |
75 writer_.reset(new ServiceWorkerResponseWriter(resource_id, dest)); | |
76 metadata_writer_.reset( | |
77 new ServiceWorkerResponseMetadataWriter(resource_id, dest)); | |
78 } | |
79 | |
80 ServiceWorkerDiskCacheMigrator::Task::~Task() { | |
81 entry_->Close(); | |
82 } | |
83 | |
84 void ServiceWorkerDiskCacheMigrator::Task::Run() { | |
85 ReadResponseInfo(); | |
86 } | |
87 | |
88 void ServiceWorkerDiskCacheMigrator::Task::ReadResponseInfo() { | |
89 scoped_refptr<HttpResponseInfoIOBuffer> info_buffer( | |
90 new HttpResponseInfoIOBuffer); | |
91 reader_->ReadInfo(info_buffer.get(), | |
92 base::Bind(&Task::OnReadResponseInfo, | |
93 weak_factory_.GetWeakPtr(), info_buffer)); | |
94 } | |
95 | |
96 void ServiceWorkerDiskCacheMigrator::Task::OnReadResponseInfo( | |
97 const scoped_refptr<HttpResponseInfoIOBuffer>& info_buffer, | |
98 int result) { | |
99 if (result < 0) { | |
100 LOG(ERROR) << "Failed to read the response info"; | |
101 Finish(SERVICE_WORKER_ERROR_FAILED); | |
102 return; | |
103 } | |
104 writer_->WriteInfo(info_buffer.get(), | |
105 base::Bind(&Task::OnWriteResponseInfo, | |
106 weak_factory_.GetWeakPtr(), info_buffer)); | |
107 } | |
108 | |
109 void ServiceWorkerDiskCacheMigrator::Task::OnWriteResponseInfo( | |
110 const scoped_refptr<HttpResponseInfoIOBuffer>& buffer, | |
111 int result) { | |
112 if (result < 0) { | |
113 LOG(ERROR) << "Failed to write the response info"; | |
114 Finish(SERVICE_WORKER_ERROR_FAILED); | |
115 return; | |
116 } | |
117 | |
118 const net::HttpResponseInfo* http_info = buffer->http_info.get(); | |
119 if (http_info->metadata) { | |
120 WriteResponseMetadata(buffer); | |
121 return; | |
122 } | |
123 ReadResponseData(); | |
124 } | |
125 | |
126 void ServiceWorkerDiskCacheMigrator::Task::WriteResponseMetadata( | |
127 const scoped_refptr<HttpResponseInfoIOBuffer>& info_buffer) { | |
128 const net::HttpResponseInfo* http_info = info_buffer->http_info.get(); | |
129 const int data_size = http_info->metadata->size(); | |
130 | |
131 scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(data_size); | |
132 if (data_size) | |
133 memmove(buffer->data(), http_info->metadata->data(), data_size); | |
michaeln
2015/05/27 23:09:23
This copy is unfortunate, i think there's an IOBuf
nhiroki
2015/05/28 07:47:11
I see. I replaced memmove with WrapppedIOBuffer, a
| |
134 metadata_writer_->WriteMetadata( | |
135 buffer.get(), data_size, | |
136 base::Bind(&Task::OnWriteResponseMetadata, weak_factory_.GetWeakPtr())); | |
137 } | |
138 | |
139 void ServiceWorkerDiskCacheMigrator::Task::OnWriteResponseMetadata(int result) { | |
140 if (result < 0) { | |
141 LOG(ERROR) << "Failed to write the response metadata"; | |
142 Finish(SERVICE_WORKER_ERROR_FAILED); | |
143 return; | |
144 } | |
145 ReadResponseData(); | |
146 } | |
147 | |
148 void ServiceWorkerDiskCacheMigrator::Task::ReadResponseData() { | |
149 scoped_refptr<net::IOBuffer> buffer = | |
150 new net::IOBuffer(entry_->GetDataSize(0)); | |
151 reader_->ReadData(buffer.get(), entry_->GetDataSize(0), | |
152 base::Bind(&Task::OnReadResponseData, | |
153 weak_factory_.GetWeakPtr(), buffer)); | |
154 } | |
155 | |
156 void ServiceWorkerDiskCacheMigrator::Task::OnReadResponseData( | |
157 const scoped_refptr<net::IOBuffer>& buffer, | |
158 int result) { | |
159 if (result < 0) { | |
160 LOG(ERROR) << "Failed to read the response data"; | |
161 Finish(SERVICE_WORKER_ERROR_FAILED); | |
162 return; | |
163 } | |
164 writer_->WriteData( | |
165 buffer.get(), result, | |
166 base::Bind(&Task::OnWriteResponseData, weak_factory_.GetWeakPtr())); | |
167 } | |
168 | |
169 void ServiceWorkerDiskCacheMigrator::Task::OnWriteResponseData(int result) { | |
170 if (result < 0) { | |
171 LOG(ERROR) << "Failed to write the response data"; | |
172 Finish(SERVICE_WORKER_ERROR_FAILED); | |
173 return; | |
174 } | |
175 Finish(SERVICE_WORKER_OK); | |
176 } | |
177 | |
178 void ServiceWorkerDiskCacheMigrator::Task::Finish( | |
179 ServiceWorkerStatusCode status) { | |
180 DCHECK(owner_); | |
181 owner_->OnResourceMigrated(task_id_, status); | |
182 } | |
183 | |
184 ServiceWorkerDiskCacheMigrator::ServiceWorkerDiskCacheMigrator( | |
185 ServiceWorkerDiskCache* src, | |
186 ServiceWorkerDiskCache* dest) | |
187 : src_(src), dest_(dest), weak_factory_(this) { | |
188 DCHECK(!src_->is_disabled()); | |
189 DCHECK(!dest_->is_disabled()); | |
190 } | |
191 | |
192 ServiceWorkerDiskCacheMigrator::~ServiceWorkerDiskCacheMigrator() { | |
193 } | |
194 | |
195 void ServiceWorkerDiskCacheMigrator::Start(const StatusCallback& callback) { | |
196 callback_ = callback; | |
197 iterator_ = src_->disk_cache()->CreateIterator(); | |
198 ContinueMigratingResources(); | |
199 } | |
200 | |
201 void ServiceWorkerDiskCacheMigrator::ContinueMigratingResources() { | |
202 disk_cache::Entry** entry = new disk_cache::Entry*(); | |
203 net::CompletionCallback callback = | |
204 base::Bind(&ServiceWorkerDiskCacheMigrator::OnOpenNextEntry, | |
205 weak_factory_.GetWeakPtr(), base::Owned(entry)); | |
206 int result = iterator_->OpenNextEntry(entry, callback); | |
207 if (result == net::ERR_IO_PENDING) | |
208 return; | |
209 callback.Run(result); | |
210 } | |
211 | |
212 void ServiceWorkerDiskCacheMigrator::OnOpenNextEntry(disk_cache::Entry** entry, | |
213 int result) { | |
214 if (result == net::ERR_FAILED) { | |
215 // ERR_FAILED means the iterator reaches the end of the enumeration. | |
216 if (inflight_tasks_.IsEmpty()) | |
217 Complete(SERVICE_WORKER_OK); | |
218 return; | |
219 } | |
220 | |
221 if (result != net::OK) { | |
222 LOG(ERROR) << "Failed to open the next entry"; | |
223 inflight_tasks_.Clear(); | |
224 Complete(SERVICE_WORKER_ERROR_FAILED); | |
225 return; | |
226 } | |
227 | |
228 int64 resource_id = kInvalidServiceWorkerResourceId; | |
229 if (!base::StringToInt64((*entry)->GetKey(), &resource_id)) { | |
michaeln
2015/05/27 23:09:23
Does anything call (*entry)->Close() in this case
nhiroki
2015/05/28 07:47:11
Good point. To fix this, I introduced WrappedEntry
| |
230 LOG(ERROR) << "Failed to read the resource id"; | |
231 inflight_tasks_.Clear(); | |
232 Complete(SERVICE_WORKER_ERROR_FAILED); | |
233 return; | |
234 } | |
235 | |
236 InflightTaskMap::KeyType task_id = next_task_id_++; | |
237 scoped_ptr<Task> next_task(new Task(task_id, resource_id, *entry, src_, dest_, | |
238 weak_factory_.GetWeakPtr())); | |
239 next_task->Run(); | |
michaeln
2015/05/27 23:09:23
Looks like this will create and start tasks to mig
nhiroki
2015/05/28 00:21:09
In the current patchset, there is no mechanism to
nhiroki
2015/05/28 07:47:11
Done.
| |
240 inflight_tasks_.AddWithID(next_task.release(), task_id); | |
241 | |
242 ContinueMigratingResources(); | |
243 } | |
244 | |
245 void ServiceWorkerDiskCacheMigrator::OnResourceMigrated( | |
246 InflightTaskMap::KeyType task_id, | |
247 ServiceWorkerStatusCode status) { | |
248 DCHECK(inflight_tasks_.Lookup(task_id)); | |
249 inflight_tasks_.Remove(task_id); | |
250 | |
251 if (status != SERVICE_WORKER_OK) { | |
252 inflight_tasks_.Clear(); | |
253 Complete(status); | |
254 return; | |
255 } | |
256 | |
257 if (inflight_tasks_.IsEmpty()) { | |
258 Complete(SERVICE_WORKER_OK); | |
259 return; | |
260 } | |
261 } | |
262 | |
263 void ServiceWorkerDiskCacheMigrator::Complete(ServiceWorkerStatusCode status) { | |
264 DCHECK(inflight_tasks_.IsEmpty()); | |
265 // TODO(nhiroki): Add UMA for the result of migration. | |
266 callback_.Run(status); | |
267 } | |
268 | |
269 } // namespace content | |
OLD | NEW |