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

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

Issue 2342233002: Remove Fetch[Blob|FormData]ConsumerHandle (Closed)
Patch Set: rebase 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 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
5 #include "modules/fetch/FetchFormDataConsumerHandle.h"
6
7 #include "modules/fetch/DataConsumerHandleUtil.h"
8 #include "modules/fetch/FetchBlobDataConsumerHandle.h"
9 #include "wtf/PtrUtil.h"
10 #include "wtf/ThreadingPrimitives.h"
11 #include "wtf/Vector.h"
12 #include "wtf/text/TextCodec.h"
13 #include "wtf/text/TextEncoding.h"
14 #include "wtf/text/WTFString.h"
15 #include <memory>
16 #include <utility>
17
18 namespace blink {
19
20 using Result = FetchDataConsumerHandle::Result;
21
22 namespace {
23
24 bool isSimple(const EncodedFormData* formData)
25 {
26 for (const auto& element : formData->elements()) {
27 if (element.m_type != FormDataElement::data)
28 return false;
29 }
30 return true;
31 }
32
33 } // namespace
34
35 class FetchFormDataConsumerHandle::Context : public ThreadSafeRefCounted<Context > {
36 WTF_MAKE_NONCOPYABLE(Context);
37 public:
38 virtual ~Context() {}
39 virtual std::unique_ptr<FetchDataConsumerHandle::Reader> obtainReader(Client *) = 0;
40
41 protected:
42 explicit Context() {}
43 };
44
45 class FetchFormDataConsumerHandle::SimpleContext final : public Context {
46 class ReaderImpl;
47 public:
48 static PassRefPtr<SimpleContext> create(const String& body) { return adoptRe f(new SimpleContext(body)); }
49 static PassRefPtr<SimpleContext> create(const void* data, size_t size) { ret urn adoptRef(new SimpleContext(data, size)); }
50 static PassRefPtr<SimpleContext> create(PassRefPtr<EncodedFormData> body) { return adoptRef(new SimpleContext(std::move(body))); }
51
52 std::unique_ptr<Reader> obtainReader(Client* client) override
53 {
54 // For memory barrier.
55 Mutex m;
56 MutexLocker locker(m);
57 return ReaderImpl::create(this, client);
58 }
59
60 PassRefPtr<BlobDataHandle> drainAsBlobDataHandle()
61 {
62 if (!m_formData)
63 return nullptr;
64 flatten();
65 std::unique_ptr<BlobData> blobData = BlobData::create();
66 blobData->appendBytes(m_flattenFormData.data(), m_flattenFormData.size() );
67 m_flattenFormData.clear();
68 auto length = blobData->length();
69 return BlobDataHandle::create(std::move(blobData), length);
70 }
71
72 PassRefPtr<EncodedFormData> drainFormData()
73 {
74 ASSERT(!m_formData || m_formData->isSafeToSendToAnotherThread());
75 return m_formData.release();
76 }
77
78 Result read(void* data, size_t size, Flags flags, size_t* readSize)
79 {
80 *readSize = 0;
81 if (size == 0 && m_formData)
82 return WebDataConsumerHandle::Ok;
83
84 flatten();
85 RELEASE_ASSERT(m_flattenFormDataOffset <= m_flattenFormData.size());
86
87 *readSize = std::min(size, m_flattenFormData.size() - m_flattenFormDataO ffset);
88 if (*readSize == 0)
89 return WebDataConsumerHandle::Done;
90 memcpy(data, &m_flattenFormData[m_flattenFormDataOffset], *readSize);
91 m_flattenFormDataOffset += *readSize;
92 RELEASE_ASSERT(m_flattenFormDataOffset <= m_flattenFormData.size());
93
94 return WebDataConsumerHandle::Ok;
95 }
96
97 Result beginRead(const void** buffer, Flags flags, size_t* available)
98 {
99 *buffer = nullptr;
100 *available = 0;
101
102 flatten();
103 RELEASE_ASSERT(m_flattenFormDataOffset <= m_flattenFormData.size());
104
105 if (m_flattenFormData.size() == m_flattenFormDataOffset)
106 return WebDataConsumerHandle::Done;
107 *buffer = &m_flattenFormData[m_flattenFormDataOffset];
108 *available = m_flattenFormData.size() - m_flattenFormDataOffset;
109 return WebDataConsumerHandle::Ok;
110 }
111
112 Result endRead(size_t read)
113 {
114 RELEASE_ASSERT(m_flattenFormDataOffset <= m_flattenFormData.size());
115 RELEASE_ASSERT(read <= m_flattenFormData.size() - m_flattenFormDataOffse t);
116 m_flattenFormDataOffset += read;
117
118 return WebDataConsumerHandle::Ok;
119 }
120
121 private:
122 class ReaderImpl final : public FetchDataConsumerHandle::Reader {
123 WTF_MAKE_NONCOPYABLE(ReaderImpl);
124 public:
125 static std::unique_ptr<ReaderImpl> create(PassRefPtr<SimpleContext> cont ext, Client* client) { return wrapUnique(new ReaderImpl(std::move(context), clie nt)); }
126 Result read(void* data, size_t size, Flags flags, size_t* readSize) over ride
127 {
128 return m_context->read(data, size, flags, readSize);
129 }
130 Result beginRead(const void** buffer, Flags flags, size_t* available) ov erride
131 {
132 return m_context->beginRead(buffer, flags, available);
133 }
134 Result endRead(size_t read) override
135 {
136 return m_context->endRead(read);
137 }
138 PassRefPtr<BlobDataHandle> drainAsBlobDataHandle(BlobSizePolicy) overrid e
139 {
140 // A "simple" FormData always has a finite known size.
141 return m_context->drainAsBlobDataHandle();
142 }
143 PassRefPtr<EncodedFormData> drainAsFormData() override
144 {
145 return m_context->drainFormData();
146 }
147
148 private:
149 ReaderImpl(PassRefPtr<SimpleContext> context, Client* client) : m_contex t(context), m_notifier(client) {}
150
151 RefPtr<SimpleContext> m_context;
152 NotifyOnReaderCreationHelper m_notifier;
153 };
154
155 explicit SimpleContext(const String& body)
156 : m_formData(EncodedFormData::create(UTF8Encoding().encode(body, WTF::En titiesForUnencodables)))
157 , m_flattenFormDataOffset(0) {}
158 SimpleContext(const void* data, size_t size) : m_formData(EncodedFormData::c reate(data, size)) , m_flattenFormDataOffset(0) {}
159 explicit SimpleContext(PassRefPtr<EncodedFormData> body) : m_formData(body-> deepCopy()) , m_flattenFormDataOffset(0) {}
160
161 void flatten()
162 {
163 if (!m_formData) {
164 // It is already drained or flatten.
165 return;
166 }
167 ASSERT(m_formData->isSafeToSendToAnotherThread());
168 m_formData->flatten(m_flattenFormData);
169 m_formData = nullptr;
170 }
171
172 // either one of |m_formData| and |m_flattenFormData| is usable at a time.
173 RefPtr<EncodedFormData> m_formData;
174 Vector<char> m_flattenFormData;
175 size_t m_flattenFormDataOffset;
176 };
177
178 class FetchFormDataConsumerHandle::ComplexContext final : public Context {
179 class ReaderImpl;
180 public:
181 static PassRefPtr<ComplexContext> create(ExecutionContext* executionContext,
182 PassRefPtr<EncodedFormData> formData,
183 FetchBlobDataConsumerHandle::LoaderFactory* factory)
184 {
185 return adoptRef(new ComplexContext(executionContext, std::move(formData) , factory));
186 }
187
188 std::unique_ptr<FetchFormDataConsumerHandle::Reader> obtainReader(Client* cl ient) override
189 {
190 // For memory barrier.
191 Mutex m;
192 MutexLocker locker(m);
193 return ReaderImpl::create(this, client);
194 }
195
196 private:
197 class ReaderImpl final : public FetchDataConsumerHandle::Reader {
198 WTF_MAKE_NONCOPYABLE(ReaderImpl);
199 public:
200 static std::unique_ptr<ReaderImpl> create(PassRefPtr<ComplexContext> con text, Client* client) { return wrapUnique(new ReaderImpl(std::move(context), cli ent)); }
201 Result read(void* data, size_t size, Flags flags, size_t* readSize) over ride
202 {
203 Result r = m_reader->read(data, size, flags, readSize);
204 if (!(size == 0 && (r == Ok || r == ShouldWait))) {
205 m_context->drainFormData();
206 }
207 return r;
208 }
209 Result beginRead(const void** buffer, Flags flags, size_t* available) ov erride
210 {
211 m_context->drainFormData();
212 return m_reader->beginRead(buffer, flags, available);
213 }
214 Result endRead(size_t read) override
215 {
216 return m_reader->endRead(read);
217 }
218 PassRefPtr<BlobDataHandle> drainAsBlobDataHandle(BlobSizePolicy policy) override
219 {
220 RefPtr<BlobDataHandle> handle = m_reader->drainAsBlobDataHandle(poli cy);
221 if (handle) {
222 m_context->drainFormData();
223 }
224 return handle.release();
225 }
226 PassRefPtr<EncodedFormData> drainAsFormData() override
227 {
228 RefPtr<EncodedFormData> formData = m_context->drainFormData();
229 if (formData) {
230 // Drain blob from the underlying handle to mark data as read.
231 RefPtr<BlobDataHandle> handle = m_reader->drainAsBlobDataHandle( AllowBlobWithInvalidSize);
232 // Here we assume we can always get the valid handle. That is
233 // in fact not specified at FetchDataConsumerHandle level, but
234 // |m_context->m_handle| is a FetchBlobDataConsumerHandle.
235 ASSERT(handle);
236 }
237 return formData.release();
238 }
239 private:
240 ReaderImpl(PassRefPtr<ComplexContext> context, Client* client) : m_conte xt(context), m_reader(m_context->m_handle->obtainFetchDataReader(client)) {}
241
242 RefPtr<ComplexContext> m_context;
243 std::unique_ptr<FetchDataConsumerHandle::Reader> m_reader;
244 };
245
246 ComplexContext(ExecutionContext* executionContext, PassRefPtr<EncodedFormDat a> body, FetchBlobDataConsumerHandle::LoaderFactory* factory)
247 {
248 std::unique_ptr<BlobData> blobData = BlobData::create();
249 for (const auto& element : body->elements()) {
250 switch (element.m_type) {
251 case FormDataElement::data:
252 blobData->appendBytes(element.m_data.data(), element.m_data.size ());
253 break;
254 case FormDataElement::encodedFile:
255 blobData->appendFile(element.m_filename, element.m_fileStart, el ement.m_fileLength, element.m_expectedFileModificationTime);
256 break;
257 case FormDataElement::encodedBlob:
258 if (element.m_optionalBlobDataHandle)
259 blobData->appendBlob(element.m_optionalBlobDataHandle, 0, el ement.m_optionalBlobDataHandle->size());
260 break;
261 case FormDataElement::encodedFileSystemURL:
262 blobData->appendFileSystemURL(element.m_fileSystemURL, element.m _fileStart, element.m_fileLength, element.m_expectedFileModificationTime);
263 break;
264 }
265 }
266 // Here we handle body->boundary() as a C-style string. See
267 // FormDataEncoder::generateUniqueBoundaryString.
268 blobData->setContentType(AtomicString("multipart/form-data; boundary=") + body->boundary().data());
269 auto size = blobData->length();
270 if (factory) {
271 // For testing
272 m_handle = FetchBlobDataConsumerHandle::create(executionContext, Blo bDataHandle::create(std::move(blobData), size), factory);
273 } else {
274 m_handle = FetchBlobDataConsumerHandle::create(executionContext, Blo bDataHandle::create(std::move(blobData), size));
275 }
276 // It is important to initialize |m_formData| here, because even
277 // read-only operations may make the form data unsharable with implicit
278 // ref-counting.
279 m_formData = body->deepCopy();
280 }
281 PassRefPtr<EncodedFormData> drainFormData()
282 {
283 ASSERT(!m_formData || m_formData->isSafeToSendToAnotherThread());
284 return m_formData.release();
285 }
286
287 RefPtr<EncodedFormData> m_formData;
288 std::unique_ptr<FetchDataConsumerHandle> m_handle;
289 };
290
291 std::unique_ptr<FetchDataConsumerHandle> FetchFormDataConsumerHandle::create(con st String& body)
292 {
293 return wrapUnique(new FetchFormDataConsumerHandle(body));
294 }
295 std::unique_ptr<FetchDataConsumerHandle> FetchFormDataConsumerHandle::create(DOM ArrayBuffer* body)
296 {
297 return wrapUnique(new FetchFormDataConsumerHandle(body->data(), body->byteLe ngth()));
298 }
299 std::unique_ptr<FetchDataConsumerHandle> FetchFormDataConsumerHandle::create(DOM ArrayBufferView* body)
300 {
301 return wrapUnique(new FetchFormDataConsumerHandle(body->baseAddress(), body- >byteLength()));
302 }
303 std::unique_ptr<FetchDataConsumerHandle> FetchFormDataConsumerHandle::create(con st void* data, size_t size)
304 {
305 return wrapUnique(new FetchFormDataConsumerHandle(data, size));
306 }
307 std::unique_ptr<FetchDataConsumerHandle> FetchFormDataConsumerHandle::create(Exe cutionContext* executionContext, PassRefPtr<EncodedFormData> body)
308 {
309 return wrapUnique(new FetchFormDataConsumerHandle(executionContext, std::mov e(body)));
310 }
311 std::unique_ptr<FetchDataConsumerHandle> FetchFormDataConsumerHandle::createForT est(
312 ExecutionContext* executionContext,
313 PassRefPtr<EncodedFormData> body,
314 FetchBlobDataConsumerHandle::LoaderFactory* loaderFactory)
315 {
316 return wrapUnique(new FetchFormDataConsumerHandle(executionContext, std::mov e(body), loaderFactory));
317 }
318
319 FetchFormDataConsumerHandle::FetchFormDataConsumerHandle(const String& body) : m _context(SimpleContext::create(body)) {}
320 FetchFormDataConsumerHandle::FetchFormDataConsumerHandle(const void* data, size_ t size) : m_context(SimpleContext::create(data, size)) {}
321 FetchFormDataConsumerHandle::FetchFormDataConsumerHandle(ExecutionContext* execu tionContext,
322 PassRefPtr<EncodedFormData> body,
323 FetchBlobDataConsumerHandle::LoaderFactory* loaderFactory)
324 {
325 if (isSimple(body.get())) {
326 m_context = SimpleContext::create(std::move(body));
327 } else {
328 m_context = ComplexContext::create(executionContext, std::move(body), lo aderFactory);
329 }
330 }
331 FetchFormDataConsumerHandle::~FetchFormDataConsumerHandle() {}
332
333 std::unique_ptr<FetchDataConsumerHandle::Reader> FetchFormDataConsumerHandle::ob tainFetchDataReader(Client* client)
334 {
335 return m_context->obtainReader(client);
336 }
337
338 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698