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

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

Issue 1265413002: Introduce FetchFormDataConsumerHandle. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 years, 4 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 | Annotate | Revision Log
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 "config.h"
6 #include "modules/fetch/FetchFormDataConsumerHandle.h"
7
8 #include "core/dom/DOMArrayBuffer.h"
9 #include "modules/fetch/DataConsumerHandleUtil.h"
10 #include "modules/fetch/FetchBlobDataConsumerHandle.h"
11 #include "platform/network/FormData.h"
12 #include "wtf/ThreadSafeRefCounted.h"
13 #include "wtf/ThreadingPrimitives.h"
14 #include "wtf/Vector.h"
15 #include "wtf/text/TextCodec.h"
16 #include "wtf/text/TextEncoding.h"
17 #include "wtf/text/WTFString.h"
18
19 #include <utility>
20
21 namespace blink {
22
23 using Result = FetchDataConsumerHandle::Result;
24
25 class FetchFormDataConsumerHandle::Context final : public ThreadSafeRefCounted<C ontext> {
26 WTF_MAKE_NONCOPYABLE(Context);
27 public:
28 static PassRefPtr<Context> create(const String& body) { return adoptRef(new Context(body)); }
29 static PassRefPtr<Context> create(PassRefPtr<DOMArrayBuffer> body) { return adoptRef(new Context(body)); }
30 static PassRefPtr<Context> create(ExecutionContext* executionContext, PassRe fPtr<FormData> body, FetchBlobDataConsumerHandle::LoaderFactory* factory)
31 {
32 return adoptRef(new Context(executionContext, body, factory));
33 }
34
35 void obtainReader(Client* client)
36 {
37 if (m_handleForComplexFormData) {
hiroshige 2015/08/10 13:27:03 Switching by |m_handleForComplexFormData| seems co
yhirano 2015/08/11 06:08:43 I split Context into SimpleContext and ComplexCont
38 m_readerForComplexFormData = m_handleForComplexFormData->obtainReade r(client);
39 }
40 }
41
42 void releaseReader()
43 {
44 m_readerForComplexFormData = nullptr;
45 }
46
47 Result read(void* data, size_t size, Flags flags, size_t* readSize)
48 {
49 if (m_readerForComplexFormData) {
50 Result r = m_readerForComplexFormData->read(data, size, flags, readS ize);
51 if (!((r == WebDataConsumerHandle::Ok && *readSize == 0) || r == Web DataConsumerHandle::ShouldWait)) {
52 // Something is read, so the form data should be disposed.
53 m_formData = nullptr;
54 }
55 return r;
56 }
57
58 *readSize = 0;
59 if (size == 0) {
60 if (!m_formData && m_flattenFormData.size() == m_flattenFormDataOffs et)
61 return WebDataConsumerHandle::Done;
62 return WebDataConsumerHandle::Ok;
63 }
64 flatten();
65
66 *readSize = std::min(size, m_flattenFormData.size() - m_flattenFormDataO ffset);
67 if (*readSize == 0)
68 return WebDataConsumerHandle::Done;
69 memcpy(data, &m_flattenFormData[m_flattenFormDataOffset], *readSize);
70 m_flattenFormDataOffset += *readSize;
71 return WebDataConsumerHandle::Ok;
72 }
73
74 Result beginRead(const void** buffer, Flags flags, size_t* available)
75 {
76 if (m_readerForComplexFormData) {
77 Result r = m_readerForComplexFormData->beginRead(buffer, flags, avai lable);
78 if (r != WebDataConsumerHandle::ShouldWait) {
79 // Something is read, so the form data should be disposed.
80 m_formData = nullptr;
81 }
82 return r;
83 }
84
85 *buffer = nullptr;
86 *available = 0;
87
88 flatten();
89 if (m_flattenFormData.size() == m_flattenFormDataOffset)
90 return WebDataConsumerHandle::Done;
91 *buffer = &m_flattenFormData[m_flattenFormDataOffset];
92 *available = m_flattenFormData.size() - m_flattenFormDataOffset;
93 return WebDataConsumerHandle::Ok;
94 }
95
96 Result endRead(size_t read)
97 {
98 if (m_readerForComplexFormData)
99 return m_readerForComplexFormData->endRead(read);
100
101 m_flattenFormDataOffset += read;
102 return WebDataConsumerHandle::Ok;
103 }
104
105 PassRefPtr<FormData> drainFormData()
106 {
107 if (!m_formData)
108 return nullptr;
109
110 ASSERT(m_formData->hasOneRef());
111 if (m_readerForComplexFormData) {
112 // Note that m_formData must be null in a two-phase read and hence
113 // we can release the reader here.
114 m_readerForComplexFormData = nullptr;
115 m_handleForComplexFormData = nullptr;
116 }
117 ASSERT(!m_handleForComplexFormData);
118 return m_formData.release();
119 }
120
121 private:
122 explicit Context(const String& body)
123 : m_formData(FormData::create(UTF8Encoding().encode(body, WTF::EntitiesF orUnencodables)))
124 , m_flattenFormDataOffset(0) {}
125 explicit Context(PassRefPtr<DOMArrayBuffer> body)
126 : m_formData(FormData::create(body->data(), body->byteLength()))
127 , m_flattenFormDataOffset(0) {}
128 explicit Context(ExecutionContext* executionContext, PassRefPtr<FormData> bo dy, FetchBlobDataConsumerHandle::LoaderFactory* factory)
129 : m_formData(body->deepCopy())
130 , m_flattenFormDataOffset(0)
131 {
132 for (const auto& element : m_formData->elements()) {
133 if (element.m_type != FormDataElement::data) {
134 // Non data type is found, so we need to use
135 // FetchBlobDataConsumerHandle.
136 createDataConsumerHandleForComplexFormData(executionContext, fac tory);
137 break;
138 }
139 }
140 }
141
142 void createDataConsumerHandleForComplexFormData(ExecutionContext* executionC ontext, FetchBlobDataConsumerHandle::LoaderFactory* factory)
143 {
144 OwnPtr<BlobData> blobData = BlobData::create();
145 for (const auto& element : m_formData->elements()) {
146 switch (element.m_type) {
147 case FormDataElement::data: {
hiroshige 2015/08/10 13:27:03 nit: can we remove "{" here and "}" in L150?
yhirano 2015/08/11 06:08:43 Done.
148 blobData->appendBytes(element.m_data.data(), element.m_data.size ());
149 break;
150 }
151 case FormDataElement::encodedFile:
152 blobData->appendFile(element.m_filename, element.m_fileStart, el ement.m_fileLength, element.m_expectedFileModificationTime);
153 break;
154 case FormDataElement::encodedBlob:
155 if (element.m_optionalBlobDataHandle)
156 blobData->appendBlob(element.m_optionalBlobDataHandle, 0, el ement.m_optionalBlobDataHandle->size());
157 break;
158 case FormDataElement::encodedFileSystemURL:
159 blobData->appendFileSystemURL(element.m_fileSystemURL, element.m _fileStart, element.m_fileLength, element.m_expectedFileModificationTime);
160 break;
161 }
162 }
163 blobData->setContentType("multipart/form-data; boundary=" + String(m_for mData->boundary().data(), m_formData->boundary().size()));
164 auto size = blobData->length();
165 if (factory) {
166 // For testing
167 m_handleForComplexFormData = FetchBlobDataConsumerHandle::create(exe cutionContext, BlobDataHandle::create(blobData.release(), size), factory);
168 } else {
169 m_handleForComplexFormData = FetchBlobDataConsumerHandle::create(exe cutionContext, BlobDataHandle::create(blobData.release(), size));
170 }
171 }
172
173 void flatten()
174 {
175 ASSERT(!m_handleForComplexFormData);
176 if (!m_formData) {
177 // It's already flatten or drained.
178 return;
179 }
180 m_formData->flatten(m_flattenFormData);
181 m_formData = nullptr;
182 }
183
184 // Note this data is not shared by anyone and hence it is safe to pass
185 // around the data between threads.
186 RefPtr<FormData> m_formData;
187 Vector<char> m_flattenFormData;
188 size_t m_flattenFormDataOffset;
189 OwnPtr<WebDataConsumerHandle> m_handleForComplexFormData;
190 OwnPtr<WebDataConsumerHandle::Reader> m_readerForComplexFormData;
191 };
192
193 class FetchFormDataConsumerHandle::ReaderImpl final : public FetchDataConsumerHa ndle::Reader {
194 WTF_MAKE_NONCOPYABLE(ReaderImpl);
195 public:
196 ReaderImpl(PassRefPtr<Context> context, Client* client)
197 : m_context(context)
198 , m_notifier(client)
199 {
200 // For memory barrier.
201 Mutex m;
202 MutexLocker locker(m);
203 m_context->obtainReader(client);
204 }
205 ~ReaderImpl() override
206 {
207 // For memory barrier.
208 Mutex m;
209 MutexLocker locker(m);
210 m_context->releaseReader();
211 }
212
213 Result read(void* data, size_t size, Flags flags, size_t* readSize) override
214 {
215 return m_context->read(data, size, flags, readSize);
216 }
217 Result beginRead(const void** buffer, Flags flags, size_t* available) overri de
218 {
219 return m_context->beginRead(buffer, flags, available);
220 }
221 Result endRead(size_t read) override
222 {
223 return m_context->endRead(read);
224 }
225 PassRefPtr<FormData> drainAsFormData() override
226 {
227 return m_context->drainFormData();
228 }
229
230 private:
231 RefPtr<Context> m_context;
232 NotifyOnReaderCreationHelper m_notifier;
233 };
234
235 FetchFormDataConsumerHandle::FetchFormDataConsumerHandle(const String& body) : m _context(Context::create(body)) {}
236 FetchFormDataConsumerHandle::FetchFormDataConsumerHandle(PassRefPtr<DOMArrayBuff er> body) : m_context(Context::create(body)) {}
237 FetchFormDataConsumerHandle::FetchFormDataConsumerHandle(ExecutionContext* execu tionContext,
238 PassRefPtr<FormData> body,
239 FetchBlobDataConsumerHandle::LoaderFactory* loaderFactory)
240 : m_context(Context::create(executionContext, body, loaderFactory))
241 {
242 }
243 FetchFormDataConsumerHandle::~FetchFormDataConsumerHandle() {}
244
245 FetchDataConsumerHandle::Reader* FetchFormDataConsumerHandle::obtainReaderIntern al(Client* client)
246 {
247 return new ReaderImpl(m_context, client);
248 }
249
250 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698