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

Side by Side Diff: WebCore/platform/network/FormData.cpp

Issue 1769002: BlobBuilder/FormData refactor attempt (Closed)
Patch Set: back to simple FormData Created 10 years, 6 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
« no previous file with comments | « WebCore/platform/network/FormData.h ('k') | WebCore/platform/network/mac/FormDataStreamMac.mm » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved. 2 * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2009 Google Inc. All rights reserved. 3 * Copyright (C) 2009 Google Inc. All rights reserved.
4 * 4 *
5 * This library is free software; you can redistribute it and/or 5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public 6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either 7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version. 8 * version 2 of the License, or (at your option) any later version.
9 * 9 *
10 * This library is distributed in the hope that it will be useful, 10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details. 13 * Library General Public License for more details.
14 * 14 *
15 * You should have received a copy of the GNU Library General Public License 15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to 16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA. 18 * Boston, MA 02110-1301, USA.
19 */ 19 */
20 20
21 #include "config.h" 21 #include "config.h"
22
22 #include "FormData.h" 23 #include "FormData.h"
23 24
24 #include "Blob.h" 25 #include "BlobItem.h"
25 #include "Chrome.h" 26 #include "Chrome.h"
26 #include "ChromeClient.h" 27 #include "ChromeClient.h"
27 #include "DOMFormData.h"
28 #include "Document.h" 28 #include "Document.h"
29 #include "File.h"
30 #include "FileSystem.h" 29 #include "FileSystem.h"
31 #include "FormDataBuilder.h" 30 #include "FormDataBuilder.h"
32 #include "MIMETypeRegistry.h" 31 #include "MIMETypeRegistry.h"
33 #include "Page.h" 32 #include "Page.h"
34 #include "TextEncoding.h" 33 #include "TextEncoding.h"
35 #include "UUID.h"
36 34
37 namespace WebCore { 35 namespace WebCore {
38 36
37 #if ENABLE(BLOB_SLICE)
38 const long long FormDataElement::toEndOfFile = -1;
39 const double FormDataElement::doNotCheckFileChange = 0;
40 #endif
41
39 inline FormData::FormData() 42 inline FormData::FormData()
40 : m_identifier(0) 43 : m_identifier(0)
41 , m_hasGeneratedFiles(false) 44 , m_hasGeneratedFiles(false)
42 , m_alwaysStream(false) 45 , m_alwaysStream(false)
43 { 46 {
44 } 47 }
45 48
46 inline FormData::FormData(const FormData& data) 49 inline FormData::FormData(const FormData& data)
47 : RefCounted<FormData>() 50 : RefCounted<FormData>()
48 , m_elements(data.m_elements) 51 , m_elements(data.m_elements)
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
89 return result.release(); 92 return result.release();
90 } 93 }
91 94
92 PassRefPtr<FormData> FormData::create(const Vector<char>& vector) 95 PassRefPtr<FormData> FormData::create(const Vector<char>& vector)
93 { 96 {
94 RefPtr<FormData> result = create(); 97 RefPtr<FormData> result = create();
95 result->appendData(vector.data(), vector.size()); 98 result->appendData(vector.data(), vector.size());
96 return result.release(); 99 return result.release();
97 } 100 }
98 101
99 PassRefPtr<FormData> FormData::create(const DOMFormData& domFormData) 102 PassRefPtr<FormData> FormData::create(const BlobItemList& items, const TextEncod ing& encoding)
100 { 103 {
101 RefPtr<FormData> result = create(); 104 RefPtr<FormData> result = create();
102 result->appendDOMFormData(domFormData, false, 0); 105 result->appendKeyValuePairItems(items, encoding, false, 0);
103 return result.release(); 106 return result.release();
104 } 107 }
105 108
106 PassRefPtr<FormData> FormData::createMultiPart(const DOMFormData& domFormData, D ocument* document) 109 PassRefPtr<FormData> FormData::createMultiPart(const BlobItemList& items, const TextEncoding& encoding, Document* document)
107 { 110 {
108 RefPtr<FormData> result = create(); 111 RefPtr<FormData> result = create();
109 result->appendDOMFormData(domFormData, true, document); 112 result->appendKeyValuePairItems(items, encoding, true, document);
110 return result.release(); 113 return result.release();
111 } 114 }
112 115
113 PassRefPtr<FormData> FormData::copy() const 116 PassRefPtr<FormData> FormData::copy() const
114 { 117 {
115 return adoptRef(new FormData(*this)); 118 return adoptRef(new FormData(*this));
116 } 119 }
117 120
118 PassRefPtr<FormData> FormData::deepCopy() const 121 PassRefPtr<FormData> FormData::deepCopy() const
119 { 122 {
(...skipping 27 matching lines...) Expand all
147 m_elements.append(FormDataElement()); 150 m_elements.append(FormDataElement());
148 FormDataElement& e = m_elements.last(); 151 FormDataElement& e = m_elements.last();
149 size_t oldSize = e.m_data.size(); 152 size_t oldSize = e.m_data.size();
150 e.m_data.grow(oldSize + size); 153 e.m_data.grow(oldSize + size);
151 memcpy(e.m_data.data() + oldSize, data, size); 154 memcpy(e.m_data.data() + oldSize, data, size);
152 } 155 }
153 156
154 void FormData::appendFile(const String& filename, bool shouldGenerateFile) 157 void FormData::appendFile(const String& filename, bool shouldGenerateFile)
155 { 158 {
156 #if ENABLE(BLOB_SLICE) 159 #if ENABLE(BLOB_SLICE)
157 m_elements.append(FormDataElement(filename, 0, Blob::toEndOfFile, Blob::doNo tCheckFileChange, shouldGenerateFile)); 160 m_elements.append(FormDataElement(filename, 0, FormDataElement::toEndOfFile, FormDataElement::doNotCheckFileChange, shouldGenerateFile));
158 #else 161 #else
159 m_elements.append(FormDataElement(filename, shouldGenerateFile)); 162 m_elements.append(FormDataElement(filename, shouldGenerateFile));
160 #endif 163 #endif
161 } 164 }
162 165
166 void FormData::appendItems(const BlobItemList& items)
167 {
168 for (BlobItemList::const_iterator iter(items.begin()); iter != items.end(); ++iter)
169 appendItem(iter->get(), false);
170 }
171
172 void FormData::appendItem(const BlobItem* item, bool shouldGenerateFile)
173 {
174 const DataBlobItem* dataItem = item->toDataBlobItem();
175 if (dataItem) {
176 appendData(dataItem->data(), static_cast<size_t>(dataItem->size()));
177 return;
178 }
179
180 const FileBlobItem* fileItem = item->toFileBlobItem();
181 ASSERT(fileItem);
182 if (fileItem->path().isEmpty()) {
183 // If the path is empty do not add the item.
184 return;
185 }
186
187 #if ENABLE(BLOB_SLICE)
188 const FileRangeBlobItem* fileRangeItem = item->toFileRangeBlobItem();
189 if (fileRangeItem) {
190 appendFileRange(fileItem->path(), fileRangeItem->start(), fileRangeItem- >size(), fileRangeItem->snapshotModificationTime(), shouldGenerateFile);
191 return;
192 }
193 #endif
194
195 appendFile(fileItem->path(), shouldGenerateFile);
196 }
197
163 #if ENABLE(BLOB_SLICE) 198 #if ENABLE(BLOB_SLICE)
164 void FormData::appendFileRange(const String& filename, long long start, long lon g length, double expectedModificationTime, bool shouldGenerateFile) 199 void FormData::appendFileRange(const String& filename, long long start, long lon g length, double expectedModificationTime, bool shouldGenerateFile)
165 { 200 {
166 m_elements.append(FormDataElement(filename, start, length, expectedModificat ionTime, shouldGenerateFile)); 201 m_elements.append(FormDataElement(filename, start, length, expectedModificat ionTime, shouldGenerateFile));
167 } 202 }
168 #endif 203 #endif
169 204
170 void FormData::appendDOMFormData(const DOMFormData& domFormData, bool isMultiPar tForm, Document* document) 205 void FormData::appendKeyValuePairItems(const BlobItemList& items, const TextEnco ding& encoding, bool isMultiPartForm, Document* document)
171 { 206 {
172 FormDataBuilder formDataBuilder; 207 FormDataBuilder formDataBuilder;
173 if (isMultiPartForm) 208 if (isMultiPartForm)
174 m_boundary = formDataBuilder.generateUniqueBoundaryString(); 209 m_boundary = formDataBuilder.generateUniqueBoundaryString();
175 210
176 Vector<char> encodedData; 211 Vector<char> encodedData;
177 TextEncoding encoding = domFormData.encoding();
178 212
179 const Vector<FormDataList::Item>& list = domFormData.list(); 213 size_t formDataListSize = items.size();
180 size_t formDataListSize = list.size();
181 ASSERT(!(formDataListSize % 2)); 214 ASSERT(!(formDataListSize % 2));
182 for (size_t i = 0; i < formDataListSize; i += 2) { 215 for (size_t i = 0; i < formDataListSize; i += 2) {
183 const FormDataList::Item& key = list[i]; 216 const StringBlobItem* key = items[i]->toStringBlobItem();
184 const FormDataList::Item& value = list[i + 1]; 217 const RefPtr<BlobItem> value = items[i + 1];
218 ASSERT(key);
185 if (isMultiPartForm) { 219 if (isMultiPartForm) {
186 Vector<char> header; 220 Vector<char> header;
187 formDataBuilder.beginMultiPartHeader(header, m_boundary.data(), key. data()); 221 formDataBuilder.beginMultiPartHeader(header, m_boundary.data(), key- >cstr());
188 222
189 bool shouldGenerateFile = false; 223 bool shouldGenerateFile = false;
190 // If the current type is FILE, then we also need to include the fil ename 224 // If the current type is FILE, then we also need to include the fil ename
191 if (value.blob()) { 225 const FileBlobItem* fileItem = value->toFileBlobItem();
192 const String& path = value.blob()->path(); 226 if (fileItem) {
193 #if ENABLE(BLOB_SLICE) 227 const String& path = fileItem->path();
194 String fileName; 228 String fileName = fileItem->name();
195 if (value.blob()->isFile())
196 fileName = static_cast<File*>(value.blob())->fileName();
197 else {
198 // If a blob is sliced from a file, it does not have the fil ename. In this case, let's produce a unique filename.
199 fileName = "Blob" + createCanonicalUUIDString();
200 fileName.replace("-", ""); // For safty, remove '-' from the filename snce some servers may not like it.
201 }
202 #else
203 ASSERT(value.blob()->isFile());
204 String fileName = static_cast<File*>(value.blob())->fileName();
205 #endif
206 229
207 // Let the application specify a filename if it's going to gener ate a replacement file for the upload. 230 // Let the application specify a filename if it's going to gener ate a replacement file for the upload.
208 if (!path.isEmpty()) { 231 if (!path.isEmpty()) {
209 if (Page* page = document->page()) { 232 if (Page* page = document->page()) {
210 String generatedFileName; 233 String generatedFileName;
211 shouldGenerateFile = page->chrome()->client()->shouldRep laceWithGeneratedFileForUpload(path, generatedFileName); 234 shouldGenerateFile = page->chrome()->client()->shouldRep laceWithGeneratedFileForUpload(path, generatedFileName);
212 if (shouldGenerateFile) 235 if (shouldGenerateFile)
213 fileName = generatedFileName; 236 fileName = generatedFileName;
214 } 237 }
215 } 238 }
216 239
217 // We have to include the filename=".." part in the header, even if the filename is empty 240 // We have to include the filename=".." part in the header, even if the filename is empty
218 formDataBuilder.addFilenameToMultiPartHeader(header, encoding, f ileName); 241 formDataBuilder.addFilenameToMultiPartHeader(header, encoding, f ileName);
219 242
220 // If a blob is sliced from a file, do not add the content type. 243 // If the item is sliced from a file, do not add the content typ e.
221 #if ENABLE(BLOB_SLICE) 244 #if ENABLE(BLOB_SLICE)
222 if (!fileName.isEmpty() && value.blob()->isFile()) { 245 if (!fileName.isEmpty() && !value->toFileRangeBlobItem()) {
223 #else 246 #else
224 if (!fileName.isEmpty()) { 247 if (!fileName.isEmpty()) {
225 #endif 248 #endif
226 // FIXME: The MIMETypeRegistry function's name makes it soun d like it takes a path, 249 // FIXME: The MIMETypeRegistry function's name makes it soun d like it takes a path,
227 // not just a basename. But filename is not the path. But no te that it's not safe to 250 // not just a basename. But filename is not the path. But no te that it's not safe to
228 // just use path instead since in the generated-file case it will not reflect the 251 // just use path instead since in the generated-file case it will not reflect the
229 // MIME type of the generated file. 252 // MIME type of the generated file.
230 String mimeType = MIMETypeRegistry::getMIMETypeForPath(fileN ame); 253 String mimeType = MIMETypeRegistry::getMIMETypeForPath(fileN ame);
231 if (!mimeType.isEmpty()) 254 if (!mimeType.isEmpty())
232 formDataBuilder.addContentTypeToMultiPartHeader(header, mimeType.latin1()); 255 formDataBuilder.addContentTypeToMultiPartHeader(header, mimeType.latin1());
233 } 256 }
234 } 257 }
235 258
236 formDataBuilder.finishMultiPartHeader(header); 259 formDataBuilder.finishMultiPartHeader(header);
237 260
238 // Append body 261 // Append body
239 appendData(header.data(), header.size()); 262 appendData(header.data(), header.size());
240 if (size_t dataSize = value.data().length()) 263 appendItem(value.get(), shouldGenerateFile);
241 appendData(value.data().data(), dataSize);
242 else if (value.blob() && !value.blob()->path().isEmpty())
243 #if ENABLE(BLOB_SLICE)
244 appendFileRange(value.blob()->path(), value.blob()->start(), val ue.blob()->length(), value.blob()->modificationTime(), shouldGenerateFile);
245 #else
246 appendFile(value.blob()->path(), shouldGenerateFile);
247 #endif
248
249 appendData("\r\n", 2); 264 appendData("\r\n", 2);
250 } else { 265 } else {
251 // Omit the name "isindex" if it's the first form data element. 266 // Omit the name "isindex" if it's the first form data element.
252 // FIXME: Why is this a good rule? Is this obsolete now? 267 // FIXME: Why is this a good rule? Is this obsolete now?
253 if (encodedData.isEmpty() && key.data() == "isindex") 268 const StringBlobItem* stringValue = value->toStringBlobItem();
254 FormDataBuilder::encodeStringAsFormData(encodedData, value.data( )); 269 if (!stringValue)
270 continue;
271 if (encodedData.isEmpty() && key->cstr() == "isindex")
272 FormDataBuilder::encodeStringAsFormData(encodedData, stringValue ->cstr());
255 else 273 else
256 formDataBuilder.addKeyValuePairAsFormData(encodedData, key.data( ), value.data()); 274 formDataBuilder.addKeyValuePairAsFormData(encodedData, key->cstr (), stringValue->cstr());
257 } 275 }
258 } 276 }
259 277
260 if (isMultiPartForm) 278 if (isMultiPartForm)
261 formDataBuilder.addBoundaryToMultiPartHeader(encodedData, m_boundary.dat a(), true); 279 formDataBuilder.addBoundaryToMultiPartHeader(encodedData, m_boundary.dat a(), true);
262 280
263 appendData(encodedData.data(), encodedData.size()); 281 appendData(encodedData.data(), encodedData.size());
264 } 282 }
265 283
266 void FormData::flatten(Vector<char>& data) const 284 void FormData::flatten(Vector<char>& data) const
267 { 285 {
268 // Concatenate all the byte arrays, but omit any files. 286 // Concatenate all the byte arrays, but omit any files.
269 data.clear(); 287 data.clear();
270 size_t n = m_elements.size(); 288 size_t n = m_elements.size();
271 for (size_t i = 0; i < n; ++i) { 289 for (size_t i = 0; i < n; ++i) {
272 const FormDataElement& e = m_elements[i]; 290 const FormDataElement& e = m_elements[i];
273 if (e.m_type == FormDataElement::data) { 291 if (e.m_type == FormDataElement::data)
274 size_t oldSize = data.size(); 292 data.append(e.m_data.data(), static_cast<size_t>(e.m_data.size()));
275 size_t delta = e.m_data.size();
276 data.grow(oldSize + delta);
277 memcpy(data.data() + oldSize, e.m_data.data(), delta);
278 }
279 } 293 }
280 } 294 }
281 295
282 String FormData::flattenToString() const 296 String FormData::flattenToString() const
283 { 297 {
284 Vector<char> bytes; 298 Vector<char> bytes;
285 flatten(bytes); 299 flatten(bytes);
286 return Latin1Encoding().decode(bytes.data(), bytes.size()); 300 return Latin1Encoding().decode(bytes.data(), bytes.size());
287 } 301 }
288 302
289 void FormData::generateFiles(Document* document) 303 void FormData::generateFiles(Document* document)
290 { 304 {
291 ASSERT(!m_hasGeneratedFiles); 305 ASSERT(!m_hasGeneratedFiles);
292 306
293 if (m_hasGeneratedFiles) 307 if (m_hasGeneratedFiles)
294 return; 308 return;
295 309
296 Page* page = document->page(); 310 Page* page = document->page();
297 if (!page) 311 if (!page)
298 return; 312 return;
299 ChromeClient* client = page->chrome()->client(); 313 ChromeClient* client = page->chrome()->client();
300 314
301 size_t n = m_elements.size(); 315 size_t n = m_elements.size();
302 for (size_t i = 0; i < n; ++i) { 316 for (size_t i = 0; i < n; ++i) {
303 FormDataElement& e = m_elements[i]; 317 FormDataElement& e = m_elements[i];
304 if (e.m_type == FormDataElement::encodedFile && e.m_shouldGenerateFile) { 318 if (e.m_type == FormDataElement::encodedFile && e.m_shouldGenerateFile) {
305 e.m_generatedFilename = client->generateReplacementFile(e.m_filename ); 319 e.m_generatedFilename = client->generateReplacementFile(e.m_filename );
306 m_hasGeneratedFiles = true; 320 m_hasGeneratedFiles = true;
307 } 321 }
308 } 322 }
309 } 323 }
310 324
311 void FormData::removeGeneratedFilesIfNeeded() 325 void FormData::removeGeneratedFilesIfNeeded()
312 { 326 {
313 if (!m_hasGeneratedFiles) 327 if (!m_hasGeneratedFiles)
314 return; 328 return;
315 329
316 size_t n = m_elements.size(); 330 size_t n = m_elements.size();
317 for (size_t i = 0; i < n; ++i) { 331 for (size_t i = 0; i < n; ++i) {
318 FormDataElement& e = m_elements[i]; 332 FormDataElement& e = m_elements[i];
319 if (e.m_type == FormDataElement::encodedFile && !e.m_generatedFilename.i sEmpty()) { 333 if (e.m_type == FormDataElement::encodedFile && !e.m_generatedFilename.i sEmpty()) {
320 ASSERT(e.m_shouldGenerateFile); 334 ASSERT(e.m_shouldGenerateFile);
321 String directory = directoryName(e.m_generatedFilename); 335 String directory = directoryName(e.m_generatedFilename);
322 deleteFile(e.m_generatedFilename); 336 deleteFile(e.m_generatedFilename);
323 deleteEmptyDirectory(directory); 337 deleteEmptyDirectory(directory);
324 e.m_generatedFilename = String(); 338 e.m_generatedFilename = String();
325 } 339 }
326 } 340 }
327 m_hasGeneratedFiles = false; 341 m_hasGeneratedFiles = false;
328 } 342 }
329 343
330 } // namespace WebCore 344 } // namespace WebCore
OLDNEW
« no previous file with comments | « WebCore/platform/network/FormData.h ('k') | WebCore/platform/network/mac/FormDataStreamMac.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698