Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/FormDataBytesConsumer.h" | 5 #include "modules/fetch/FormDataBytesConsumer.h" |
| 6 | 6 |
| 7 #include "bindings/core/v8/ExceptionState.h" | |
| 7 #include "core/dom/DOMArrayBuffer.h" | 8 #include "core/dom/DOMArrayBuffer.h" |
| 8 #include "core/dom/DOMArrayBufferView.h" | 9 #include "core/dom/DOMArrayBufferView.h" |
| 10 #include "core/dom/ExecutionContext.h" | |
| 11 #include "core/dom/TaskRunnerHelper.h" | |
| 12 #include "core/fileapi/Blob.h" | |
| 13 #include "core/fileapi/File.h" | |
| 9 #include "modules/fetch/BlobBytesConsumer.h" | 14 #include "modules/fetch/BlobBytesConsumer.h" |
| 10 #include "platform/blob/BlobData.h" | 15 #include "platform/blob/BlobData.h" |
| 11 #include "platform/network/EncodedFormData.h" | 16 #include "platform/network/EncodedFormData.h" |
| 12 #include "wtf/Vector.h" | 17 #include "wtf/Vector.h" |
| 13 #include "wtf/text/TextCodec.h" | 18 #include "wtf/text/TextCodec.h" |
| 14 #include "wtf/text/TextEncoding.h" | 19 #include "wtf/text/TextEncoding.h" |
| 15 #include "wtf/text/WTFString.h" | 20 #include "wtf/text/WTFString.h" |
| 16 | 21 |
| 17 namespace blink { | 22 namespace blink { |
| 18 | 23 |
| 19 namespace { | 24 namespace { |
| 20 | 25 |
| 26 using BytesConsumerFactory = FormDataBytesConsumer::BytesConsumerFactory; | |
| 27 | |
| 21 bool isSimple(const EncodedFormData* formData) { | 28 bool isSimple(const EncodedFormData* formData) { |
| 22 for (const auto& element : formData->elements()) { | 29 for (const auto& element : formData->elements()) { |
| 23 if (element.m_type != FormDataElement::data) | 30 if (element.m_type != FormDataElement::data) |
| 24 return false; | 31 return false; |
| 25 } | 32 } |
| 26 return true; | 33 return true; |
| 27 } | 34 } |
| 28 | 35 |
| 29 class SimpleFormDataBytesConsumer : public BytesConsumer { | 36 class SimpleFormDataBytesConsumer : public BytesConsumer { |
| 30 public: | 37 public: |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 94 | 101 |
| 95 private: | 102 private: |
| 96 // either one of |m_formData| and |m_flattenFormData| is usable at a time. | 103 // either one of |m_formData| and |m_flattenFormData| is usable at a time. |
| 97 RefPtr<EncodedFormData> m_formData; | 104 RefPtr<EncodedFormData> m_formData; |
| 98 Vector<char> m_flattenFormData; | 105 Vector<char> m_flattenFormData; |
| 99 size_t m_flattenFormDataOffset = 0; | 106 size_t m_flattenFormDataOffset = 0; |
| 100 PublicState m_state = PublicState::ReadableOrWaiting; | 107 PublicState m_state = PublicState::ReadableOrWaiting; |
| 101 }; | 108 }; |
| 102 | 109 |
| 103 class ComplexFormDataBytesConsumer final : public BytesConsumer { | 110 class ComplexFormDataBytesConsumer final : public BytesConsumer { |
| 111 enum class State { | |
| 112 Clean, | |
| 113 Reading, | |
| 114 Closed, | |
| 115 Errored, | |
| 116 }; | |
| 117 | |
| 104 public: | 118 public: |
| 105 ComplexFormDataBytesConsumer(ExecutionContext* executionContext, | 119 ComplexFormDataBytesConsumer(ExecutionContext* executionContext, |
| 106 PassRefPtr<EncodedFormData> formData, | 120 PassRefPtr<EncodedFormData> formData, |
| 107 BytesConsumer* consumer) | 121 std::unique_ptr<BytesConsumerFactory> factory) |
| 108 : m_formData(formData) { | 122 : m_formData(formData), |
| 109 if (consumer) { | 123 m_executionContext(executionContext), |
| 110 // For testing. | 124 m_factoryForTesting(std::move(factory)) {} |
| 111 m_blobBytesConsumer = consumer; | |
| 112 return; | |
| 113 } | |
| 114 | |
| 115 std::unique_ptr<BlobData> blobData = BlobData::create(); | |
| 116 for (const auto& element : m_formData->elements()) { | |
| 117 switch (element.m_type) { | |
| 118 case FormDataElement::data: | |
| 119 blobData->appendBytes(element.m_data.data(), element.m_data.size()); | |
| 120 break; | |
| 121 case FormDataElement::encodedFile: | |
| 122 blobData->appendFile(element.m_filename, element.m_fileStart, | |
| 123 element.m_fileLength, | |
|
dmurph
2017/02/24 19:49:24
Why not just check if the file size is -1, and if
yhirano
2017/03/02 04:05:04
Fixed.
| |
| 124 element.m_expectedFileModificationTime); | |
| 125 break; | |
| 126 case FormDataElement::encodedBlob: | |
| 127 if (element.m_optionalBlobDataHandle) | |
| 128 blobData->appendBlob(element.m_optionalBlobDataHandle, 0, | |
| 129 element.m_optionalBlobDataHandle->size()); | |
| 130 break; | |
| 131 case FormDataElement::encodedFileSystemURL: | |
| 132 blobData->appendFileSystemURL( | |
| 133 element.m_fileSystemURL, element.m_fileStart, | |
| 134 element.m_fileLength, element.m_expectedFileModificationTime); | |
| 135 break; | |
| 136 } | |
| 137 } | |
| 138 // Here we handle m_formData->boundary() as a C-style string. See | |
| 139 // FormDataEncoder::generateUniqueBoundaryString. | |
| 140 blobData->setContentType(AtomicString("multipart/form-data; boundary=") + | |
| 141 m_formData->boundary().data()); | |
| 142 auto size = blobData->length(); | |
| 143 m_blobBytesConsumer = new BlobBytesConsumer( | |
| 144 executionContext, BlobDataHandle::create(std::move(blobData), size)); | |
| 145 } | |
| 146 | 125 |
| 147 // BytesConsumer implementation | 126 // BytesConsumer implementation |
| 148 Result beginRead(const char** buffer, size_t* available) override { | 127 Result beginRead(const char** buffer, size_t* available) override { |
| 128 *buffer = nullptr; | |
| 129 *available = 0; | |
| 130 if (m_state == State::Closed) | |
| 131 return Result::Done; | |
| 132 if (m_state == State::Errored) | |
| 133 return Result::Error; | |
| 134 if (m_state == State::Clean) | |
| 135 m_state = State::Reading; | |
| 136 | |
| 137 if (m_blobBytesConsumer) { | |
| 138 auto r = m_blobBytesConsumer->beginRead(buffer, available); | |
| 139 if (r == Result::Error) { | |
| 140 m_state = State::Errored; | |
| 141 return r; | |
| 142 } | |
| 143 if (r == Result::Done) { | |
| 144 ++m_elementIndex; | |
| 145 m_blobBytesConsumer = nullptr; | |
| 146 if (m_elementIndex == m_formData->elements().size()) { | |
| 147 m_state = State::Closed; | |
| 148 return Result::Done; | |
| 149 } | |
| 150 return beginRead(buffer, available); | |
| 151 } | |
| 152 return r; | |
| 153 } | |
| 154 const auto& element = m_formData->elements()[m_elementIndex]; | |
| 155 if (element.m_type == FormDataElement::data) { | |
| 156 DCHECK_LE(m_offset, element.m_data.size()); | |
| 157 *buffer = &element.m_data[m_offset]; | |
| 158 *available = element.m_data.size() - m_offset; | |
| 159 return Result::Ok; | |
| 160 } | |
| 161 | |
| 162 RefPtr<BlobDataHandle> blobDataHandle = nullptr; | |
| 163 const String type = "application/octet-stream"; | |
| 164 switch (element.m_type) { | |
| 165 case FormDataElement::data: | |
| 166 NOTREACHED(); | |
| 167 break; | |
| 168 case FormDataElement::encodedBlob: | |
| 169 if (element.m_optionalBlobDataHandle) | |
| 170 blobDataHandle = element.m_optionalBlobDataHandle; | |
| 171 else | |
| 172 blobDataHandle = BlobDataHandle::create(element.m_blobUUID, type, -1); | |
| 173 break; | |
| 174 case FormDataElement::encodedFile: { | |
| 175 NonThrowableExceptionState es; | |
| 176 Blob* file = File::create(element.m_filename); | |
| 177 if (element.m_fileStart > 0) { | |
| 178 file = | |
| 179 file->slice(element.m_fileStart, | |
| 180 element.m_fileStart + element.m_fileLength, type, es); | |
| 181 } | |
| 182 blobDataHandle = file->blobDataHandle(); | |
| 183 break; | |
| 184 } | |
| 185 case FormDataElement::encodedFileSystemURL: { | |
| 186 FileMetadata metadata; | |
| 187 metadata.length = element.m_fileStart + element.m_fileLength; | |
| 188 NonThrowableExceptionState es; | |
| 189 Blob* file = File::createForFileSystemFile( | |
| 190 element.m_fileSystemURL, metadata, File::IsUserVisible); | |
| 191 if (element.m_fileStart > 0) { | |
| 192 file = | |
| 193 file->slice(element.m_fileStart, | |
| 194 element.m_fileStart + element.m_fileLength, type, es); | |
| 195 } | |
| 196 blobDataHandle = file->blobDataHandle(); | |
| 197 break; | |
| 198 } | |
| 199 } | |
| 200 if (m_factoryForTesting) { | |
| 201 m_blobBytesConsumer = | |
| 202 (*m_factoryForTesting)(m_executionContext, std::move(blobDataHandle)); | |
| 203 } else { | |
| 204 m_blobBytesConsumer = | |
| 205 new BlobBytesConsumer(m_executionContext, std::move(blobDataHandle)); | |
| 206 } | |
| 207 if (m_client) | |
| 208 m_blobBytesConsumer->setClient(m_client); | |
| 209 return beginRead(buffer, available); | |
| 210 } | |
| 211 Result endRead(size_t readSize) override { | |
| 212 DCHECK_EQ(m_state, State::Reading); | |
| 213 const auto& element = m_formData->elements()[m_elementIndex]; | |
| 214 if (element.m_type == FormDataElement::data) { | |
| 215 DCHECK_LE(m_offset + readSize, element.m_data.size()); | |
| 216 m_offset += readSize; | |
| 217 if (m_offset == element.m_data.size()) { | |
| 218 m_offset = 0; | |
| 219 ++m_elementIndex; | |
| 220 } | |
| 221 } else { | |
| 222 DCHECK(m_blobBytesConsumer); | |
| 223 auto r = m_blobBytesConsumer->endRead(readSize); | |
| 224 if (r == Result::Error) { | |
| 225 m_state = State::Errored; | |
| 226 return r; | |
| 227 } | |
| 228 if (r == Result::Done) { | |
| 229 m_blobBytesConsumer = nullptr; | |
| 230 ++m_elementIndex; | |
| 231 } | |
| 232 } | |
| 233 if (m_elementIndex == m_formData->elements().size()) { | |
| 234 m_state = State::Closed; | |
| 235 return Result::Done; | |
| 236 } | |
| 237 return Result::Ok; | |
| 238 } | |
| 239 PassRefPtr<EncodedFormData> drainAsFormData() override { | |
| 240 if (m_state != State::Clean) | |
| 241 return nullptr; | |
| 242 DCHECK(!m_blobBytesConsumer); | |
| 243 DCHECK(m_formData); | |
| 244 m_state = State::Closed; | |
| 245 return m_formData.release(); | |
| 246 } | |
| 247 void setClient(BytesConsumer::Client* client) override { | |
| 248 DCHECK(client); | |
| 249 m_client = client; | |
| 250 if (m_blobBytesConsumer) { | |
| 251 m_blobBytesConsumer->setClient(client); | |
| 252 } else if (getPublicState() == PublicState::ReadableOrWaiting) { | |
| 253 TaskRunnerHelper::get(TaskType::Networking, m_executionContext) | |
| 254 ->postTask(BLINK_FROM_HERE, | |
| 255 WTF::bind(&BytesConsumer::Client::onStateChange, | |
| 256 wrapPersistent(m_client.get()))); | |
| 257 } | |
| 258 } | |
| 259 void clearClient() override { | |
| 260 m_client = nullptr; | |
| 261 if (m_blobBytesConsumer) | |
| 262 m_blobBytesConsumer->clearClient(); | |
| 263 } | |
| 264 void cancel() override { | |
| 265 if (m_state == State::Closed || m_state == State::Errored) | |
| 266 return; | |
| 149 m_formData = nullptr; | 267 m_formData = nullptr; |
| 150 // Delegate the operation to the underlying consumer. This relies on | 268 m_client = nullptr; |
| 151 // the fact that we appropriately notify the draining information to | 269 m_state = State::Closed; |
| 152 // the underlying consumer. | 270 if (m_blobBytesConsumer) |
| 153 return m_blobBytesConsumer->beginRead(buffer, available); | 271 m_blobBytesConsumer->cancel(); |
| 154 } | |
| 155 Result endRead(size_t readSize) override { | |
| 156 return m_blobBytesConsumer->endRead(readSize); | |
| 157 } | |
| 158 PassRefPtr<BlobDataHandle> drainAsBlobDataHandle( | |
| 159 BlobSizePolicy policy) override { | |
| 160 RefPtr<BlobDataHandle> handle = | |
| 161 m_blobBytesConsumer->drainAsBlobDataHandle(policy); | |
| 162 if (handle) | |
| 163 m_formData = nullptr; | |
| 164 return handle.release(); | |
| 165 } | |
| 166 PassRefPtr<EncodedFormData> drainAsFormData() override { | |
| 167 if (!m_formData) | |
| 168 return nullptr; | |
| 169 m_blobBytesConsumer->cancel(); | |
| 170 return m_formData.release(); | |
| 171 } | |
| 172 void setClient(BytesConsumer::Client* client) override { | |
| 173 m_blobBytesConsumer->setClient(client); | |
| 174 } | |
| 175 void clearClient() override { m_blobBytesConsumer->clearClient(); } | |
| 176 void cancel() override { | |
| 177 m_formData = nullptr; | |
| 178 m_blobBytesConsumer->cancel(); | |
| 179 } | 272 } |
| 180 PublicState getPublicState() const override { | 273 PublicState getPublicState() const override { |
| 181 return m_blobBytesConsumer->getPublicState(); | 274 switch (m_state) { |
| 182 } | 275 case State::Clean: |
| 183 Error getError() const override { return m_blobBytesConsumer->getError(); } | 276 case State::Reading: |
| 277 return PublicState::ReadableOrWaiting; | |
| 278 case State::Closed: | |
| 279 return PublicState::Closed; | |
| 280 case State::Errored: | |
| 281 return PublicState::Errored; | |
| 282 } | |
| 283 NOTREACHED(); | |
| 284 return PublicState::Errored; | |
| 285 } | |
| 286 Error getError() const override { | |
| 287 if (m_blobBytesConsumer) | |
| 288 return m_blobBytesConsumer->getError(); | |
| 289 return Error(); | |
| 290 } | |
| 184 String debugName() const override { return "ComplexFormDataBytesConsumer"; } | 291 String debugName() const override { return "ComplexFormDataBytesConsumer"; } |
| 185 | 292 |
| 186 DEFINE_INLINE_TRACE() { | 293 DEFINE_INLINE_TRACE() { |
| 187 visitor->trace(m_blobBytesConsumer); | 294 visitor->trace(m_blobBytesConsumer); |
| 295 visitor->trace(m_client); | |
| 296 visitor->trace(m_executionContext); | |
| 188 BytesConsumer::trace(visitor); | 297 BytesConsumer::trace(visitor); |
| 189 } | 298 } |
| 190 | 299 |
| 191 private: | 300 private: |
| 301 unsigned m_elementIndex = 0; | |
| 302 size_t m_offset = 0; | |
| 303 State m_state = State::Clean; | |
| 192 RefPtr<EncodedFormData> m_formData; | 304 RefPtr<EncodedFormData> m_formData; |
| 193 Member<BytesConsumer> m_blobBytesConsumer; | 305 Member<BytesConsumer> m_blobBytesConsumer; |
| 306 Member<BytesConsumer::Client> m_client; | |
| 307 Member<ExecutionContext> m_executionContext; | |
| 308 std::unique_ptr<BytesConsumerFactory> m_factoryForTesting; | |
| 194 }; | 309 }; |
| 195 | 310 |
| 196 } // namespace | 311 } // namespace |
| 197 | 312 |
| 198 FormDataBytesConsumer::FormDataBytesConsumer(const String& string) | 313 FormDataBytesConsumer::FormDataBytesConsumer(const String& string) |
| 199 : m_impl(new SimpleFormDataBytesConsumer(EncodedFormData::create( | 314 : m_impl(new SimpleFormDataBytesConsumer(EncodedFormData::create( |
| 200 UTF8Encoding().encode(string, WTF::EntitiesForUnencodables)))) {} | 315 UTF8Encoding().encode(string, WTF::EntitiesForUnencodables)))) {} |
| 201 | 316 |
| 202 FormDataBytesConsumer::FormDataBytesConsumer(DOMArrayBuffer* buffer) | 317 FormDataBytesConsumer::FormDataBytesConsumer(DOMArrayBuffer* buffer) |
| 203 : FormDataBytesConsumer(buffer->data(), buffer->byteLength()) {} | 318 : FormDataBytesConsumer(buffer->data(), buffer->byteLength()) {} |
| 204 | 319 |
| 205 FormDataBytesConsumer::FormDataBytesConsumer(DOMArrayBufferView* view) | 320 FormDataBytesConsumer::FormDataBytesConsumer(DOMArrayBufferView* view) |
| 206 : FormDataBytesConsumer(view->baseAddress(), view->byteLength()) {} | 321 : FormDataBytesConsumer(view->baseAddress(), view->byteLength()) {} |
| 207 | 322 |
| 208 FormDataBytesConsumer::FormDataBytesConsumer(const void* data, size_t size) | 323 FormDataBytesConsumer::FormDataBytesConsumer(const void* data, size_t size) |
| 209 : m_impl(new SimpleFormDataBytesConsumer( | 324 : m_impl(new SimpleFormDataBytesConsumer( |
| 210 EncodedFormData::create(data, size))) {} | 325 EncodedFormData::create(data, size))) {} |
| 211 | 326 |
| 212 FormDataBytesConsumer::FormDataBytesConsumer( | 327 FormDataBytesConsumer::FormDataBytesConsumer( |
| 213 ExecutionContext* executionContext, | 328 ExecutionContext* executionContext, |
| 214 PassRefPtr<EncodedFormData> formData) | 329 PassRefPtr<EncodedFormData> formData) |
| 215 : FormDataBytesConsumer(executionContext, std::move(formData), nullptr) {} | 330 : FormDataBytesConsumer(executionContext, std::move(formData), nullptr) {} |
| 216 | 331 |
| 217 FormDataBytesConsumer::FormDataBytesConsumer( | 332 FormDataBytesConsumer::FormDataBytesConsumer( |
| 218 ExecutionContext* executionContext, | 333 ExecutionContext* executionContext, |
| 219 PassRefPtr<EncodedFormData> formData, | 334 PassRefPtr<EncodedFormData> formData, |
| 220 BytesConsumer* consumer) | 335 std::unique_ptr<BytesConsumerFactory> factory) |
| 221 : m_impl(isSimple(formData.get()) | 336 : m_impl(isSimple(formData.get()) |
| 222 ? static_cast<BytesConsumer*>( | 337 ? static_cast<BytesConsumer*>( |
| 223 new SimpleFormDataBytesConsumer(std::move(formData))) | 338 new SimpleFormDataBytesConsumer(std::move(formData))) |
| 224 : static_cast<BytesConsumer*>( | 339 : static_cast<BytesConsumer*>( |
| 225 new ComplexFormDataBytesConsumer(executionContext, | 340 new ComplexFormDataBytesConsumer(executionContext, |
| 226 std::move(formData), | 341 std::move(formData), |
| 227 consumer))) {} | 342 std::move(factory)))) {} |
| 228 | 343 |
| 229 } // namespace blink | 344 } // namespace blink |
| OLD | NEW |