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 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
161 BytesConsumer::Client::trace(visitor); | 166 BytesConsumer::Client::trace(visitor); |
162 } | 167 } |
163 | 168 |
164 private: | 169 private: |
165 Member<BytesConsumer> m_consumer; | 170 Member<BytesConsumer> m_consumer; |
166 Member<FetchDataLoader::Client> m_client; | 171 Member<FetchDataLoader::Client> m_client; |
167 | 172 |
168 std::unique_ptr<ArrayBufferBuilder> m_rawData; | 173 std::unique_ptr<ArrayBufferBuilder> m_rawData; |
169 }; | 174 }; |
170 | 175 |
176 class FetchDataLoaderAsFormData final : public FetchDataLoader, public BytesCons umer::Client, public MultipartParser::Client { | |
yhirano
2016/09/21 09:02:57
Please add unittests.
e_hakkinen
2016/09/22 22:27:15
Done.
| |
177 USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsFormData); | |
178 | |
179 public: | |
180 explicit FetchDataLoaderAsFormData(const String& multipartBoundary) | |
181 : m_multipartBoundary(multipartBoundary) | |
182 { | |
183 } | |
184 | |
185 void start(BytesConsumer* consumer, FetchDataLoader::Client* client) overrid e | |
186 { | |
187 DCHECK(!m_client); | |
188 DCHECK(!m_multipartParser); | |
189 DCHECK(!m_consumer); | |
190 | |
191 CString multipartBoundaryCString = m_multipartBoundary.utf8(); | |
192 Vector<char> multipartBoundaryVector; | |
193 multipartBoundaryVector.append(multipartBoundaryCString.data(), multipar tBoundaryCString.length()); | |
194 | |
195 m_client = client; | |
196 m_formData = FormData::create(); | |
197 m_multipartParser = new MultipartParser(std::move(multipartBoundaryVecto r), this); | |
198 m_consumer = consumer; | |
199 m_consumer->setClient(this); | |
200 onStateChange(); | |
201 } | |
202 | |
203 void onStateChange() override | |
204 { | |
205 while (!m_multipartParser->isCancelled()) { | |
206 const char* buffer; | |
207 size_t available; | |
208 switch (m_consumer->beginRead(&buffer, &available)) { | |
209 case BytesConsumer::Result::Ok: | |
210 if (available > 0) { | |
211 if (!m_multipartParser->appendData(buffer, available)) | |
212 failed(); | |
yhirano
2016/09/21 09:02:57
BytesConsumer::cancel cannot be called in a two-ph
e_hakkinen
2016/09/22 22:27:15
Done.
| |
213 } | |
214 if (m_consumer->endRead(available) != BytesConsumer::Result::Ok) { | |
yhirano
2016/09/21 09:02:57
I recently changed BytesConsumer::endRead so that
e_hakkinen
2016/09/22 22:27:16
Done.
| |
215 m_client->didFetchDataLoadFailed(); | |
yhirano
2016/09/21 09:02:57
failed()?
e_hakkinen
2016/09/22 22:27:16
Yeah, but there is not really need for failed() to
| |
216 return; | |
217 } | |
218 break; | |
219 case BytesConsumer::Result::ShouldWait: | |
220 return; | |
221 case BytesConsumer::Result::Done: | |
222 if (m_multipartParser->finish()) { | |
223 m_client->didFetchDataLoadedFormData(m_formData); | |
224 } else { | |
225 m_client->didFetchDataLoadFailed(); | |
226 } | |
227 return; | |
228 case BytesConsumer::Result::Error: | |
229 m_client->didFetchDataLoadFailed(); | |
230 return; | |
231 } | |
232 } | |
233 } | |
234 | |
235 void cancel() override | |
236 { | |
237 m_consumer->cancel(); | |
238 m_multipartParser->cancel(); | |
239 } | |
240 | |
241 DEFINE_INLINE_TRACE() | |
242 { | |
243 visitor->trace(m_consumer); | |
244 visitor->trace(m_client); | |
245 visitor->trace(m_formData); | |
246 visitor->trace(m_multipartParser); | |
247 FetchDataLoader::trace(visitor); | |
248 BytesConsumer::Client::trace(visitor); | |
249 MultipartParser::Client::trace(visitor); | |
250 } | |
251 | |
252 private: | |
253 void failed() | |
254 { | |
255 m_client->didFetchDataLoadFailed(); | |
256 // The client does not like to be notified multiple times thus stop | |
257 // parsing so that no more errors will be reached. | |
258 cancel(); | |
259 } | |
260 | |
261 void partHeaderFieldsInMultipartReceived(const ResourceResponse& response) o verride | |
262 { | |
263 if (!m_currentEntry.initialize(response)) | |
264 failed(); | |
265 } | |
266 | |
267 void partDataInMultipartReceived(const char* bytes, size_t size) override | |
268 { | |
269 if (!m_currentEntry.appendBytes(bytes, size)) | |
270 failed(); | |
271 } | |
272 | |
273 void partDataInMultipartFullyReceived() override | |
274 { | |
275 if (!m_currentEntry.finish(m_formData)) | |
276 failed(); | |
277 } | |
278 | |
279 class Entry { | |
280 public: | |
281 bool initialize(const ResourceResponse& response) | |
282 { | |
283 ParsedContentType disposition(response.httpHeaderField(HTTPNames::Co ntent_Disposition)); | |
284 String dispositionType = disposition.mimeType(); | |
285 m_filename = disposition.parameterValueForName("filename"); | |
286 m_name = disposition.parameterValueForName("name"); | |
287 m_blobData.reset(); | |
288 m_stringBuilder.reset(); | |
289 if (dispositionType != "form-data" || m_name.isNull()) | |
290 return false; | |
291 if (!m_filename.isNull()) { | |
292 m_blobData = BlobData::create(); | |
293 m_blobData->setContentType(response.httpHeaderField(HTTPNames::C ontent_Type)); | |
294 } else { | |
295 if (!m_decoder) | |
296 m_decoder = TextResourceDecoder::createAlwaysUseUTF8ForText( ); | |
297 m_stringBuilder.reset(new StringBuilder); | |
298 } | |
299 return true; | |
300 } | |
301 | |
302 bool appendBytes(const char* bytes, size_t size) | |
303 { | |
304 if (m_blobData) | |
305 m_blobData->appendBytes(bytes, size); | |
306 if (m_stringBuilder) { | |
307 m_stringBuilder->append(m_decoder->decode(bytes, size)); | |
308 if (m_decoder->sawError()) | |
309 return false; | |
310 } | |
311 return true; | |
312 } | |
313 | |
314 bool finish(FormData* formData) | |
315 { | |
316 if (m_blobData) { | |
317 DCHECK(!m_stringBuilder); | |
318 auto size = m_blobData->length(); | |
319 formData->append(m_name, Blob::create(BlobDataHandle::create(std ::move(m_blobData), size)), m_filename); | |
320 } | |
321 if (m_stringBuilder) { | |
322 DCHECK(!m_blobData); | |
323 m_stringBuilder->append(m_decoder->flush()); | |
324 if (m_decoder->sawError()) | |
325 return false; | |
326 formData->append(m_name, m_stringBuilder->toString()); | |
327 } | |
328 return true; | |
329 } | |
330 | |
331 private: | |
332 std::unique_ptr<BlobData> m_blobData; | |
333 std::unique_ptr<TextResourceDecoder> m_decoder; | |
334 String m_filename; | |
335 String m_name; | |
336 std::unique_ptr<StringBuilder> m_stringBuilder; | |
337 }; | |
338 | |
339 Member<BytesConsumer> m_consumer; | |
340 Member<FetchDataLoader::Client> m_client; | |
341 Member<FormData> m_formData; | |
342 Member<MultipartParser> m_multipartParser; | |
343 | |
344 Entry m_currentEntry; | |
345 String m_multipartBoundary; | |
346 }; | |
347 | |
171 class FetchDataLoaderAsString final : public FetchDataLoader, public BytesConsum er::Client { | 348 class FetchDataLoaderAsString final : public FetchDataLoader, public BytesConsum er::Client { |
172 USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsString); | 349 USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsString); |
173 public: | 350 public: |
174 void start(BytesConsumer* consumer, FetchDataLoader::Client* client) overrid e | 351 void start(BytesConsumer* consumer, FetchDataLoader::Client* client) overrid e |
175 { | 352 { |
176 DCHECK(!m_client); | 353 DCHECK(!m_client); |
177 DCHECK(!m_decoder); | 354 DCHECK(!m_decoder); |
178 DCHECK(!m_consumer); | 355 DCHECK(!m_consumer); |
179 m_client = client; | 356 m_client = client; |
180 m_decoder = TextResourceDecoder::createAlwaysUseUTF8ForText(); | 357 m_decoder = TextResourceDecoder::createAlwaysUseUTF8ForText(); |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
312 FetchDataLoader* FetchDataLoader::createLoaderAsBlobHandle(const String& mimeTyp e) | 489 FetchDataLoader* FetchDataLoader::createLoaderAsBlobHandle(const String& mimeTyp e) |
313 { | 490 { |
314 return new FetchDataLoaderAsBlobHandle(mimeType); | 491 return new FetchDataLoaderAsBlobHandle(mimeType); |
315 } | 492 } |
316 | 493 |
317 FetchDataLoader* FetchDataLoader::createLoaderAsArrayBuffer() | 494 FetchDataLoader* FetchDataLoader::createLoaderAsArrayBuffer() |
318 { | 495 { |
319 return new FetchDataLoaderAsArrayBuffer(); | 496 return new FetchDataLoaderAsArrayBuffer(); |
320 } | 497 } |
321 | 498 |
499 FetchDataLoader* FetchDataLoader::createLoaderAsFormData(const String& multipart Boundary) | |
500 { | |
501 return new FetchDataLoaderAsFormData(multipartBoundary); | |
502 } | |
503 | |
322 FetchDataLoader* FetchDataLoader::createLoaderAsString() | 504 FetchDataLoader* FetchDataLoader::createLoaderAsString() |
323 { | 505 { |
324 return new FetchDataLoaderAsString(); | 506 return new FetchDataLoaderAsString(); |
325 } | 507 } |
326 | 508 |
327 FetchDataLoader* FetchDataLoader::createLoaderAsStream(Stream* outStream) | 509 FetchDataLoader* FetchDataLoader::createLoaderAsStream(Stream* outStream) |
328 { | 510 { |
329 return new FetchDataLoaderAsStream(outStream); | 511 return new FetchDataLoaderAsStream(outStream); |
330 } | 512 } |
331 | 513 |
332 } // namespace blink | 514 } // namespace blink |
OLD | NEW |