[email protected] | b0ef9af | 2015-06-19 09:20:44 | [diff] [blame] | 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 | |
[email protected] | b0ef9af | 2015-06-19 09:20:44 | [diff] [blame] | 5 | #include "modules/fetch/FetchDataLoader.h" |
| 6 | |
Yuta Kitamura | 68130af | 2017-04-11 08:20:36 | [diff] [blame] | 7 | #include <memory> |
eero.hakkinen | 6bd271f | 2017-05-22 11:36:04 | [diff] [blame] | 8 | #include "core/fileapi/File.h" |
| 9 | #include "core/html/FormData.h" |
[email protected] | 3e1cfc8 | 2015-07-21 13:54:38 | [diff] [blame] | 10 | #include "core/html/parser/TextResourceDecoder.h" |
yhirano | 6963b6b | 2016-08-17 04:14:56 | [diff] [blame] | 11 | #include "modules/fetch/BytesConsumer.h" |
eero.hakkinen | 6bd271f | 2017-05-22 11:36:04 | [diff] [blame] | 12 | #include "modules/fetch/MultipartParser.h" |
shimazu | 1ac68cf | 2017-04-20 06:03:46 | [diff] [blame] | 13 | #include "mojo/public/cpp/system/simple_watcher.h" |
eero.hakkinen | 6bd271f | 2017-05-22 11:36:04 | [diff] [blame] | 14 | #include "platform/HTTPNames.h" |
Hiroshige Hayashizaki | ee353af | 2017-06-20 22:37:33 | [diff] [blame] | 15 | #include "platform/loader/fetch/TextResourceDecoderOptions.h" |
eero.hakkinen | fb83c2d | 2017-05-24 06:53:32 | [diff] [blame] | 16 | #include "platform/network/ParsedContentDisposition.h" |
shimazu | 1ac68cf | 2017-04-20 06:03:46 | [diff] [blame] | 17 | #include "platform/wtf/Functional.h" |
Yuta Kitamura | 68130af | 2017-04-11 08:20:36 | [diff] [blame] | 18 | #include "platform/wtf/PtrUtil.h" |
| 19 | #include "platform/wtf/text/StringBuilder.h" |
| 20 | #include "platform/wtf/text/WTFString.h" |
| 21 | #include "platform/wtf/typed_arrays/ArrayBufferBuilder.h" |
[email protected] | b0ef9af | 2015-06-19 09:20:44 | [diff] [blame] | 22 | |
| 23 | namespace blink { |
| 24 | |
| 25 | namespace { |
| 26 | |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 27 | class FetchDataLoaderAsBlobHandle final : public FetchDataLoader, |
| 28 | public BytesConsumer::Client { |
| 29 | USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsBlobHandle); |
| 30 | |
| 31 | public: |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 32 | explicit FetchDataLoaderAsBlobHandle(const String& mime_type) |
| 33 | : mime_type_(mime_type) {} |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 34 | |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 35 | void Start(BytesConsumer* consumer, |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 36 | FetchDataLoader::Client* client) override { |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 37 | DCHECK(!client_); |
| 38 | DCHECK(!consumer_); |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 39 | |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 40 | client_ = client; |
| 41 | consumer_ = consumer; |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 42 | |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 43 | RefPtr<BlobDataHandle> blob_handle = consumer_->DrainAsBlobDataHandle(); |
| 44 | if (blob_handle) { |
| 45 | DCHECK_NE(UINT64_MAX, blob_handle->size()); |
| 46 | if (blob_handle->GetType() != mime_type_) { |
Marijn Kruisselbrink | 058ca54 | 2017-08-01 22:55:21 | [diff] [blame^] | 47 | storage::mojom::blink::BlobPtr blob_clone = blob_handle->CloneBlobPtr(); |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 48 | // A new BlobDataHandle is created to override the Blob's type. |
Marijn Kruisselbrink | 058ca54 | 2017-08-01 22:55:21 | [diff] [blame^] | 49 | // TODO(mek): It might be cleaner to create a new blob (referencing the |
| 50 | // old blob) rather than just a new BlobDataHandle with mime type not |
| 51 | // matching the type of the underlying blob. |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 52 | client_->DidFetchDataLoadedBlobHandle(BlobDataHandle::Create( |
Marijn Kruisselbrink | 058ca54 | 2017-08-01 22:55:21 | [diff] [blame^] | 53 | blob_handle->Uuid(), mime_type_, blob_handle->size(), |
| 54 | blob_clone.PassInterface())); |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 55 | } else { |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 56 | client_->DidFetchDataLoadedBlobHandle(std::move(blob_handle)); |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 57 | } |
| 58 | return; |
[email protected] | b0ef9af | 2015-06-19 09:20:44 | [diff] [blame] | 59 | } |
| 60 | |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 61 | blob_data_ = BlobData::Create(); |
| 62 | blob_data_->SetContentType(mime_type_); |
| 63 | consumer_->SetClient(this); |
| 64 | OnStateChange(); |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 65 | } |
[email protected] | b0ef9af | 2015-06-19 09:20:44 | [diff] [blame] | 66 | |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 67 | void Cancel() override { consumer_->Cancel(); } |
yhirano | 6963b6b | 2016-08-17 04:14:56 | [diff] [blame] | 68 | |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 69 | void OnStateChange() override { |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 70 | while (true) { |
| 71 | const char* buffer; |
| 72 | size_t available; |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 73 | auto result = consumer_->BeginRead(&buffer, &available); |
| 74 | if (result == BytesConsumer::Result::kShouldWait) |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 75 | return; |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 76 | if (result == BytesConsumer::Result::kOk) { |
| 77 | blob_data_->AppendBytes(buffer, available); |
| 78 | result = consumer_->EndRead(available); |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 79 | } |
| 80 | switch (result) { |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 81 | case BytesConsumer::Result::kOk: |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 82 | break; |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 83 | case BytesConsumer::Result::kShouldWait: |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 84 | NOTREACHED(); |
| 85 | return; |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 86 | case BytesConsumer::Result::kDone: { |
| 87 | auto size = blob_data_->length(); |
| 88 | client_->DidFetchDataLoadedBlobHandle( |
| 89 | BlobDataHandle::Create(std::move(blob_data_), size)); |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 90 | return; |
| 91 | } |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 92 | case BytesConsumer::Result::kError: |
| 93 | client_->DidFetchDataLoadFailed(); |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 94 | return; |
| 95 | } |
| 96 | } |
| 97 | } |
| 98 | |
| 99 | DEFINE_INLINE_TRACE() { |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 100 | visitor->Trace(consumer_); |
| 101 | visitor->Trace(client_); |
| 102 | FetchDataLoader::Trace(visitor); |
| 103 | BytesConsumer::Client::Trace(visitor); |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 104 | } |
| 105 | |
| 106 | private: |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 107 | Member<BytesConsumer> consumer_; |
| 108 | Member<FetchDataLoader::Client> client_; |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 109 | |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 110 | String mime_type_; |
| 111 | std::unique_ptr<BlobData> blob_data_; |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 112 | }; |
| 113 | |
| 114 | class FetchDataLoaderAsArrayBuffer final : public FetchDataLoader, |
| 115 | public BytesConsumer::Client { |
| 116 | USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsArrayBuffer) |
| 117 | public: |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 118 | void Start(BytesConsumer* consumer, |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 119 | FetchDataLoader::Client* client) override { |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 120 | DCHECK(!client_); |
| 121 | DCHECK(!raw_data_); |
| 122 | DCHECK(!consumer_); |
| 123 | client_ = client; |
| 124 | raw_data_ = WTF::MakeUnique<ArrayBufferBuilder>(); |
| 125 | consumer_ = consumer; |
| 126 | consumer_->SetClient(this); |
| 127 | OnStateChange(); |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 128 | } |
| 129 | |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 130 | void Cancel() override { consumer_->Cancel(); } |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 131 | |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 132 | void OnStateChange() override { |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 133 | while (true) { |
| 134 | const char* buffer; |
| 135 | size_t available; |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 136 | auto result = consumer_->BeginRead(&buffer, &available); |
| 137 | if (result == BytesConsumer::Result::kShouldWait) |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 138 | return; |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 139 | if (result == BytesConsumer::Result::kOk) { |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 140 | if (available > 0) { |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 141 | unsigned bytes_appended = raw_data_->Append(buffer, available); |
| 142 | if (!bytes_appended) { |
| 143 | auto unused = consumer_->EndRead(0); |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 144 | ALLOW_UNUSED_LOCAL(unused); |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 145 | consumer_->Cancel(); |
| 146 | client_->DidFetchDataLoadFailed(); |
[email protected] | b0ef9af | 2015-06-19 09:20:44 | [diff] [blame] | 147 | return; |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 148 | } |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 149 | DCHECK_EQ(bytes_appended, available); |
[email protected] | b0ef9af | 2015-06-19 09:20:44 | [diff] [blame] | 150 | } |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 151 | result = consumer_->EndRead(available); |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 152 | } |
| 153 | switch (result) { |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 154 | case BytesConsumer::Result::kOk: |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 155 | break; |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 156 | case BytesConsumer::Result::kShouldWait: |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 157 | NOTREACHED(); |
| 158 | return; |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 159 | case BytesConsumer::Result::kDone: |
| 160 | client_->DidFetchDataLoadedArrayBuffer( |
| 161 | DOMArrayBuffer::Create(raw_data_->ToArrayBuffer())); |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 162 | return; |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 163 | case BytesConsumer::Result::kError: |
| 164 | client_->DidFetchDataLoadFailed(); |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 165 | return; |
| 166 | } |
[email protected] | b0ef9af | 2015-06-19 09:20:44 | [diff] [blame] | 167 | } |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 168 | } |
[email protected] | b0ef9af | 2015-06-19 09:20:44 | [diff] [blame] | 169 | |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 170 | DEFINE_INLINE_TRACE() { |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 171 | visitor->Trace(consumer_); |
| 172 | visitor->Trace(client_); |
| 173 | FetchDataLoader::Trace(visitor); |
| 174 | BytesConsumer::Client::Trace(visitor); |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 175 | } |
[email protected] | b0ef9af | 2015-06-19 09:20:44 | [diff] [blame] | 176 | |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 177 | private: |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 178 | Member<BytesConsumer> consumer_; |
| 179 | Member<FetchDataLoader::Client> client_; |
yhirano | 6963b6b | 2016-08-17 04:14:56 | [diff] [blame] | 180 | |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 181 | std::unique_ptr<ArrayBufferBuilder> raw_data_; |
[email protected] | b0ef9af | 2015-06-19 09:20:44 | [diff] [blame] | 182 | }; |
| 183 | |
eero.hakkinen | 6bd271f | 2017-05-22 11:36:04 | [diff] [blame] | 184 | class FetchDataLoaderAsFailure final : public FetchDataLoader, |
| 185 | public BytesConsumer::Client { |
| 186 | USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsFailure); |
| 187 | |
| 188 | public: |
| 189 | void Start(BytesConsumer* consumer, |
| 190 | FetchDataLoader::Client* client) override { |
| 191 | DCHECK(!client_); |
| 192 | DCHECK(!consumer_); |
| 193 | client_ = client; |
| 194 | consumer_ = consumer; |
| 195 | consumer_->SetClient(this); |
| 196 | OnStateChange(); |
| 197 | } |
| 198 | |
| 199 | void OnStateChange() override { |
| 200 | while (true) { |
| 201 | const char* buffer; |
| 202 | size_t available; |
| 203 | auto result = consumer_->BeginRead(&buffer, &available); |
| 204 | if (result == BytesConsumer::Result::kShouldWait) |
| 205 | return; |
| 206 | if (result == BytesConsumer::Result::kOk) |
| 207 | result = consumer_->EndRead(available); |
| 208 | switch (result) { |
| 209 | case BytesConsumer::Result::kOk: |
| 210 | break; |
| 211 | case BytesConsumer::Result::kShouldWait: |
| 212 | NOTREACHED(); |
| 213 | return; |
| 214 | case BytesConsumer::Result::kDone: |
| 215 | case BytesConsumer::Result::kError: |
| 216 | client_->DidFetchDataLoadFailed(); |
| 217 | return; |
| 218 | } |
| 219 | } |
| 220 | } |
| 221 | |
| 222 | void Cancel() override { consumer_->Cancel(); } |
| 223 | |
| 224 | DEFINE_INLINE_TRACE() { |
| 225 | visitor->Trace(consumer_); |
| 226 | visitor->Trace(client_); |
| 227 | FetchDataLoader::Trace(visitor); |
| 228 | BytesConsumer::Client::Trace(visitor); |
| 229 | } |
| 230 | |
| 231 | private: |
| 232 | Member<BytesConsumer> consumer_; |
| 233 | Member<FetchDataLoader::Client> client_; |
| 234 | }; |
| 235 | |
| 236 | class FetchDataLoaderAsFormData final : public FetchDataLoader, |
| 237 | public BytesConsumer::Client, |
| 238 | public MultipartParser::Client { |
| 239 | USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsFormData); |
| 240 | |
| 241 | public: |
| 242 | explicit FetchDataLoaderAsFormData(const String& multipart_boundary) |
| 243 | : multipart_boundary_(multipart_boundary) {} |
| 244 | |
| 245 | void Start(BytesConsumer* consumer, |
| 246 | FetchDataLoader::Client* client) override { |
| 247 | DCHECK(!client_); |
| 248 | DCHECK(!consumer_); |
| 249 | DCHECK(!form_data_); |
| 250 | DCHECK(!multipart_parser_); |
| 251 | |
| 252 | const CString multipart_boundary_utf8 = multipart_boundary_.Utf8(); |
| 253 | Vector<char> multipart_boundary_vector; |
| 254 | multipart_boundary_vector.Append(multipart_boundary_utf8.data(), |
| 255 | multipart_boundary_utf8.length()); |
| 256 | |
| 257 | client_ = client; |
| 258 | form_data_ = FormData::Create(); |
| 259 | multipart_parser_ = |
| 260 | new MultipartParser(std::move(multipart_boundary_vector), this); |
| 261 | consumer_ = consumer; |
| 262 | consumer_->SetClient(this); |
| 263 | OnStateChange(); |
| 264 | } |
| 265 | |
| 266 | void OnStateChange() override { |
| 267 | while (true) { |
| 268 | const char* buffer; |
| 269 | size_t available; |
| 270 | auto result = consumer_->BeginRead(&buffer, &available); |
| 271 | if (result == BytesConsumer::Result::kShouldWait) |
| 272 | return; |
| 273 | if (result == BytesConsumer::Result::kOk) { |
| 274 | const bool buffer_appended = |
| 275 | multipart_parser_->AppendData(buffer, available); |
| 276 | const bool multipart_receive_failed = multipart_parser_->IsCancelled(); |
| 277 | result = consumer_->EndRead(available); |
| 278 | if (!buffer_appended || multipart_receive_failed) |
| 279 | result = BytesConsumer::Result::kError; |
| 280 | } |
| 281 | switch (result) { |
| 282 | case BytesConsumer::Result::kOk: |
| 283 | break; |
| 284 | case BytesConsumer::Result::kShouldWait: |
| 285 | NOTREACHED(); |
| 286 | return; |
| 287 | case BytesConsumer::Result::kDone: |
| 288 | if (multipart_parser_->Finish()) { |
| 289 | DCHECK(!multipart_parser_->IsCancelled()); |
| 290 | client_->DidFetchDataLoadedFormData(form_data_); |
| 291 | } else { |
| 292 | client_->DidFetchDataLoadFailed(); |
| 293 | } |
| 294 | return; |
| 295 | case BytesConsumer::Result::kError: |
| 296 | client_->DidFetchDataLoadFailed(); |
| 297 | return; |
| 298 | } |
| 299 | } |
| 300 | } |
| 301 | |
| 302 | void Cancel() override { |
| 303 | consumer_->Cancel(); |
| 304 | multipart_parser_->Cancel(); |
| 305 | } |
| 306 | |
| 307 | DEFINE_INLINE_TRACE() { |
| 308 | visitor->Trace(consumer_); |
| 309 | visitor->Trace(client_); |
| 310 | visitor->Trace(form_data_); |
| 311 | visitor->Trace(multipart_parser_); |
| 312 | FetchDataLoader::Trace(visitor); |
| 313 | BytesConsumer::Client::Trace(visitor); |
| 314 | MultipartParser::Client::Trace(visitor); |
| 315 | } |
| 316 | |
| 317 | private: |
| 318 | void PartHeaderFieldsInMultipartReceived( |
| 319 | const HTTPHeaderMap& header_fields) override { |
| 320 | if (!current_entry_.Initialize(header_fields)) |
| 321 | multipart_parser_->Cancel(); |
| 322 | } |
| 323 | |
| 324 | void PartDataInMultipartReceived(const char* bytes, size_t size) override { |
| 325 | if (!current_entry_.AppendBytes(bytes, size)) |
| 326 | multipart_parser_->Cancel(); |
| 327 | } |
| 328 | |
| 329 | void PartDataInMultipartFullyReceived() override { |
| 330 | if (!current_entry_.Finish(form_data_)) |
| 331 | multipart_parser_->Cancel(); |
| 332 | } |
| 333 | |
| 334 | class Entry { |
| 335 | public: |
| 336 | bool Initialize(const HTTPHeaderMap& header_fields) { |
eero.hakkinen | fb83c2d | 2017-05-24 06:53:32 | [diff] [blame] | 337 | const ParsedContentDisposition disposition( |
| 338 | header_fields.Get(HTTPNames::Content_Disposition)); |
| 339 | const String disposition_type = disposition.Type(); |
| 340 | filename_ = disposition.Filename(); |
eero.hakkinen | 6bd271f | 2017-05-22 11:36:04 | [diff] [blame] | 341 | name_ = disposition.ParameterValueForName("name"); |
| 342 | blob_data_.reset(); |
| 343 | string_builder_.reset(); |
| 344 | if (disposition_type != "form-data" || name_.IsNull()) |
| 345 | return false; |
| 346 | if (!filename_.IsNull()) { |
| 347 | blob_data_ = BlobData::Create(); |
| 348 | const AtomicString& content_type = |
| 349 | header_fields.Get(HTTPNames::Content_Type); |
| 350 | blob_data_->SetContentType(content_type.IsNull() ? "text/plain" |
| 351 | : content_type); |
| 352 | } else { |
Hiroshige Hayashizaki | ee353af | 2017-06-20 22:37:33 | [diff] [blame] | 353 | if (!string_decoder_) { |
| 354 | string_decoder_ = TextResourceDecoder::Create( |
| 355 | TextResourceDecoderOptions::CreateAlwaysUseUTF8ForText()); |
| 356 | } |
eero.hakkinen | 6bd271f | 2017-05-22 11:36:04 | [diff] [blame] | 357 | string_builder_.reset(new StringBuilder); |
| 358 | } |
| 359 | return true; |
| 360 | } |
| 361 | |
| 362 | bool AppendBytes(const char* bytes, size_t size) { |
| 363 | if (blob_data_) |
| 364 | blob_data_->AppendBytes(bytes, size); |
| 365 | if (string_builder_) { |
| 366 | string_builder_->Append(string_decoder_->Decode(bytes, size)); |
| 367 | if (string_decoder_->SawError()) |
| 368 | return false; |
| 369 | } |
| 370 | return true; |
| 371 | } |
| 372 | |
| 373 | bool Finish(FormData* form_data) { |
| 374 | if (blob_data_) { |
| 375 | DCHECK(!string_builder_); |
| 376 | const auto size = blob_data_->length(); |
| 377 | File* file = |
| 378 | File::Create(filename_, InvalidFileTime(), |
| 379 | BlobDataHandle::Create(std::move(blob_data_), size)); |
| 380 | form_data->append(name_, file, filename_); |
| 381 | return true; |
| 382 | } |
| 383 | DCHECK(!blob_data_); |
| 384 | DCHECK(string_builder_); |
| 385 | string_builder_->Append(string_decoder_->Flush()); |
| 386 | if (string_decoder_->SawError()) |
| 387 | return false; |
| 388 | form_data->append(name_, string_builder_->ToString()); |
| 389 | return true; |
| 390 | } |
| 391 | |
| 392 | private: |
| 393 | std::unique_ptr<BlobData> blob_data_; |
| 394 | String filename_; |
| 395 | String name_; |
| 396 | std::unique_ptr<StringBuilder> string_builder_; |
| 397 | std::unique_ptr<TextResourceDecoder> string_decoder_; |
| 398 | }; |
| 399 | |
| 400 | Member<BytesConsumer> consumer_; |
| 401 | Member<FetchDataLoader::Client> client_; |
| 402 | Member<FormData> form_data_; |
| 403 | Member<MultipartParser> multipart_parser_; |
| 404 | |
| 405 | Entry current_entry_; |
| 406 | String multipart_boundary_; |
| 407 | }; |
| 408 | |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 409 | class FetchDataLoaderAsString final : public FetchDataLoader, |
| 410 | public BytesConsumer::Client { |
| 411 | USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsString); |
| 412 | |
| 413 | public: |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 414 | void Start(BytesConsumer* consumer, |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 415 | FetchDataLoader::Client* client) override { |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 416 | DCHECK(!client_); |
| 417 | DCHECK(!decoder_); |
| 418 | DCHECK(!consumer_); |
| 419 | client_ = client; |
Hiroshige Hayashizaki | ee353af | 2017-06-20 22:37:33 | [diff] [blame] | 420 | decoder_ = TextResourceDecoder::Create( |
| 421 | TextResourceDecoderOptions::CreateAlwaysUseUTF8ForText()); |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 422 | consumer_ = consumer; |
| 423 | consumer_->SetClient(this); |
| 424 | OnStateChange(); |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 425 | } |
| 426 | |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 427 | void OnStateChange() override { |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 428 | while (true) { |
| 429 | const char* buffer; |
| 430 | size_t available; |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 431 | auto result = consumer_->BeginRead(&buffer, &available); |
| 432 | if (result == BytesConsumer::Result::kShouldWait) |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 433 | return; |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 434 | if (result == BytesConsumer::Result::kOk) { |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 435 | if (available > 0) |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 436 | builder_.Append(decoder_->Decode(buffer, available)); |
| 437 | result = consumer_->EndRead(available); |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 438 | } |
| 439 | switch (result) { |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 440 | case BytesConsumer::Result::kOk: |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 441 | break; |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 442 | case BytesConsumer::Result::kShouldWait: |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 443 | NOTREACHED(); |
| 444 | return; |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 445 | case BytesConsumer::Result::kDone: |
| 446 | builder_.Append(decoder_->Flush()); |
| 447 | client_->DidFetchDataLoadedString(builder_.ToString()); |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 448 | return; |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 449 | case BytesConsumer::Result::kError: |
| 450 | client_->DidFetchDataLoadFailed(); |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 451 | return; |
| 452 | } |
[email protected] | b0ef9af | 2015-06-19 09:20:44 | [diff] [blame] | 453 | } |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 454 | } |
[email protected] | b0ef9af | 2015-06-19 09:20:44 | [diff] [blame] | 455 | |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 456 | void Cancel() override { consumer_->Cancel(); } |
[email protected] | b0ef9af | 2015-06-19 09:20:44 | [diff] [blame] | 457 | |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 458 | DEFINE_INLINE_TRACE() { |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 459 | visitor->Trace(consumer_); |
| 460 | visitor->Trace(client_); |
| 461 | FetchDataLoader::Trace(visitor); |
| 462 | BytesConsumer::Client::Trace(visitor); |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 463 | } |
[email protected] | b0ef9af | 2015-06-19 09:20:44 | [diff] [blame] | 464 | |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 465 | private: |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 466 | Member<BytesConsumer> consumer_; |
| 467 | Member<FetchDataLoader::Client> client_; |
[email protected] | b0ef9af | 2015-06-19 09:20:44 | [diff] [blame] | 468 | |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 469 | std::unique_ptr<TextResourceDecoder> decoder_; |
| 470 | StringBuilder builder_; |
[email protected] | b0ef9af | 2015-06-19 09:20:44 | [diff] [blame] | 471 | }; |
| 472 | |
shimazu | 1ac68cf | 2017-04-20 06:03:46 | [diff] [blame] | 473 | class FetchDataLoaderAsDataPipe final : public FetchDataLoader, |
| 474 | public BytesConsumer::Client { |
| 475 | USING_GARBAGE_COLLECTED_MIXIN(FetchDataLoaderAsDataPipe); |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 476 | |
| 477 | public: |
shimazu | 1ac68cf | 2017-04-20 06:03:46 | [diff] [blame] | 478 | explicit FetchDataLoaderAsDataPipe( |
| 479 | mojo::ScopedDataPipeProducerHandle out_data_pipe) |
| 480 | : out_data_pipe_(std::move(out_data_pipe)), |
| 481 | data_pipe_watcher_(FROM_HERE, |
| 482 | mojo::SimpleWatcher::ArmingPolicy::MANUAL) {} |
| 483 | ~FetchDataLoaderAsDataPipe() override {} |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 484 | |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 485 | void Start(BytesConsumer* consumer, |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 486 | FetchDataLoader::Client* client) override { |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 487 | DCHECK(!client_); |
| 488 | DCHECK(!consumer_); |
shimazu | 1ac68cf | 2017-04-20 06:03:46 | [diff] [blame] | 489 | data_pipe_watcher_.Watch( |
| 490 | out_data_pipe_.get(), MOJO_HANDLE_SIGNAL_WRITABLE, |
| 491 | ConvertToBaseCallback(WTF::Bind(&FetchDataLoaderAsDataPipe::OnWritable, |
| 492 | WrapWeakPersistent(this)))); |
| 493 | data_pipe_watcher_.ArmOrNotify(); |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 494 | client_ = client; |
| 495 | consumer_ = consumer; |
| 496 | consumer_->SetClient(this); |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 497 | } |
| 498 | |
shimazu | 1ac68cf | 2017-04-20 06:03:46 | [diff] [blame] | 499 | void OnWritable(MojoResult) { OnStateChange(); } |
| 500 | |
| 501 | // Implements BytesConsumer::Client. |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 502 | void OnStateChange() override { |
shimazu | 1ac68cf | 2017-04-20 06:03:46 | [diff] [blame] | 503 | bool should_wait = false; |
| 504 | while (!should_wait) { |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 505 | const char* buffer; |
| 506 | size_t available; |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 507 | auto result = consumer_->BeginRead(&buffer, &available); |
shimazu | 1ac68cf | 2017-04-20 06:03:46 | [diff] [blame] | 508 | if (result == BytesConsumer::Result::kShouldWait) |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 509 | return; |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 510 | if (result == BytesConsumer::Result::kOk) { |
shimazu | 1ac68cf | 2017-04-20 06:03:46 | [diff] [blame] | 511 | DCHECK_GT(available, 0UL); |
| 512 | uint32_t num_bytes = available; |
| 513 | MojoResult mojo_result = |
| 514 | mojo::WriteDataRaw(out_data_pipe_.get(), buffer, &num_bytes, |
| 515 | MOJO_WRITE_DATA_FLAG_NONE); |
| 516 | if (mojo_result == MOJO_RESULT_OK) { |
| 517 | result = consumer_->EndRead(num_bytes); |
| 518 | } else if (mojo_result == MOJO_RESULT_SHOULD_WAIT) { |
| 519 | result = consumer_->EndRead(0); |
| 520 | should_wait = true; |
| 521 | data_pipe_watcher_.ArmOrNotify(); |
| 522 | } else { |
| 523 | result = consumer_->EndRead(0); |
| 524 | StopInternal(); |
| 525 | client_->DidFetchDataLoadFailed(); |
| 526 | return; |
| 527 | } |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 528 | } |
| 529 | switch (result) { |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 530 | case BytesConsumer::Result::kOk: |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 531 | break; |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 532 | case BytesConsumer::Result::kShouldWait: |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 533 | NOTREACHED(); |
| 534 | return; |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 535 | case BytesConsumer::Result::kDone: |
shimazu | 1ac68cf | 2017-04-20 06:03:46 | [diff] [blame] | 536 | StopInternal(); |
| 537 | client_->DidFetchDataLoadedDataPipe(); |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 538 | return; |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 539 | case BytesConsumer::Result::kError: |
shimazu | 1ac68cf | 2017-04-20 06:03:46 | [diff] [blame] | 540 | StopInternal(); |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 541 | client_->DidFetchDataLoadFailed(); |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 542 | return; |
| 543 | } |
[email protected] | 3e1cfc8 | 2015-07-21 13:54:38 | [diff] [blame] | 544 | } |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 545 | } |
[email protected] | 3e1cfc8 | 2015-07-21 13:54:38 | [diff] [blame] | 546 | |
shimazu | 1ac68cf | 2017-04-20 06:03:46 | [diff] [blame] | 547 | void Cancel() override { StopInternal(); } |
[email protected] | 3e1cfc8 | 2015-07-21 13:54:38 | [diff] [blame] | 548 | |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 549 | DEFINE_INLINE_TRACE() { |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 550 | visitor->Trace(consumer_); |
| 551 | visitor->Trace(client_); |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 552 | FetchDataLoader::Trace(visitor); |
| 553 | BytesConsumer::Client::Trace(visitor); |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 554 | } |
[email protected] | 3e1cfc8 | 2015-07-21 13:54:38 | [diff] [blame] | 555 | |
shimazu | 1ac68cf | 2017-04-20 06:03:46 | [diff] [blame] | 556 | private: |
| 557 | void StopInternal() { |
| 558 | consumer_->Cancel(); |
| 559 | data_pipe_watcher_.Cancel(); |
| 560 | out_data_pipe_.reset(); |
| 561 | } |
| 562 | |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 563 | Member<BytesConsumer> consumer_; |
| 564 | Member<FetchDataLoader::Client> client_; |
shimazu | 1ac68cf | 2017-04-20 06:03:46 | [diff] [blame] | 565 | |
| 566 | mojo::ScopedDataPipeProducerHandle out_data_pipe_; |
| 567 | mojo::SimpleWatcher data_pipe_watcher_; |
[email protected] | 3e1cfc8 | 2015-07-21 13:54:38 | [diff] [blame] | 568 | }; |
| 569 | |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 570 | } // namespace |
[email protected] | f4b82b9 | 2015-06-25 12:39:33 | [diff] [blame] | 571 | |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 572 | FetchDataLoader* FetchDataLoader::CreateLoaderAsBlobHandle( |
| 573 | const String& mime_type) { |
| 574 | return new FetchDataLoaderAsBlobHandle(mime_type); |
[email protected] | b0ef9af | 2015-06-19 09:20:44 | [diff] [blame] | 575 | } |
| 576 | |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 577 | FetchDataLoader* FetchDataLoader::CreateLoaderAsArrayBuffer() { |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 578 | return new FetchDataLoaderAsArrayBuffer(); |
[email protected] | b0ef9af | 2015-06-19 09:20:44 | [diff] [blame] | 579 | } |
| 580 | |
eero.hakkinen | 6bd271f | 2017-05-22 11:36:04 | [diff] [blame] | 581 | FetchDataLoader* FetchDataLoader::CreateLoaderAsFailure() { |
| 582 | return new FetchDataLoaderAsFailure(); |
| 583 | } |
| 584 | |
| 585 | FetchDataLoader* FetchDataLoader::CreateLoaderAsFormData( |
| 586 | const String& multipartBoundary) { |
| 587 | return new FetchDataLoaderAsFormData(multipartBoundary); |
| 588 | } |
| 589 | |
Blink Reformat | 1c4d759e | 2017-04-09 16:34:54 | [diff] [blame] | 590 | FetchDataLoader* FetchDataLoader::CreateLoaderAsString() { |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 591 | return new FetchDataLoaderAsString(); |
[email protected] | b0ef9af | 2015-06-19 09:20:44 | [diff] [blame] | 592 | } |
| 593 | |
shimazu | 1ac68cf | 2017-04-20 06:03:46 | [diff] [blame] | 594 | FetchDataLoader* FetchDataLoader::CreateLoaderAsDataPipe( |
| 595 | mojo::ScopedDataPipeProducerHandle out_data_pipe) { |
| 596 | return new FetchDataLoaderAsDataPipe(std::move(out_data_pipe)); |
[email protected] | f4b82b9 | 2015-06-25 12:39:33 | [diff] [blame] | 597 | } |
| 598 | |
Blink Reformat | 1c8e1a77 | 2016-10-01 00:25:32 | [diff] [blame] | 599 | } // namespace blink |