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/File.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, | |
177 public BytesConsumer::Client, | |
178 public MultipartParser::Client { | |
179 USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsFormData); | |
180 | |
181 public: | |
182 explicit FetchDataLoaderAsFormData(const String& multipartBoundary) | |
183 : m_multipartBoundary(multipartBoundary) {} | |
184 | |
185 void start(BytesConsumer* consumer, | |
186 FetchDataLoader::Client* client) override { | |
187 DCHECK(!m_client); | |
188 DCHECK(!m_consumer); | |
189 DCHECK(!m_formData); | |
190 DCHECK(!m_multipartParser); | |
191 | |
192 const CString multipartBoundaryCString = m_multipartBoundary.utf8(); | |
yhirano
2017/01/11 08:54:03
Is this variable needed? Isn't it enough to run |m
e_hakkinen
2017/05/02 23:38:56
|Utf8()| is not a getter but a conversion function
| |
193 Vector<char> multipartBoundaryVector; | |
194 multipartBoundaryVector.append(multipartBoundaryCString.data(), | |
195 multipartBoundaryCString.length()); | |
196 | |
197 m_client = client; | |
198 m_formData = FormData::create(); | |
199 m_multipartParser = | |
200 new MultipartParser(std::move(multipartBoundaryVector), this); | |
201 m_consumer = consumer; | |
202 m_consumer->setClient(this); | |
203 onStateChange(); | |
204 } | |
205 | |
206 void onStateChange() override { | |
207 while (true) { | |
208 const char* buffer; | |
209 size_t available; | |
210 auto result = m_consumer->beginRead(&buffer, &available); | |
211 if (result == BytesConsumer::Result::ShouldWait) | |
212 return; | |
213 if (result == BytesConsumer::Result::Ok) { | |
214 const bool bufferAppended = | |
215 m_multipartParser->appendData(buffer, available); | |
216 const bool multipartReceiveFailed = m_multipartParser->isCancelled(); | |
217 result = m_consumer->endRead(available); | |
218 if (!bufferAppended || multipartReceiveFailed) | |
219 result = BytesConsumer::Result::Error; | |
220 } | |
221 switch (result) { | |
222 case BytesConsumer::Result::Ok: | |
223 break; | |
224 case BytesConsumer::Result::ShouldWait: | |
225 NOTREACHED(); | |
226 return; | |
227 case BytesConsumer::Result::Done: | |
228 if (m_multipartParser->finish()) { | |
229 DCHECK(!m_multipartParser->isCancelled()); | |
230 m_client->didFetchDataLoadedFormData(m_formData); | |
231 return; | |
232 } | |
233 // Fall throught. | |
yhirano
2017/01/11 08:54:03
Can you write m_client->didFetchDataLoadFailed() h
e_hakkinen
2017/05/02 23:38:56
Done.
| |
234 case BytesConsumer::Result::Error: | |
235 m_client->didFetchDataLoadFailed(); | |
236 return; | |
237 } | |
238 } | |
239 } | |
240 | |
241 void cancel() override { | |
242 m_consumer->cancel(); | |
243 m_multipartParser->cancel(); | |
244 } | |
245 | |
246 DEFINE_INLINE_TRACE() { | |
247 visitor->trace(m_consumer); | |
248 visitor->trace(m_client); | |
249 visitor->trace(m_formData); | |
250 visitor->trace(m_multipartParser); | |
251 FetchDataLoader::trace(visitor); | |
252 BytesConsumer::Client::trace(visitor); | |
253 MultipartParser::Client::trace(visitor); | |
254 } | |
255 | |
256 private: | |
257 void partHeaderFieldsInMultipartReceived( | |
258 const HTTPHeaderMap& headerFields) override { | |
259 if (!m_currentEntry.initialize(headerFields)) | |
260 m_multipartParser->cancel(); | |
yhirano
2017/01/11 08:54:03
Shouldn't be this cancel() (i.e., this->cancel())?
e_hakkinen
2017/05/02 23:38:56
No, it should not. This member function is called
| |
261 } | |
262 | |
263 void partDataInMultipartReceived(const char* bytes, size_t size) override { | |
264 if (!m_currentEntry.appendBytes(bytes, size)) | |
265 m_multipartParser->cancel(); | |
266 } | |
267 | |
268 void partDataInMultipartFullyReceived() override { | |
269 if (!m_currentEntry.finish(m_formData)) | |
270 m_multipartParser->cancel(); | |
271 } | |
272 | |
273 class Entry { | |
274 public: | |
275 bool initialize(const HTTPHeaderMap& headerFields) { | |
276 const ParsedContentType disposition( | |
277 headerFields.get(HTTPNames::Content_Disposition)); | |
278 const String dispositionType = disposition.mimeType(); | |
279 m_filename = disposition.parameterValueForName("filename"); | |
280 m_name = disposition.parameterValueForName("name"); | |
281 m_blobData.reset(); | |
282 m_stringBuilder.reset(); | |
283 if (dispositionType != "form-data" || m_name.isNull()) | |
284 return false; | |
285 if (!m_filename.isNull()) { | |
286 m_blobData = BlobData::create(); | |
287 const AtomicString& contentType = | |
288 headerFields.get(HTTPNames::Content_Type); | |
289 m_blobData->setContentType(contentType.isNull() ? "text/plain" | |
290 : contentType); | |
291 } else { | |
292 if (!m_decoder) | |
293 m_decoder = TextResourceDecoder::createAlwaysUseUTF8ForText(); | |
294 m_stringBuilder.reset(new StringBuilder); | |
295 } | |
296 return true; | |
297 } | |
298 | |
299 bool appendBytes(const char* bytes, size_t size) { | |
300 if (m_blobData) | |
301 m_blobData->appendBytes(bytes, size); | |
302 if (m_stringBuilder) { | |
303 m_stringBuilder->append(m_decoder->decode(bytes, size)); | |
304 if (m_decoder->sawError()) | |
305 return false; | |
306 } | |
307 return true; | |
308 } | |
309 | |
310 bool finish(FormData* formData) { | |
311 if (m_blobData) { | |
312 DCHECK(!m_stringBuilder); | |
313 const auto size = m_blobData->length(); | |
314 File* file = | |
315 File::create(m_filename, invalidFileTime(), | |
316 BlobDataHandle::create(std::move(m_blobData), size)); | |
317 formData->append(m_name, file, m_filename); | |
318 } | |
319 if (m_stringBuilder) { | |
320 DCHECK(!m_blobData); | |
321 m_stringBuilder->append(m_decoder->flush()); | |
322 if (m_decoder->sawError()) | |
323 return false; | |
324 formData->append(m_name, m_stringBuilder->toString()); | |
325 } | |
326 return true; | |
327 } | |
328 | |
329 private: | |
330 std::unique_ptr<BlobData> m_blobData; | |
331 std::unique_ptr<TextResourceDecoder> m_decoder; | |
332 String m_filename; | |
333 String m_name; | |
334 std::unique_ptr<StringBuilder> m_stringBuilder; | |
335 }; | |
336 | |
337 Member<BytesConsumer> m_consumer; | |
338 Member<FetchDataLoader::Client> m_client; | |
339 Member<FormData> m_formData; | |
340 Member<MultipartParser> m_multipartParser; | |
341 | |
342 Entry m_currentEntry; | |
343 String m_multipartBoundary; | |
344 }; | |
345 | |
171 class FetchDataLoaderAsString final : public FetchDataLoader, | 346 class FetchDataLoaderAsString final : public FetchDataLoader, |
172 public BytesConsumer::Client { | 347 public BytesConsumer::Client { |
173 USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsString); | 348 USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsString); |
174 | 349 |
175 public: | 350 public: |
176 void start(BytesConsumer* consumer, | 351 void start(BytesConsumer* consumer, |
177 FetchDataLoader::Client* client) override { | 352 FetchDataLoader::Client* client) override { |
178 DCHECK(!m_client); | 353 DCHECK(!m_client); |
179 DCHECK(!m_decoder); | 354 DCHECK(!m_decoder); |
180 DCHECK(!m_consumer); | 355 DCHECK(!m_consumer); |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
309 | 484 |
310 FetchDataLoader* FetchDataLoader::createLoaderAsBlobHandle( | 485 FetchDataLoader* FetchDataLoader::createLoaderAsBlobHandle( |
311 const String& mimeType) { | 486 const String& mimeType) { |
312 return new FetchDataLoaderAsBlobHandle(mimeType); | 487 return new FetchDataLoaderAsBlobHandle(mimeType); |
313 } | 488 } |
314 | 489 |
315 FetchDataLoader* FetchDataLoader::createLoaderAsArrayBuffer() { | 490 FetchDataLoader* FetchDataLoader::createLoaderAsArrayBuffer() { |
316 return new FetchDataLoaderAsArrayBuffer(); | 491 return new FetchDataLoaderAsArrayBuffer(); |
317 } | 492 } |
318 | 493 |
494 FetchDataLoader* FetchDataLoader::createLoaderAsFormData( | |
495 const String& multipartBoundary) { | |
496 return new FetchDataLoaderAsFormData(multipartBoundary); | |
497 } | |
498 | |
319 FetchDataLoader* FetchDataLoader::createLoaderAsString() { | 499 FetchDataLoader* FetchDataLoader::createLoaderAsString() { |
320 return new FetchDataLoaderAsString(); | 500 return new FetchDataLoaderAsString(); |
321 } | 501 } |
322 | 502 |
323 FetchDataLoader* FetchDataLoader::createLoaderAsStream(Stream* outStream) { | 503 FetchDataLoader* FetchDataLoader::createLoaderAsStream(Stream* outStream) { |
324 return new FetchDataLoaderAsStream(outStream); | 504 return new FetchDataLoaderAsStream(outStream); |
325 } | 505 } |
326 | 506 |
327 } // namespace blink | 507 } // namespace blink |
OLD | NEW |