Chromium Code Reviews| 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 |