OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 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 "config.h" | 5 #include "config.h" |
6 #include "modules/fetch/FetchFormDataConsumerHandle.h" | 6 #include "modules/fetch/FetchFormDataConsumerHandle.h" |
7 | 7 |
8 #include "modules/fetch/DataConsumerHandleUtil.h" | 8 #include "modules/fetch/DataConsumerHandleUtil.h" |
9 #include "modules/fetch/FetchBlobDataConsumerHandle.h" | 9 #include "modules/fetch/FetchBlobDataConsumerHandle.h" |
10 #include "wtf/ThreadSafeRefCounted.h" | 10 #include "wtf/ThreadSafeRefCounted.h" |
11 #include "wtf/ThreadingPrimitives.h" | 11 #include "wtf/ThreadingPrimitives.h" |
12 #include "wtf/Vector.h" | 12 #include "wtf/Vector.h" |
13 #include "wtf/text/TextCodec.h" | 13 #include "wtf/text/TextCodec.h" |
14 #include "wtf/text/TextEncoding.h" | 14 #include "wtf/text/TextEncoding.h" |
15 #include "wtf/text/WTFString.h" | 15 #include "wtf/text/WTFString.h" |
16 | 16 |
17 #include <utility> | 17 #include <utility> |
18 | 18 |
19 namespace blink { | 19 namespace blink { |
20 | 20 |
21 using Result = FetchDataConsumerHandle::Result; | 21 using Result = FetchDataConsumerHandle::Result; |
22 | 22 |
23 namespace { | 23 namespace { |
24 | 24 |
25 bool isSimple(const FormData* formData) | 25 bool isSimple(const EncodedFormData* formData) |
26 { | 26 { |
27 for (const auto& element : formData->elements()) { | 27 for (const auto& element : formData->elements()) { |
28 if (element.m_type != FormDataElement::data) | 28 if (element.m_type != FormDataElement::data) |
29 return false; | 29 return false; |
30 } | 30 } |
31 return true; | 31 return true; |
32 } | 32 } |
33 | 33 |
34 } // namespace | 34 } // namespace |
35 | 35 |
36 class FetchFormDataConsumerHandle::Context : public ThreadSafeRefCounted<Context
> { | 36 class FetchFormDataConsumerHandle::Context : public ThreadSafeRefCounted<Context
> { |
37 WTF_MAKE_NONCOPYABLE(Context); | 37 WTF_MAKE_NONCOPYABLE(Context); |
38 public: | 38 public: |
39 virtual ~Context() {} | 39 virtual ~Context() {} |
40 virtual PassOwnPtr<FetchDataConsumerHandle::Reader> obtainReader(Client*) =
0; | 40 virtual PassOwnPtr<FetchDataConsumerHandle::Reader> obtainReader(Client*) =
0; |
41 | 41 |
42 protected: | 42 protected: |
43 explicit Context() {} | 43 explicit Context() {} |
44 }; | 44 }; |
45 | 45 |
46 class FetchFormDataConsumerHandle::SimpleContext final : public Context { | 46 class FetchFormDataConsumerHandle::SimpleContext final : public Context { |
47 class ReaderImpl; | 47 class ReaderImpl; |
48 public: | 48 public: |
49 static PassRefPtr<SimpleContext> create(const String& body) { return adoptRe
f(new SimpleContext(body)); } | 49 static PassRefPtr<SimpleContext> create(const String& body) { return adoptRe
f(new SimpleContext(body)); } |
50 static PassRefPtr<SimpleContext> create(const void* data, size_t size) { ret
urn adoptRef(new SimpleContext(data, size)); } | 50 static PassRefPtr<SimpleContext> create(const void* data, size_t size) { ret
urn adoptRef(new SimpleContext(data, size)); } |
51 static PassRefPtr<SimpleContext> create(PassRefPtr<FormData> body) { return
adoptRef(new SimpleContext(body)); } | 51 static PassRefPtr<SimpleContext> create(PassRefPtr<EncodedFormData> body) {
return adoptRef(new SimpleContext(body)); } |
52 | 52 |
53 PassOwnPtr<Reader> obtainReader(Client* client) override | 53 PassOwnPtr<Reader> obtainReader(Client* client) override |
54 { | 54 { |
55 // For memory barrier. | 55 // For memory barrier. |
56 Mutex m; | 56 Mutex m; |
57 MutexLocker locker(m); | 57 MutexLocker locker(m); |
58 return ReaderImpl::create(this, client); | 58 return ReaderImpl::create(this, client); |
59 } | 59 } |
60 | 60 |
61 PassRefPtr<FormData> drainFormData() | 61 PassRefPtr<EncodedFormData> drainFormData() |
62 { | 62 { |
63 ASSERT(!m_formData || m_formData->isSafeToSendToAnotherThread()); | 63 ASSERT(!m_formData || m_formData->isSafeToSendToAnotherThread()); |
64 return m_formData.release(); | 64 return m_formData.release(); |
65 } | 65 } |
66 | 66 |
67 Result read(void* data, size_t size, Flags flags, size_t* readSize) | 67 Result read(void* data, size_t size, Flags flags, size_t* readSize) |
68 { | 68 { |
69 *readSize = 0; | 69 *readSize = 0; |
70 if (size == 0 && m_formData) | 70 if (size == 0 && m_formData) |
71 return WebDataConsumerHandle::Ok; | 71 return WebDataConsumerHandle::Ok; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 return m_context->read(data, size, flags, readSize); | 117 return m_context->read(data, size, flags, readSize); |
118 } | 118 } |
119 Result beginRead(const void** buffer, Flags flags, size_t* available) ov
erride | 119 Result beginRead(const void** buffer, Flags flags, size_t* available) ov
erride |
120 { | 120 { |
121 return m_context->beginRead(buffer, flags, available); | 121 return m_context->beginRead(buffer, flags, available); |
122 } | 122 } |
123 Result endRead(size_t read) override | 123 Result endRead(size_t read) override |
124 { | 124 { |
125 return m_context->endRead(read); | 125 return m_context->endRead(read); |
126 } | 126 } |
127 PassRefPtr<FormData> drainAsFormData() override | 127 PassRefPtr<EncodedFormData> drainAsFormData() override |
128 { | 128 { |
129 return m_context->drainFormData(); | 129 return m_context->drainFormData(); |
130 } | 130 } |
131 | 131 |
132 private: | 132 private: |
133 ReaderImpl(PassRefPtr<SimpleContext> context, Client* client) : m_contex
t(context), m_notifier(client) {} | 133 ReaderImpl(PassRefPtr<SimpleContext> context, Client* client) : m_contex
t(context), m_notifier(client) {} |
134 | 134 |
135 RefPtr<SimpleContext> m_context; | 135 RefPtr<SimpleContext> m_context; |
136 NotifyOnReaderCreationHelper m_notifier; | 136 NotifyOnReaderCreationHelper m_notifier; |
137 }; | 137 }; |
138 | 138 |
139 explicit SimpleContext(const String& body) | 139 explicit SimpleContext(const String& body) |
140 : m_formData(FormData::create(UTF8Encoding().encode(body, WTF::EntitiesF
orUnencodables))) | 140 : m_formData(EncodedFormData::create(UTF8Encoding().encode(body, WTF::En
titiesForUnencodables))) |
141 , m_flattenFormDataOffset(0) {} | 141 , m_flattenFormDataOffset(0) {} |
142 explicit SimpleContext(const void* data, size_t size) : m_formData(FormData:
:create(data, size)) , m_flattenFormDataOffset(0) {} | 142 SimpleContext(const void* data, size_t size) : m_formData(EncodedFormData::c
reate(data, size)) , m_flattenFormDataOffset(0) {} |
143 explicit SimpleContext(PassRefPtr<FormData> body) : m_formData(body->deepCop
y()) , m_flattenFormDataOffset(0) {} | 143 explicit SimpleContext(PassRefPtr<EncodedFormData> body) : m_formData(body->
deepCopy()) , m_flattenFormDataOffset(0) {} |
144 | 144 |
145 void flatten() | 145 void flatten() |
146 { | 146 { |
147 if (!m_formData) { | 147 if (!m_formData) { |
148 // It is already drained or flatten. | 148 // It is already drained or flatten. |
149 return; | 149 return; |
150 } | 150 } |
151 ASSERT(m_formData->isSafeToSendToAnotherThread()); | 151 ASSERT(m_formData->isSafeToSendToAnotherThread()); |
152 m_formData->flatten(m_flattenFormData); | 152 m_formData->flatten(m_flattenFormData); |
153 m_formData = nullptr; | 153 m_formData = nullptr; |
154 } | 154 } |
155 | 155 |
156 // either one of |m_formData| and |m_flattenFormData| is usable at a time. | 156 // either one of |m_formData| and |m_flattenFormData| is usable at a time. |
157 RefPtr<FormData> m_formData; | 157 RefPtr<EncodedFormData> m_formData; |
158 Vector<char> m_flattenFormData; | 158 Vector<char> m_flattenFormData; |
159 size_t m_flattenFormDataOffset; | 159 size_t m_flattenFormDataOffset; |
160 }; | 160 }; |
161 | 161 |
162 class FetchFormDataConsumerHandle::ComplexContext final : public Context { | 162 class FetchFormDataConsumerHandle::ComplexContext final : public Context { |
163 class ReaderImpl; | 163 class ReaderImpl; |
164 public: | 164 public: |
165 static PassRefPtr<ComplexContext> create(ExecutionContext* executionContext, | 165 static PassRefPtr<ComplexContext> create(ExecutionContext* executionContext, |
166 PassRefPtr<FormData> formData, | 166 PassRefPtr<EncodedFormData> formData, |
167 FetchBlobDataConsumerHandle::LoaderFactory* factory) | 167 FetchBlobDataConsumerHandle::LoaderFactory* factory) |
168 { | 168 { |
169 return adoptRef(new ComplexContext(executionContext, formData, factory))
; | 169 return adoptRef(new ComplexContext(executionContext, formData, factory))
; |
170 } | 170 } |
171 | 171 |
172 PassOwnPtr<FetchFormDataConsumerHandle::Reader> obtainReader(Client* client)
override | 172 PassOwnPtr<FetchFormDataConsumerHandle::Reader> obtainReader(Client* client)
override |
173 { | 173 { |
174 // For memory barrier. | 174 // For memory barrier. |
175 Mutex m; | 175 Mutex m; |
176 MutexLocker locker(m); | 176 MutexLocker locker(m); |
(...skipping 23 matching lines...) Expand all Loading... |
200 return m_reader->endRead(read); | 200 return m_reader->endRead(read); |
201 } | 201 } |
202 PassRefPtr<BlobDataHandle> drainAsBlobDataHandle(BlobSizePolicy policy)
override | 202 PassRefPtr<BlobDataHandle> drainAsBlobDataHandle(BlobSizePolicy policy)
override |
203 { | 203 { |
204 RefPtr<BlobDataHandle> handle = m_reader->drainAsBlobDataHandle(poli
cy); | 204 RefPtr<BlobDataHandle> handle = m_reader->drainAsBlobDataHandle(poli
cy); |
205 if (handle) { | 205 if (handle) { |
206 m_context->drainFormData(); | 206 m_context->drainFormData(); |
207 } | 207 } |
208 return handle.release(); | 208 return handle.release(); |
209 } | 209 } |
210 PassRefPtr<FormData> drainAsFormData() override | 210 PassRefPtr<EncodedFormData> drainAsFormData() override |
211 { | 211 { |
212 RefPtr<FormData> formData = m_context->drainFormData(); | 212 RefPtr<EncodedFormData> formData = m_context->drainFormData(); |
213 if (formData) { | 213 if (formData) { |
214 // Drain blob from the underlying handle to mark data as read. | 214 // Drain blob from the underlying handle to mark data as read. |
215 RefPtr<BlobDataHandle> handle = m_reader->drainAsBlobDataHandle(
AllowBlobWithInvalidSize); | 215 RefPtr<BlobDataHandle> handle = m_reader->drainAsBlobDataHandle(
AllowBlobWithInvalidSize); |
216 // Here we assume we can always get the valid handle. That is | 216 // Here we assume we can always get the valid handle. That is |
217 // in fact not specified at FetchDataConsumerHandle level, but | 217 // in fact not specified at FetchDataConsumerHandle level, but |
218 // |m_context->m_handle| is a FetchBlobDataConsumerHandle. | 218 // |m_context->m_handle| is a FetchBlobDataConsumerHandle. |
219 ASSERT(handle); | 219 ASSERT(handle); |
220 } | 220 } |
221 return formData.release(); | 221 return formData.release(); |
222 } | 222 } |
223 private: | 223 private: |
224 ReaderImpl(PassRefPtr<ComplexContext> context, Client* client) : m_conte
xt(context), m_reader(m_context->m_handle->obtainReader(client)) {} | 224 ReaderImpl(PassRefPtr<ComplexContext> context, Client* client) : m_conte
xt(context), m_reader(m_context->m_handle->obtainReader(client)) {} |
225 | 225 |
226 RefPtr<ComplexContext> m_context; | 226 RefPtr<ComplexContext> m_context; |
227 OwnPtr<FetchDataConsumerHandle::Reader> m_reader; | 227 OwnPtr<FetchDataConsumerHandle::Reader> m_reader; |
228 }; | 228 }; |
229 | 229 |
230 explicit ComplexContext(ExecutionContext* executionContext, PassRefPtr<FormD
ata> body, FetchBlobDataConsumerHandle::LoaderFactory* factory) | 230 ComplexContext(ExecutionContext* executionContext, PassRefPtr<EncodedFormDat
a> body, FetchBlobDataConsumerHandle::LoaderFactory* factory) |
231 { | 231 { |
232 OwnPtr<BlobData> blobData = BlobData::create(); | 232 OwnPtr<BlobData> blobData = BlobData::create(); |
233 for (const auto& element : body->elements()) { | 233 for (const auto& element : body->elements()) { |
234 switch (element.m_type) { | 234 switch (element.m_type) { |
235 case FormDataElement::data: | 235 case FormDataElement::data: |
236 blobData->appendBytes(element.m_data.data(), element.m_data.size
()); | 236 blobData->appendBytes(element.m_data.data(), element.m_data.size
()); |
237 break; | 237 break; |
238 case FormDataElement::encodedFile: | 238 case FormDataElement::encodedFile: |
239 blobData->appendFile(element.m_filename, element.m_fileStart, el
ement.m_fileLength, element.m_expectedFileModificationTime); | 239 blobData->appendFile(element.m_filename, element.m_fileStart, el
ement.m_fileLength, element.m_expectedFileModificationTime); |
240 break; | 240 break; |
241 case FormDataElement::encodedBlob: | 241 case FormDataElement::encodedBlob: |
242 if (element.m_optionalBlobDataHandle) | 242 if (element.m_optionalBlobDataHandle) |
243 blobData->appendBlob(element.m_optionalBlobDataHandle, 0, el
ement.m_optionalBlobDataHandle->size()); | 243 blobData->appendBlob(element.m_optionalBlobDataHandle, 0, el
ement.m_optionalBlobDataHandle->size()); |
244 break; | 244 break; |
245 case FormDataElement::encodedFileSystemURL: | 245 case FormDataElement::encodedFileSystemURL: |
246 blobData->appendFileSystemURL(element.m_fileSystemURL, element.m
_fileStart, element.m_fileLength, element.m_expectedFileModificationTime); | 246 blobData->appendFileSystemURL(element.m_fileSystemURL, element.m
_fileStart, element.m_fileLength, element.m_expectedFileModificationTime); |
247 break; | 247 break; |
248 } | 248 } |
249 } | 249 } |
250 // Here we handle body->boundary() as a C-style string. See | 250 // Here we handle body->boundary() as a C-style string. See |
251 // FormDataBuilder::generateUniqueBoundaryString. | 251 // FormDataEncoder::generateUniqueBoundaryString. |
252 blobData->setContentType(AtomicString("multipart/form-data; boundary=",
AtomicString::ConstructFromLiteral) + body->boundary().data()); | 252 blobData->setContentType(AtomicString("multipart/form-data; boundary=",
AtomicString::ConstructFromLiteral) + body->boundary().data()); |
253 auto size = blobData->length(); | 253 auto size = blobData->length(); |
254 if (factory) { | 254 if (factory) { |
255 // For testing | 255 // For testing |
256 m_handle = FetchBlobDataConsumerHandle::create(executionContext, Blo
bDataHandle::create(blobData.release(), size), factory); | 256 m_handle = FetchBlobDataConsumerHandle::create(executionContext, Blo
bDataHandle::create(blobData.release(), size), factory); |
257 } else { | 257 } else { |
258 m_handle = FetchBlobDataConsumerHandle::create(executionContext, Blo
bDataHandle::create(blobData.release(), size)); | 258 m_handle = FetchBlobDataConsumerHandle::create(executionContext, Blo
bDataHandle::create(blobData.release(), size)); |
259 } | 259 } |
260 // It is important to initialize |m_formData| here, because even | 260 // It is important to initialize |m_formData| here, because even |
261 // read-only operations may make the form data unsharable with implicit | 261 // read-only operations may make the form data unsharable with implicit |
262 // ref-counting. | 262 // ref-counting. |
263 m_formData = body->deepCopy(); | 263 m_formData = body->deepCopy(); |
264 } | 264 } |
265 PassRefPtr<FormData> drainFormData() | 265 PassRefPtr<EncodedFormData> drainFormData() |
266 { | 266 { |
267 ASSERT(!m_formData || m_formData->isSafeToSendToAnotherThread()); | 267 ASSERT(!m_formData || m_formData->isSafeToSendToAnotherThread()); |
268 return m_formData.release(); | 268 return m_formData.release(); |
269 } | 269 } |
270 | 270 |
271 RefPtr<FormData> m_formData; | 271 RefPtr<EncodedFormData> m_formData; |
272 OwnPtr<FetchDataConsumerHandle> m_handle; | 272 OwnPtr<FetchDataConsumerHandle> m_handle; |
273 }; | 273 }; |
274 | 274 |
275 PassOwnPtr<FetchDataConsumerHandle> FetchFormDataConsumerHandle::create(const St
ring& body) | 275 PassOwnPtr<FetchDataConsumerHandle> FetchFormDataConsumerHandle::create(const St
ring& body) |
276 { | 276 { |
277 return adoptPtr(new FetchFormDataConsumerHandle(body)); | 277 return adoptPtr(new FetchFormDataConsumerHandle(body)); |
278 } | 278 } |
279 PassOwnPtr<FetchDataConsumerHandle> FetchFormDataConsumerHandle::create(PassRefP
tr<DOMArrayBuffer> body) | 279 PassOwnPtr<FetchDataConsumerHandle> FetchFormDataConsumerHandle::create(PassRefP
tr<DOMArrayBuffer> body) |
280 { | 280 { |
281 return adoptPtr(new FetchFormDataConsumerHandle(body->data(), body->byteLeng
th())); | 281 return adoptPtr(new FetchFormDataConsumerHandle(body->data(), body->byteLeng
th())); |
282 } | 282 } |
283 PassOwnPtr<FetchDataConsumerHandle> FetchFormDataConsumerHandle::create(PassRefP
tr<DOMArrayBufferView> body) | 283 PassOwnPtr<FetchDataConsumerHandle> FetchFormDataConsumerHandle::create(PassRefP
tr<DOMArrayBufferView> body) |
284 { | 284 { |
285 return adoptPtr(new FetchFormDataConsumerHandle(body->baseAddress(), body->b
yteLength())); | 285 return adoptPtr(new FetchFormDataConsumerHandle(body->baseAddress(), body->b
yteLength())); |
286 } | 286 } |
287 PassOwnPtr<FetchDataConsumerHandle> FetchFormDataConsumerHandle::create(const vo
id* data, size_t size) | 287 PassOwnPtr<FetchDataConsumerHandle> FetchFormDataConsumerHandle::create(const vo
id* data, size_t size) |
288 { | 288 { |
289 return adoptPtr(new FetchFormDataConsumerHandle(data, size)); | 289 return adoptPtr(new FetchFormDataConsumerHandle(data, size)); |
290 } | 290 } |
291 PassOwnPtr<FetchDataConsumerHandle> FetchFormDataConsumerHandle::create(Executio
nContext* executionContext, PassRefPtr<FormData> body) | 291 PassOwnPtr<FetchDataConsumerHandle> FetchFormDataConsumerHandle::create(Executio
nContext* executionContext, PassRefPtr<EncodedFormData> body) |
292 { | 292 { |
293 return adoptPtr(new FetchFormDataConsumerHandle(executionContext, body)); | 293 return adoptPtr(new FetchFormDataConsumerHandle(executionContext, body)); |
294 } | 294 } |
295 PassOwnPtr<FetchDataConsumerHandle> FetchFormDataConsumerHandle::createForTest( | 295 PassOwnPtr<FetchDataConsumerHandle> FetchFormDataConsumerHandle::createForTest( |
296 ExecutionContext* executionContext, | 296 ExecutionContext* executionContext, |
297 PassRefPtr<FormData> body, | 297 PassRefPtr<EncodedFormData> body, |
298 FetchBlobDataConsumerHandle::LoaderFactory* loaderFactory) | 298 FetchBlobDataConsumerHandle::LoaderFactory* loaderFactory) |
299 { | 299 { |
300 return adoptPtr(new FetchFormDataConsumerHandle(executionContext, body, load
erFactory)); | 300 return adoptPtr(new FetchFormDataConsumerHandle(executionContext, body, load
erFactory)); |
301 } | 301 } |
302 | 302 |
303 FetchFormDataConsumerHandle::FetchFormDataConsumerHandle(const String& body) : m
_context(SimpleContext::create(body)) {} | 303 FetchFormDataConsumerHandle::FetchFormDataConsumerHandle(const String& body) : m
_context(SimpleContext::create(body)) {} |
304 FetchFormDataConsumerHandle::FetchFormDataConsumerHandle(const void* data, size_
t size) : m_context(SimpleContext::create(data, size)) {} | 304 FetchFormDataConsumerHandle::FetchFormDataConsumerHandle(const void* data, size_
t size) : m_context(SimpleContext::create(data, size)) {} |
305 FetchFormDataConsumerHandle::FetchFormDataConsumerHandle(ExecutionContext* execu
tionContext, | 305 FetchFormDataConsumerHandle::FetchFormDataConsumerHandle(ExecutionContext* execu
tionContext, |
306 PassRefPtr<FormData> body, | 306 PassRefPtr<EncodedFormData> body, |
307 FetchBlobDataConsumerHandle::LoaderFactory* loaderFactory) | 307 FetchBlobDataConsumerHandle::LoaderFactory* loaderFactory) |
308 { | 308 { |
309 if (isSimple(body.get())) { | 309 if (isSimple(body.get())) { |
310 m_context = SimpleContext::create(body); | 310 m_context = SimpleContext::create(body); |
311 } else { | 311 } else { |
312 m_context = ComplexContext::create(executionContext, body, loaderFactory
); | 312 m_context = ComplexContext::create(executionContext, body, loaderFactory
); |
313 } | 313 } |
314 } | 314 } |
315 FetchFormDataConsumerHandle::~FetchFormDataConsumerHandle() {} | 315 FetchFormDataConsumerHandle::~FetchFormDataConsumerHandle() {} |
316 | 316 |
317 FetchDataConsumerHandle::Reader* FetchFormDataConsumerHandle::obtainReaderIntern
al(Client* client) | 317 FetchDataConsumerHandle::Reader* FetchFormDataConsumerHandle::obtainReaderIntern
al(Client* client) |
318 { | 318 { |
319 return m_context->obtainReader(client).leakPtr(); | 319 return m_context->obtainReader(client).leakPtr(); |
320 } | 320 } |
321 | 321 |
322 } // namespace blink | 322 } // namespace blink |
OLD | NEW |