OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "modules/fetch/FetchDataLoader.h" | 5 #include "modules/fetch/FetchDataLoader.h" |
6 | 6 |
7 #include "core/fileapi/Blob.h" | |
8 #include "core/html/FormData.h" | |
7 #include "core/html/parser/TextResourceDecoder.h" | 9 #include "core/html/parser/TextResourceDecoder.h" |
8 #include "modules/fetch/BytesConsumer.h" | 10 #include "modules/fetch/BytesConsumer.h" |
11 #include "modules/fetch/MultipartParser.h" | |
12 #include "platform/HTTPNames.h" | |
13 #include "platform/network/ParsedContentType.h" | |
9 #include "wtf/PtrUtil.h" | 14 #include "wtf/PtrUtil.h" |
10 #include "wtf/text/StringBuilder.h" | 15 #include "wtf/text/StringBuilder.h" |
11 #include "wtf/text/WTFString.h" | 16 #include "wtf/text/WTFString.h" |
12 #include "wtf/typed_arrays/ArrayBufferBuilder.h" | 17 #include "wtf/typed_arrays/ArrayBufferBuilder.h" |
13 #include <memory> | 18 #include <memory> |
14 | 19 |
15 namespace blink { | 20 namespace blink { |
16 | 21 |
17 namespace { | 22 namespace { |
18 | 23 |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
154 BytesConsumer::Client::trace(visitor); | 159 BytesConsumer::Client::trace(visitor); |
155 } | 160 } |
156 | 161 |
157 private: | 162 private: |
158 Member<BytesConsumer> m_consumer; | 163 Member<BytesConsumer> m_consumer; |
159 Member<FetchDataLoader::Client> m_client; | 164 Member<FetchDataLoader::Client> m_client; |
160 | 165 |
161 std::unique_ptr<ArrayBufferBuilder> m_rawData; | 166 std::unique_ptr<ArrayBufferBuilder> m_rawData; |
162 }; | 167 }; |
163 | 168 |
169 class FetchDataLoaderAsFormData final : public FetchDataLoader, public BytesCons umer::Client, private MultipartParser::Client { | |
yhirano
2016/09/07 06:00:16
Why do you use private inheritance?
e_hakkinen
2016/09/08 00:06:29
Because public inheritance is not needed. I'll use
yhirano
2016/09/12 02:20:49
Thanks, I think public is preferred (https://googl
| |
170 USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsFormData); | |
171 | |
172 public: | |
173 explicit FetchDataLoaderAsFormData(const String& multipartBoundary) | |
174 : m_multipartBoundary(multipartBoundary) | |
175 { | |
176 } | |
177 | |
178 void start(BytesConsumer* consumer, FetchDataLoader::Client* client) overrid e | |
179 { | |
180 DCHECK(!m_client); | |
181 DCHECK(!m_multipartParser); | |
182 DCHECK(!m_consumer); | |
183 | |
184 CString multipartBoundaryCString = m_multipartBoundary.utf8(); | |
185 Vector<char> multipartBoundaryVector; | |
186 multipartBoundaryVector.append(multipartBoundaryCString.data(), multipar tBoundaryCString.length()); | |
187 | |
188 m_client = client; | |
189 m_formData = FormData::create(); | |
190 m_multipartParser = new MultipartParser(std::move(multipartBoundaryVecto r), this); | |
191 m_consumer = consumer; | |
192 m_consumer->setClient(this); | |
193 onStateChange(); | |
194 } | |
195 | |
196 void onStateChange() override | |
197 { | |
198 while (!m_multipartParser->isCancelled()) { | |
199 const char* buffer; | |
200 size_t available; | |
201 switch (m_consumer->beginRead(&buffer, &available)) { | |
202 case BytesConsumer::Result::Ok: | |
203 if (available > 0) { | |
204 if (!m_multipartParser->appendData(buffer, available)) | |
205 m_client->didFetchDataLoadFailed(); | |
yhirano
2016/09/07 06:00:16
+m_consumer->cancel();
e_hakkinen
2016/09/08 00:06:29
Done.
| |
206 } | |
207 m_consumer->endRead(available); | |
208 break; | |
209 case BytesConsumer::Result::ShouldWait: | |
210 return; | |
211 case BytesConsumer::Result::Done: | |
212 if (m_multipartParser->finish()) { | |
213 m_client->didFetchDataLoadedFormData(m_formData); | |
214 } else { | |
215 m_client->didFetchDataLoadFailed(); | |
216 } | |
217 return; | |
218 case BytesConsumer::Result::Error: | |
219 m_client->didFetchDataLoadFailed(); | |
220 return; | |
221 } | |
222 } | |
223 } | |
224 | |
225 void cancel() override | |
226 { | |
227 m_consumer->cancel(); | |
228 m_multipartParser->cancel(); | |
229 } | |
230 | |
231 DEFINE_INLINE_TRACE() | |
232 { | |
233 visitor->trace(m_consumer); | |
234 visitor->trace(m_client); | |
235 visitor->trace(m_formData); | |
236 visitor->trace(m_multipartParser); | |
237 FetchDataLoader::trace(visitor); | |
238 BytesConsumer::Client::trace(visitor); | |
239 MultipartParser::Client::trace(visitor); | |
240 } | |
241 | |
242 private: | |
243 void partHeaderFieldsInMultipartReceived(const ResourceResponse& response) o verride | |
244 { | |
245 if (!m_currentEntry.initialize(response)) { | |
246 m_client->didFetchDataLoadFailed(); | |
247 // The client does not like to be notified multiple times thus stop | |
248 // parsing so that no more errors will be reached. | |
249 m_multipartParser->cancel(); | |
yhirano
2016/09/07 06:00:16
+m_consumer->cancel();
e_hakkinen
2016/09/08 00:06:29
Done.
| |
250 } | |
251 } | |
252 | |
253 void partDataInMultipartReceived(const char* bytes, size_t size) override | |
254 { | |
255 m_currentEntry.appendBytes(bytes, size); | |
256 } | |
257 | |
258 void partDataInMultipartFullyReceived() override | |
259 { | |
260 m_currentEntry.finish(m_formData); | |
261 } | |
262 | |
263 class Entry { | |
264 public: | |
265 bool initialize(const ResourceResponse& response) | |
266 { | |
267 ParsedContentType disposition(response.httpHeaderField(HTTPNames::Co ntent_Disposition)); | |
268 String dispositionType = disposition.mimeType(); | |
269 m_filename = disposition.parameterValueForName("filename"); | |
270 m_name = disposition.parameterValueForName("name"); | |
yhirano
2016/09/07 06:00:16
I would prefer clearing members unconditionally he
e_hakkinen
2016/09/08 00:06:29
Done.
| |
271 if (dispositionType != "form-data" || m_name.isNull()) | |
272 return false; | |
273 if (!m_filename.isNull()) { | |
274 m_blobData = BlobData::create(); | |
275 m_blobData->setContentType(response.httpHeaderField(HTTPNames::C ontent_Type)); | |
276 m_stringBuilder.reset(); | |
277 } else { | |
278 m_blobData.reset(); | |
279 if (!m_decoder) | |
280 m_decoder = TextResourceDecoder::createAlwaysUseUTF8ForText( ); | |
281 m_stringBuilder.reset(new StringBuilder); | |
282 } | |
283 return true; | |
284 } | |
285 | |
286 void appendBytes(const char* bytes, size_t size) | |
287 { | |
288 if (m_blobData) | |
289 m_blobData->appendBytes(bytes, size); | |
290 if (m_stringBuilder) | |
291 m_stringBuilder->append(m_decoder->decode(bytes, size)); | |
yhirano
2016/09/07 06:00:16
You need to check m_decoder->sawError.
e_hakkinen
2016/09/08 00:06:29
Done.
| |
292 } | |
293 | |
294 void finish(FormData* formData) | |
295 { | |
296 if (m_blobData) { | |
297 DCHECK(!m_stringBuilder); | |
298 auto size = m_blobData->length(); | |
299 formData->append(m_name, Blob::create(BlobDataHandle::create(std ::move(m_blobData), size)), m_filename); | |
300 } | |
301 if (m_stringBuilder) { | |
302 DCHECK(!m_blobData); | |
303 m_stringBuilder->append(m_decoder->flush()); | |
yhirano
2016/09/07 06:00:16
You need to check m_decoder->sawError.
e_hakkinen
2016/09/08 00:06:29
Done.
| |
304 formData->append(m_name, m_stringBuilder->toString()); | |
305 } | |
306 } | |
307 | |
308 private: | |
309 std::unique_ptr<BlobData> m_blobData; | |
310 std::unique_ptr<TextResourceDecoder> m_decoder; | |
311 String m_filename; | |
312 String m_name; | |
313 std::unique_ptr<StringBuilder> m_stringBuilder; | |
314 }; | |
315 | |
316 Member<BytesConsumer> m_consumer; | |
317 Member<FetchDataLoader::Client> m_client; | |
318 Member<FormData> m_formData; | |
319 Member<MultipartParser> m_multipartParser; | |
320 | |
321 Entry m_currentEntry; | |
322 String m_multipartBoundary; | |
323 }; | |
324 | |
164 class FetchDataLoaderAsString final : public FetchDataLoader, public BytesConsum er::Client { | 325 class FetchDataLoaderAsString final : public FetchDataLoader, public BytesConsum er::Client { |
165 USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsString); | 326 USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsString); |
166 public: | 327 public: |
167 void start(BytesConsumer* consumer, FetchDataLoader::Client* client) overrid e | 328 void start(BytesConsumer* consumer, FetchDataLoader::Client* client) overrid e |
168 { | 329 { |
169 DCHECK(!m_client); | 330 DCHECK(!m_client); |
170 DCHECK(!m_decoder); | 331 DCHECK(!m_decoder); |
171 DCHECK(!m_consumer); | 332 DCHECK(!m_consumer); |
172 m_client = client; | 333 m_client = client; |
173 m_decoder = TextResourceDecoder::createAlwaysUseUTF8ForText(); | 334 m_decoder = TextResourceDecoder::createAlwaysUseUTF8ForText(); |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
298 FetchDataLoader* FetchDataLoader::createLoaderAsBlobHandle(const String& mimeTyp e) | 459 FetchDataLoader* FetchDataLoader::createLoaderAsBlobHandle(const String& mimeTyp e) |
299 { | 460 { |
300 return new FetchDataLoaderAsBlobHandle(mimeType); | 461 return new FetchDataLoaderAsBlobHandle(mimeType); |
301 } | 462 } |
302 | 463 |
303 FetchDataLoader* FetchDataLoader::createLoaderAsArrayBuffer() | 464 FetchDataLoader* FetchDataLoader::createLoaderAsArrayBuffer() |
304 { | 465 { |
305 return new FetchDataLoaderAsArrayBuffer(); | 466 return new FetchDataLoaderAsArrayBuffer(); |
306 } | 467 } |
307 | 468 |
469 FetchDataLoader* FetchDataLoader::createLoaderAsFormData(const String& multipart Boundary) | |
470 { | |
471 return new FetchDataLoaderAsFormData(multipartBoundary); | |
472 } | |
473 | |
308 FetchDataLoader* FetchDataLoader::createLoaderAsString() | 474 FetchDataLoader* FetchDataLoader::createLoaderAsString() |
309 { | 475 { |
310 return new FetchDataLoaderAsString(); | 476 return new FetchDataLoaderAsString(); |
311 } | 477 } |
312 | 478 |
313 FetchDataLoader* FetchDataLoader::createLoaderAsStream(Stream* outStream) | 479 FetchDataLoader* FetchDataLoader::createLoaderAsStream(Stream* outStream) |
314 { | 480 { |
315 return new FetchDataLoaderAsStream(outStream); | 481 return new FetchDataLoaderAsStream(outStream); |
316 } | 482 } |
317 | 483 |
318 } // namespace blink | 484 } // namespace blink |
OLD | NEW |