Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(13)

Side by Side Diff: third_party/WebKit/Source/modules/fetch/FormDataBytesConsumer.cpp

Issue 2342023002: Introduce FormDataBytesConsumer (Closed)
Patch Set: fix Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "modules/fetch/FormDataBytesConsumer.h"
6
7 #include "core/dom/DOMArrayBuffer.h"
8 #include "core/dom/DOMArrayBufferView.h"
9 #include "modules/fetch/BlobBytesConsumer.h"
10 #include "platform/blob/BlobData.h"
11 #include "platform/network/EncodedFormData.h"
12 #include "wtf/Vector.h"
13 #include "wtf/text/TextCodec.h"
14 #include "wtf/text/TextEncoding.h"
15 #include "wtf/text/WTFString.h"
16
17 namespace blink {
18
19 namespace {
20
21 bool isSimple(const EncodedFormData* formData)
22 {
23 for (const auto& element : formData->elements()) {
24 if (element.m_type != FormDataElement::data)
25 return false;
26 }
27 return true;
28 }
29
30 class SimpleFormDataBytesConsumer : public BytesConsumer {
31 public:
32 explicit SimpleFormDataBytesConsumer(PassRefPtr<EncodedFormData> formData)
33 : m_formData(formData)
34 {
35 }
36
37 // BytesConsumer implementation
38 Result beginRead(const char** buffer, size_t* available) override
39 {
40 *buffer = nullptr;
41 *available = 0;
42 if (m_formData) {
43 m_formData->flatten(m_flattenFormData);
44 m_formData = nullptr;
45 DCHECK_EQ(m_flattenFormDataOffset, 0u);
46 }
47 if (m_flattenFormDataOffset == m_flattenFormData.size())
48 return Result::Done;
49 *buffer = m_flattenFormData.data() + m_flattenFormDataOffset;
50 *available = m_flattenFormData.size() - m_flattenFormDataOffset;
51 return Result::Ok;
52 }
53 Result endRead(size_t readSize) override
54 {
55 DCHECK(!m_formData);
56 DCHECK_LE(m_flattenFormDataOffset + readSize, m_flattenFormData.size());
57 m_flattenFormDataOffset += readSize;
58 if (m_flattenFormDataOffset == m_flattenFormData.size())
59 m_state = PublicState::Closed;
hiroshige 2016/09/16 07:24:34 If we change the state to Closed here, shouldn't w
yhirano 2016/09/21 03:16:16 You're right, but as talked offline I changed the
hiroshige 2016/09/21 07:42:19 Acknowledged.
60 return Result::Ok;
61 }
62 PassRefPtr<BlobDataHandle> drainAsBlobDataHandle(BlobSizePolicy policy) over ride
63 {
64 if (!m_formData)
65 return nullptr;
66
67 Vector<char> data;
68 m_formData->flatten(data);
69 m_formData = nullptr;
70 std::unique_ptr<BlobData> blobData = BlobData::create();
71 blobData->appendBytes(data.data(), data.size());
72 auto length = blobData->length();
73 m_state = PublicState::Closed;
74 return BlobDataHandle::create(std::move(blobData), length);
75 }
76 PassRefPtr<EncodedFormData> drainAsFormData() override
77 {
78 if (!m_formData)
79 return nullptr;
80
81 m_state = PublicState::Closed;
82 return m_formData.release();
83 }
84 void setClient(BytesConsumer::Client* client) override
85 {
86 DCHECK(client);
87 }
88 void clearClient() override
89 {
90 }
91 void cancel() override
92 {
93 m_state = PublicState::Closed;
94 m_formData = nullptr;
95 m_flattenFormData.clear();
96 m_flattenFormDataOffset = 0;
97 }
98 PublicState getPublicState() const override
99 {
100 return m_state;
101 }
102 Error getError() const override
103 {
104 NOTREACHED();
105 return Error();
106 }
107 String debugName() const override
108 {
109 return "SimpleFormDataBytesConsumer";
110 }
111
112 private:
113 // either one of |m_formData| and |m_flattenFormData| is usable at a time.
114 RefPtr<EncodedFormData> m_formData;
115 Vector<char> m_flattenFormData;
116 size_t m_flattenFormDataOffset = 0;
117 PublicState m_state = PublicState::ReadableOrWaiting;
118 };
119
120 class ComplexFormDataBytesConsumer final : public BytesConsumer {
121 public:
122 ComplexFormDataBytesConsumer(ExecutionContext* executionContext, PassRefPtr< EncodedFormData> formData, BytesConsumer* consumer)
123 : m_formData(formData)
124 {
125 if (consumer) {
126 // For testing.
127 m_blobBytesConsumer = consumer;
128 return;
129 }
130
131 std::unique_ptr<BlobData> blobData = BlobData::create();
132 for (const auto& element : m_formData->elements()) {
133 switch (element.m_type) {
134 case FormDataElement::data:
135 blobData->appendBytes(element.m_data.data(), element.m_data.size ());
136 break;
137 case FormDataElement::encodedFile:
138 blobData->appendFile(element.m_filename, element.m_fileStart, el ement.m_fileLength, element.m_expectedFileModificationTime);
139 break;
140 case FormDataElement::encodedBlob:
141 if (element.m_optionalBlobDataHandle)
142 blobData->appendBlob(element.m_optionalBlobDataHandle, 0, el ement.m_optionalBlobDataHandle->size());
143 break;
144 case FormDataElement::encodedFileSystemURL:
145 blobData->appendFileSystemURL(element.m_fileSystemURL, element.m _fileStart, element.m_fileLength, element.m_expectedFileModificationTime);
146 break;
147 }
148 }
149 // Here we handle m_formData->boundary() as a C-style string. See
150 // FormDataEncoder::generateUniqueBoundaryString.
151 blobData->setContentType(AtomicString("multipart/form-data; boundary=") + m_formData->boundary().data());
152 auto size = blobData->length();
153 m_blobBytesConsumer = new BlobBytesConsumer(executionContext, BlobDataHa ndle::create(std::move(blobData), size));
154 }
155
156 // BytesConsumer implementation
157 Result beginRead(const char** buffer, size_t* available) override
158 {
159 m_formData = nullptr;
160 // Delegate the operation to the underlying consumer. This relies on
161 // the fact that we appropriately notify the draining information to
162 // the underlying consumer.
163 return m_blobBytesConsumer->beginRead(buffer, available);
164 }
165 Result endRead(size_t readSize) override
166 {
167 return m_blobBytesConsumer->endRead(readSize);
168 }
169 PassRefPtr<BlobDataHandle> drainAsBlobDataHandle(BlobSizePolicy policy) over ride
170 {
171 RefPtr<BlobDataHandle> handle = m_blobBytesConsumer->drainAsBlobDataHand le(policy);
172 if (handle)
173 m_formData = nullptr;
174 return handle.release();
175 }
176 PassRefPtr<EncodedFormData> drainAsFormData() override
177 {
178 if (!m_formData)
179 return nullptr;
180 m_blobBytesConsumer->cancel();
181 return m_formData.release();
182 }
183 void setClient(BytesConsumer::Client* client) override
184 {
185 m_blobBytesConsumer->setClient(client);
186 }
187 void clearClient() override
188 {
189 m_blobBytesConsumer->clearClient();
190 }
191 void cancel() override
192 {
193 m_formData = nullptr;
194 m_blobBytesConsumer->cancel();
195 }
196 PublicState getPublicState() const override
197 {
198 return m_blobBytesConsumer->getPublicState();
199 }
200 Error getError() const override
201 {
202 return m_blobBytesConsumer->getError();
203 }
204 String debugName() const override
205 {
206 return "ComplexFormDataBytesConsumer";
207 }
208
209 DEFINE_INLINE_TRACE()
210 {
211 visitor->trace(m_blobBytesConsumer);
212 BytesConsumer::trace(visitor);
213 }
214
215 private:
216 RefPtr<EncodedFormData> m_formData;
217 Member<BytesConsumer> m_blobBytesConsumer;
218 };
219
220 } // namespace
221
222 FormDataBytesConsumer::FormDataBytesConsumer(const String& string)
223 : m_impl(new SimpleFormDataBytesConsumer(EncodedFormData::create(UTF8Encodin g().encode(string, WTF::EntitiesForUnencodables))))
224 {
225 }
226
227 FormDataBytesConsumer::FormDataBytesConsumer(DOMArrayBuffer* buffer)
228 : FormDataBytesConsumer(buffer->data(), buffer->byteLength())
229 {
230 }
231
232 FormDataBytesConsumer::FormDataBytesConsumer(DOMArrayBufferView* view)
233 : FormDataBytesConsumer(view->baseAddress(), view->byteLength())
234 {
235 }
236
237 FormDataBytesConsumer::FormDataBytesConsumer(const void* data, size_t size)
238 : m_impl(new SimpleFormDataBytesConsumer(EncodedFormData::create(data, size) ))
239 {
240 }
241
242 FormDataBytesConsumer::FormDataBytesConsumer(ExecutionContext* executionContext, PassRefPtr<EncodedFormData> formData)
243 : FormDataBytesConsumer(executionContext, formData, nullptr)
244 {
245 }
246
247 FormDataBytesConsumer::FormDataBytesConsumer(ExecutionContext* executionContext, PassRefPtr<EncodedFormData> formData, BytesConsumer* consumer)
248 : m_impl(isSimple(formData.get()) ?
249 static_cast<BytesConsumer*>(new SimpleFormDataBytesConsumer(formData)) :
250 static_cast<BytesConsumer*>(new ComplexFormDataBytesConsumer(executionCo ntext, formData, consumer)))
251 {
252 }
253
254 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698