Changeset 236365 in webkit
- Timestamp:
- Sep 21, 2018, 3:50:36 PM (7 years ago)
- Location:
- trunk/Source
- Files:
-
- 16 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r236356 r236365 1 2018-09-21 Alex Christensen <achristensen@webkit.org> 2 3 Use a Variant for FormDataElement 4 https://bugs.webkit.org/show_bug.cgi?id=189777 5 6 Reviewed by Chris Dumez. 7 8 * platform/network/FormData.cpp: 9 (WebCore::FormData::FormData): 10 (WebCore::FormDataElement::lengthInBytes const): 11 (WebCore::FormDataElement::isolatedCopy const): 12 (WebCore::FormData::appendData): 13 (WebCore::FormData::flatten const): 14 (WebCore::FormData::resolveBlobReferences): 15 (WebCore::FormData::generateFiles): 16 (WebCore::FormData::hasGeneratedFiles const): 17 (WebCore::FormData::hasOwnedGeneratedFiles const): 18 (WebCore::FormData::removeGeneratedFilesIfNeeded): 19 (WebCore::FormData::asSharedBuffer const): 20 (WebCore::FormData::asBlobURL const): 21 (WebCore::FormData::expandDataStore): Deleted. 22 * platform/network/FormData.h: 23 (WebCore::FormDataElement::FormDataElement): 24 (WebCore::FormDataElement::encode const): 25 (WebCore::FormDataElement::decode): 26 (WebCore::FormDataElement::EncodedFileData::isolatedCopy const): 27 (WebCore::FormDataElement::EncodedFileData::operator== const): 28 (WebCore::FormDataElement::EncodedFileData::encode const): 29 (WebCore::FormDataElement::EncodedFileData::decode): 30 (WebCore::FormDataElement::EncodedBlobData::operator== const): 31 (WebCore::FormDataElement::EncodedBlobData::encode const): 32 (WebCore::FormDataElement::EncodedBlobData::decode): 33 (WebCore::FormDataElement::operator== const): 34 (WebCore::FormDataElement::operator!= const): 35 * platform/network/cf/FormDataStreamCFNet.cpp: 36 (WebCore::advanceCurrentStream): 37 (WebCore::createHTTPBodyCFReadStream): 38 (WebCore::setHTTPBody): 39 * platform/network/curl/CurlFormDataStream.cpp: 40 (WebCore::CurlFormDataStream::computeContentLength): 41 (WebCore::CurlFormDataStream::read): 42 (WebCore::CurlFormDataStream::readFromFile): 43 (WebCore::CurlFormDataStream::readFromData): 44 * platform/network/curl/CurlFormDataStream.h: 45 1 46 2018-09-20 Simon Fraser <simon.fraser@apple.com> 2 47 -
trunk/Source/WebCore/html/HTMLMediaElement.cpp
r236006 r236365 1485 1485 // 2. End the synchronous section, continuing the remaining steps in parallel. 1486 1486 // 3. Run the resource fetch algorithm with the assigned media provider object. 1487 WTF::visit(WTF::makeVisitor(1487 switchOn(m_mediaProvider.value(), 1488 1488 #if ENABLE(MEDIA_STREAM) 1489 1489 [this](RefPtr<MediaStream> stream) { m_mediaStreamSrcObject = stream; }, … … 1493 1493 #endif 1494 1494 [this](RefPtr<Blob> blob) { m_blob = blob; } 1495 ) , m_mediaProvider.value());1495 ); 1496 1496 1497 1497 ContentType contentType; -
trunk/Source/WebCore/platform/network/FormData.cpp
r235573 r236365 54 54 // but just in case, make sure the new FormData is ready to generate its own files. 55 55 for (auto& element : m_elements) { 56 if ( element.m_type == FormDataElement::Type::EncodedFile) {57 element.m_generatedFilename = String();58 element.m_ownsGeneratedFile = false;56 if (auto* fileData = WTF::get_if<FormDataElement::EncodedFileData>(element.data)) { 57 fileData->generatedFilename = { }; 58 fileData->ownsGeneratedFile = false; 59 59 } 60 60 } … … 91 91 } 92 92 93 Ref<FormData> FormData::create(Vector<char>&& vector) 94 { 95 auto data = create(); 96 data->m_elements.append(WTFMove(vector)); 97 return data; 98 } 99 93 100 Ref<FormData> FormData::create(const Vector<uint8_t>& vector) 94 101 { … … 133 140 uint64_t FormDataElement::lengthInBytes() const 134 141 { 135 switch (m_type) { 136 case Type::Data: 137 return m_data.size(); 138 case Type::EncodedFile: { 139 if (m_fileLength != BlobDataItem::toEndOfFile) 140 return m_fileLength; 141 long long fileSize; 142 if (FileSystem::getFileSize(m_shouldGenerateFile ? m_generatedFilename : m_filename, fileSize)) 143 return fileSize; 144 return 0; 145 } 146 case Type::EncodedBlob: 147 return ThreadableBlobRegistry::blobSize(m_url); 148 } 149 ASSERT_NOT_REACHED(); 150 return 0; 142 return switchOn(data, 143 [] (const Vector<char>& bytes) { 144 return static_cast<uint64_t>(bytes.size()); 145 }, [] (const FormDataElement::EncodedFileData& fileData) { 146 if (fileData.fileLength != BlobDataItem::toEndOfFile) 147 return static_cast<uint64_t>(fileData.fileLength); 148 long long fileSize; 149 if (FileSystem::getFileSize(fileData.shouldGenerateFile ? fileData.generatedFilename : fileData.filename, fileSize)) 150 return static_cast<uint64_t>(fileSize); 151 return static_cast<uint64_t>(0); 152 }, [] (const FormDataElement::EncodedBlobData& blobData) { 153 return ThreadableBlobRegistry::blobSize(blobData.url); 154 } 155 ); 151 156 } 152 157 153 158 FormDataElement FormDataElement::isolatedCopy() const 154 159 { 155 switch (m_type) { 156 case Type::Data: 157 return FormDataElement(m_data); 158 case Type::EncodedFile: 159 return FormDataElement(m_filename.isolatedCopy(), m_fileStart, m_fileLength, m_expectedFileModificationTime, m_shouldGenerateFile); 160 case Type::EncodedBlob: 161 return FormDataElement(m_url.isolatedCopy()); 162 } 163 164 RELEASE_ASSERT_NOT_REACHED(); 160 return switchOn(data, 161 [] (const Vector<char>& bytes) { 162 Vector<char> copy; 163 copy.append(bytes.data(), bytes.size()); 164 return FormDataElement(WTFMove(copy)); 165 }, [] (const FormDataElement::EncodedFileData& fileData) { 166 return FormDataElement(fileData.isolatedCopy()); 167 }, [] (const FormDataElement::EncodedBlobData& blobData) { 168 return FormDataElement(blobData.url.isolatedCopy()); 169 } 170 ); 165 171 } 166 172 167 173 void FormData::appendData(const void* data, size_t size) 168 174 { 169 memcpy(expandDataStore(size), data, size); 175 m_lengthInBytes = std::nullopt; 176 if (!m_elements.isEmpty()) { 177 if (auto* vector = WTF::get_if<Vector<char>>(m_elements.last().data)) { 178 vector->append(reinterpret_cast<const char*>(data), size); 179 return; 180 } 181 } 182 Vector<char> vector; 183 vector.append(reinterpret_cast<const char*>(data), size); 184 m_elements.append(WTFMove(vector)); 170 185 } 171 186 … … 280 295 } 281 296 282 char* FormData::expandDataStore(size_t size)283 {284 m_lengthInBytes = std::nullopt;285 if (m_elements.isEmpty() || m_elements.last().m_type != FormDataElement::Type::Data)286 m_elements.append({ });287 288 auto& lastElement = m_elements.last();289 size_t oldSize = lastElement.m_data.size();290 291 auto newSize = Checked<size_t>(oldSize) + size;292 293 lastElement.m_data.grow(newSize.unsafeGet());294 return lastElement.m_data.data() + oldSize;295 }296 297 297 Vector<char> FormData::flatten() const 298 298 { … … 300 300 Vector<char> data; 301 301 for (auto& element : m_elements) { 302 if ( element.m_type == FormDataElement::Type::Data)303 data.append( element.m_data.data(), static_cast<size_t>(element.m_data.size()));302 if (auto* vector = WTF::get_if<Vector<char>>(element.data)) 303 data.append(vector->data(), vector->size()); 304 304 } 305 305 return data; … … 341 341 bool hasBlob = false; 342 342 for (auto& element : m_elements) { 343 if ( element.m_type == FormDataElement::Type::EncodedBlob) {343 if (WTF::holds_alternative<FormDataElement::EncodedBlobData>(element.data)) { 344 344 hasBlob = true; 345 345 break; … … 356 356 357 357 for (auto& element : m_elements) { 358 if (element.m_type == FormDataElement::Type::Data) 359 newFormData->appendData(element.m_data.data(), element.m_data.size()); 360 else if (element.m_type == FormDataElement::Type::EncodedFile) 361 newFormData->appendFileRange(element.m_filename, element.m_fileStart, element.m_fileLength, element.m_expectedFileModificationTime, element.m_shouldGenerateFile); 362 else if (element.m_type == FormDataElement::Type::EncodedBlob) 363 appendBlobResolved(newFormData.ptr(), element.m_url); 364 else 365 ASSERT_NOT_REACHED(); 358 switchOn(element.data, 359 [&] (const Vector<char>& bytes) { 360 newFormData->appendData(bytes.data(), bytes.size()); 361 }, [&] (const FormDataElement::EncodedFileData& fileData) { 362 newFormData->appendFileRange(fileData.filename, fileData.fileStart, fileData.fileLength, fileData.expectedFileModificationTime, fileData.shouldGenerateFile); 363 }, [&] (const FormDataElement::EncodedBlobData& blobData) { 364 appendBlobResolved(newFormData.ptr(), blobData.url); 365 } 366 ); 366 367 } 367 368 return newFormData; … … 375 376 376 377 for (auto& element : m_elements) { 377 if (element.m_type == FormDataElement::Type::EncodedFile && element.m_shouldGenerateFile) { 378 ASSERT(!element.m_ownsGeneratedFile); 379 ASSERT(element.m_generatedFilename.isEmpty()); 380 if (!element.m_generatedFilename.isEmpty()) 381 continue; 382 element.m_generatedFilename = page->chrome().client().generateReplacementFile(element.m_filename); 383 if (!element.m_generatedFilename.isEmpty()) 384 element.m_ownsGeneratedFile = true; 378 if (auto* fileData = WTF::get_if<FormDataElement::EncodedFileData>(element.data)) { 379 if (fileData->shouldGenerateFile) { 380 ASSERT(!fileData->ownsGeneratedFile); 381 ASSERT(fileData->generatedFilename.isEmpty()); 382 if (!fileData->generatedFilename.isEmpty()) 383 continue; 384 fileData->generatedFilename = page->chrome().client().generateReplacementFile(fileData->filename); 385 if (!fileData->generatedFilename.isEmpty()) 386 fileData->ownsGeneratedFile = true; 387 } 385 388 } 386 389 } … … 390 393 { 391 394 for (auto& element : m_elements) { 392 if (element.m_type == FormDataElement::Type::EncodedFile && !element.m_generatedFilename.isEmpty()) 393 return true; 395 if (auto* fileData = WTF::get_if<FormDataElement::EncodedFileData>(element.data)) { 396 if (!fileData->generatedFilename.isEmpty()) 397 return true; 398 } 394 399 } 395 400 return false; … … 399 404 { 400 405 for (auto& element : m_elements) { 401 if (element.m_type == FormDataElement::Type::EncodedFile && element.m_ownsGeneratedFile) { 402 ASSERT(!element.m_generatedFilename.isEmpty()); 403 return true; 406 if (auto* fileData = WTF::get_if<FormDataElement::EncodedFileData>(element.data)) { 407 if (fileData->ownsGeneratedFile) { 408 ASSERT(!fileData->generatedFilename.isEmpty()); 409 return true; 410 } 404 411 } 405 412 } … … 410 417 { 411 418 for (auto& element : m_elements) { 412 if (element.m_type == FormDataElement::Type::EncodedFile && element.m_ownsGeneratedFile) { 413 ASSERT(!element.m_generatedFilename.isEmpty()); 414 ASSERT(element.m_shouldGenerateFile); 415 String directory = FileSystem::directoryName(element.m_generatedFilename); 416 FileSystem::deleteFile(element.m_generatedFilename); 417 FileSystem::deleteEmptyDirectory(directory); 418 element.m_generatedFilename = String(); 419 element.m_ownsGeneratedFile = false; 419 if (auto* fileData = WTF::get_if<FormDataElement::EncodedFileData>(element.data)) { 420 if (fileData->ownsGeneratedFile) { 421 ASSERT(!fileData->generatedFilename.isEmpty()); 422 ASSERT(fileData->shouldGenerateFile); 423 String directory = FileSystem::directoryName(fileData->generatedFilename); 424 FileSystem::deleteFile(fileData->generatedFilename); 425 FileSystem::deleteEmptyDirectory(directory); 426 fileData->generatedFilename = String(); 427 fileData->ownsGeneratedFile = false; 428 } 420 429 } 421 430 } … … 436 445 { 437 446 for (auto& element : m_elements) { 438 if ( element.m_type != FormDataElement::Type::Data)447 if (!WTF::holds_alternative<Vector<char>>(element.data)) 439 448 return nullptr; 440 449 } … … 447 456 return { }; 448 457 449 ASSERT(m_elements.first().m_type == FormDataElement::Type::EncodedBlob || m_elements.first().m_url.isNull()); 450 return m_elements.first().m_url; 458 if (auto* blobData = WTF::get_if<FormDataElement::EncodedBlobData>(m_elements.first().data)) 459 return blobData->url; 460 return { }; 451 461 } 452 462 -
trunk/Source/WebCore/platform/network/FormData.h
r226066 r236365 24 24 #include <wtf/Forward.h> 25 25 #include <wtf/RefCounted.h> 26 #include <wtf/Variant.h> 26 27 #include <wtf/Vector.h> 27 28 #include <wtf/text/WTFString.h> … … 35 36 class TextEncoding; 36 37 37 // FIXME: Convert this to a Variant of structs and remove "Type" and also the "m_" prefixes from the data members. 38 // The member functions can become non-member fucntions. 39 class FormDataElement { 40 public: 41 enum class Type { Data, EncodedFile, EncodedBlob }; 42 43 FormDataElement() 44 : m_type(Type::Data) 45 { 46 } 47 48 explicit FormDataElement(const Vector<char>& array) 49 : m_type(Type::Data) 50 , m_data(array) 51 { 52 } 53 54 FormDataElement(const String& filename, long long fileStart, long long fileLength, double expectedFileModificationTime, bool shouldGenerateFile) 55 : m_type(Type::EncodedFile) 56 , m_filename(filename) 57 , m_fileStart(fileStart) 58 , m_fileLength(fileLength) 59 , m_expectedFileModificationTime(expectedFileModificationTime) 60 , m_shouldGenerateFile(shouldGenerateFile) 61 , m_ownsGeneratedFile(false) 62 { 63 } 64 38 struct FormDataElement { 39 struct EncodedFileData; 40 struct EncodedBlobData; 41 using Data = Variant<Vector<char>, EncodedFileData, EncodedBlobData>; 42 43 FormDataElement() = default; 44 explicit FormDataElement(Data&& data) 45 : data(WTFMove(data)) { } 46 explicit FormDataElement(Vector<char>&& array) 47 : data(WTFMove(array)) { } 48 FormDataElement(const String& filename, int64_t fileStart, int64_t fileLength, double expectedFileModificationTime, bool shouldGenerateFile) 49 : data(EncodedFileData { filename, fileStart, fileLength, expectedFileModificationTime, { }, shouldGenerateFile, false }) { } 65 50 explicit FormDataElement(const URL& blobURL) 66 : m_type(Type::EncodedBlob) 67 , m_url(blobURL) 68 { 69 } 51 : data(EncodedBlobData { blobURL }) { } 70 52 71 53 uint64_t lengthInBytes() const; … … 73 55 FormDataElement isolatedCopy() const; 74 56 75 template<typename Encoder> void encode(Encoder&) const; 76 template<typename Decoder> static std::optional<FormDataElement> decode(Decoder&); 77 78 Type m_type; 79 Vector<char> m_data; 80 String m_filename; 81 URL m_url; // For Blob or URL. 82 int64_t m_fileStart; 83 int64_t m_fileLength; 84 double m_expectedFileModificationTime; 85 // FIXME: Generated file support in FormData is almost identical to Blob, they should be merged. 86 // We can't just switch to using Blobs for all files because EncodedFile form data elements do not 87 // have a valid m_expectedFileModificationTime, meaning we always upload the latest content from disk. 88 String m_generatedFilename; 89 bool m_shouldGenerateFile; 90 bool m_ownsGeneratedFile; 57 template<typename Encoder> void encode(Encoder& encoder) const 58 { 59 encoder << data; 60 } 61 template<typename Decoder> static std::optional<FormDataElement> decode(Decoder& decoder) 62 { 63 std::optional<Data> data; 64 decoder >> data; 65 if (!data) 66 return std::nullopt; 67 return FormDataElement(WTFMove(*data)); 68 } 69 70 struct EncodedFileData { 71 String filename; 72 int64_t fileStart { 0 }; 73 int64_t fileLength { 0 }; 74 double expectedFileModificationTime { 0 }; 75 String generatedFilename; 76 bool shouldGenerateFile { false }; 77 bool ownsGeneratedFile { false }; 78 79 // FIXME: Generated file support in FormData is almost identical to Blob, they should be merged. 80 // We can't just switch to using Blobs for all files because EncodedFile form data elements do not 81 // have a valid expectedFileModificationTime, meaning we always upload the latest content from disk. 82 83 EncodedFileData isolatedCopy() const 84 { 85 return { filename.isolatedCopy(), fileStart, fileLength, expectedFileModificationTime, generatedFilename.isolatedCopy(), shouldGenerateFile, ownsGeneratedFile }; 86 } 87 88 bool operator==(const EncodedFileData other) const 89 { 90 return filename == other.filename 91 && fileStart == other.fileStart 92 && fileLength == other.fileLength 93 && expectedFileModificationTime == other.expectedFileModificationTime 94 && generatedFilename == other.generatedFilename 95 && shouldGenerateFile == other.shouldGenerateFile 96 && ownsGeneratedFile == other.ownsGeneratedFile; 97 } 98 template<typename Encoder> void encode(Encoder& encoder) const 99 { 100 encoder << filename << fileStart << fileLength << expectedFileModificationTime << generatedFilename << shouldGenerateFile; 101 } 102 template<typename Decoder> static std::optional<EncodedFileData> decode(Decoder& decoder) 103 { 104 std::optional<String> filename; 105 decoder >> filename; 106 if (!filename) 107 return std::nullopt; 108 109 std::optional<int64_t> fileStart; 110 decoder >> fileStart; 111 if (!fileStart) 112 return std::nullopt; 113 114 std::optional<int64_t> fileLength; 115 decoder >> fileLength; 116 if (!fileLength) 117 return std::nullopt; 118 119 std::optional<double> expectedFileModificationTime; 120 decoder >> expectedFileModificationTime; 121 if (!expectedFileModificationTime) 122 return std::nullopt; 123 124 std::optional<String> generatedFilename; 125 decoder >> generatedFilename; 126 if (!generatedFilename) 127 return std::nullopt; 128 129 std::optional<bool> shouldGenerateFile; 130 decoder >> shouldGenerateFile; 131 if (!shouldGenerateFile) 132 return std::nullopt; 133 134 bool ownsGeneratedFile = false; 135 136 return {{ 137 WTFMove(*filename), 138 WTFMove(*fileStart), 139 WTFMove(*fileLength), 140 WTFMove(*expectedFileModificationTime), 141 WTFMove(*generatedFilename), 142 WTFMove(*shouldGenerateFile), 143 WTFMove(ownsGeneratedFile) 144 }}; 145 } 146 147 }; 148 149 struct EncodedBlobData { 150 URL url; 151 152 bool operator==(const EncodedBlobData other) const 153 { 154 return url == other.url; 155 } 156 template<typename Encoder> void encode(Encoder& encoder) const 157 { 158 encoder << url; 159 } 160 template<typename Decoder> static std::optional<EncodedBlobData> decode(Decoder& decoder) 161 { 162 std::optional<URL> url; 163 decoder >> url; 164 if (!url) 165 return std::nullopt; 166 167 return {{ WTFMove(*url) }}; 168 } 169 }; 170 171 bool operator==(const FormDataElement& other) const 172 { 173 if (&other == this) 174 return true; 175 if (data.index() != other.data.index()) 176 return false; 177 if (!data.index()) 178 return WTF::get<0>(data) == WTF::get<0>(other.data); 179 if (data.index() == 1) 180 return WTF::get<1>(data) == WTF::get<1>(other.data); 181 return WTF::get<2>(data) == WTF::get<2>(other.data); 182 } 183 bool operator!=(const FormDataElement& other) const 184 { 185 return !(*this == other); 186 } 187 188 Data data; 91 189 }; 92 93 inline bool operator==(const FormDataElement& a, const FormDataElement& b)94 {95 if (&a == &b)96 return true;97 98 if (a.m_type != b.m_type)99 return false;100 if (a.m_type == FormDataElement::Type::Data)101 return a.m_data == b.m_data;102 if (a.m_type == FormDataElement::Type::EncodedFile)103 return a.m_filename == b.m_filename && a.m_fileStart == b.m_fileStart && a.m_fileLength == b.m_fileLength && a.m_expectedFileModificationTime == b.m_expectedFileModificationTime;104 if (a.m_type == FormDataElement::Type::EncodedBlob)105 return a.m_url == b.m_url;106 107 return true;108 }109 110 inline bool operator!=(const FormDataElement& a, const FormDataElement& b)111 {112 return !(a == b);113 }114 115 template<typename Encoder>116 void FormDataElement::encode(Encoder& encoder) const117 {118 encoder.encodeEnum(m_type);119 120 switch (m_type) {121 case Type::Data:122 encoder << m_data;123 break;124 125 case Type::EncodedFile:126 encoder << m_filename;127 encoder << m_generatedFilename;128 encoder << m_shouldGenerateFile;129 encoder << m_fileStart;130 encoder << m_fileLength;131 encoder << m_expectedFileModificationTime;132 break;133 134 case Type::EncodedBlob:135 encoder << m_url.string();136 break;137 }138 }139 140 template<typename Decoder>141 std::optional<FormDataElement> FormDataElement::decode(Decoder& decoder)142 {143 FormDataElement result;144 if (!decoder.decodeEnum(result.m_type))145 return std::nullopt;146 147 switch (result.m_type) {148 case Type::Data:149 if (!decoder.decode(result.m_data))150 return std::nullopt;151 152 return WTFMove(result);153 154 case Type::EncodedFile:155 if (!decoder.decode(result.m_filename))156 return std::nullopt;157 if (!decoder.decode(result.m_generatedFilename))158 return std::nullopt;159 if (!decoder.decode(result.m_shouldGenerateFile))160 return std::nullopt;161 result.m_ownsGeneratedFile = false;162 if (!decoder.decode(result.m_fileStart))163 return std::nullopt;164 if (!decoder.decode(result.m_fileLength))165 return std::nullopt;166 167 if (result.m_fileLength != BlobDataItem::toEndOfFile && result.m_fileLength < result.m_fileStart)168 return std::nullopt;169 170 if (!decoder.decode(result.m_expectedFileModificationTime))171 return std::nullopt;172 173 return WTFMove(result);174 175 case Type::EncodedBlob: {176 String blobURLString;177 if (!decoder.decode(blobURLString))178 return std::nullopt;179 180 result.m_url = URL(URL(), blobURLString);181 182 return WTFMove(result);183 }184 }185 186 return std::nullopt;187 }188 190 189 191 class FormData : public RefCounted<FormData> { … … 198 200 WEBCORE_EXPORT static Ref<FormData> create(const void*, size_t); 199 201 static Ref<FormData> create(const CString&); 202 static Ref<FormData> create(Vector<char>&&); 200 203 static Ref<FormData> create(const Vector<char>&); 201 204 static Ref<FormData> create(const Vector<uint8_t>&); … … 218 221 WEBCORE_EXPORT void appendFileRange(const String& filename, long long start, long long length, double expectedModificationTime, bool shouldGenerateFile = false); 219 222 WEBCORE_EXPORT void appendBlob(const URL& blobURL); 220 char* expandDataStore(size_t);221 223 222 224 Vector<char> flatten() const; // omits files -
trunk/Source/WebCore/platform/network/cf/FormDataStreamCFNet.cpp
r235521 r236365 137 137 FormDataElement& nextInput = form->remainingElements.last(); 138 138 139 if (nextInput.m_type == FormDataElement::Type::Data) { 140 size_t size = nextInput.m_data.size(); 141 MallocPtr<char> data = nextInput.m_data.releaseBuffer(); 142 form->currentStream = CFReadStreamCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(data.get()), size, kCFAllocatorNull); 143 form->currentData = WTFMove(data); 144 } else { 145 // Check if the file has been changed or not if required. 146 if (FileSystem::isValidFileTime(nextInput.m_expectedFileModificationTime)) { 147 time_t fileModificationTime; 148 if (!FileSystem::getFileModificationTime(nextInput.m_filename, fileModificationTime) || fileModificationTime != static_cast<time_t>(nextInput.m_expectedFileModificationTime)) 139 bool success = switchOn(nextInput.data, 140 [form] (Vector<char>& bytes) { 141 size_t size = bytes.size(); 142 MallocPtr<char> data = bytes.releaseBuffer(); 143 form->currentStream = CFReadStreamCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(data.get()), size, kCFAllocatorNull); 144 form->currentData = WTFMove(data); 145 return true; 146 }, [form] (const FormDataElement::EncodedFileData& fileData) { 147 // Check if the file has been changed or not if required. 148 if (FileSystem::isValidFileTime(fileData.expectedFileModificationTime)) { 149 time_t fileModificationTime; 150 if (!FileSystem::getFileModificationTime(fileData.filename, fileModificationTime) || fileModificationTime != static_cast<time_t>(fileData.expectedFileModificationTime)) 151 return false; 152 } 153 const String& path = fileData.shouldGenerateFile ? fileData.generatedFilename : fileData.filename; 154 form->currentStream = CFReadStreamCreateWithFile(0, FileSystem::pathAsURL(path).get()); 155 if (!form->currentStream) { 156 // The file must have been removed or become unreadable. 149 157 return false; 150 } 151 const String& path = nextInput.m_shouldGenerateFile ? nextInput.m_generatedFilename : nextInput.m_filename; 152 form->currentStream = CFReadStreamCreateWithFile(0, FileSystem::pathAsURL(path).get()); 153 if (!form->currentStream) { 154 // The file must have been removed or become unreadable. 158 } 159 if (fileData.fileStart > 0) { 160 RetainPtr<CFNumberRef> position = adoptCF(CFNumberCreate(0, kCFNumberLongLongType, &fileData.fileStart)); 161 CFReadStreamSetProperty(form->currentStream, kCFStreamPropertyFileCurrentOffset, position.get()); 162 } 163 form->currentStreamRangeLength = fileData.fileLength; 164 return true; 165 }, [] (const FormDataElement::EncodedBlobData&) { 166 ASSERT_NOT_REACHED(); 155 167 return false; 156 168 } 157 if (nextInput.m_fileStart > 0) { 158 RetainPtr<CFNumberRef> position = adoptCF(CFNumberCreate(0, kCFNumberLongLongType, &nextInput.m_fileStart)); 159 CFReadStreamSetProperty(form->currentStream, kCFStreamPropertyFileCurrentOffset, position.get()); 160 } 161 form->currentStreamRangeLength = nextInput.m_fileLength; 162 } 169 ); 170 171 if (!success) 172 return false; 173 163 174 form->remainingElements.removeLast(); 164 175 … … 364 375 // Precompute the content length so CFNetwork doesn't use chunked mode. 365 376 unsigned long long length = 0; 366 367 for (auto& element : resolvedFormData->elements()) { 368 if (element.m_type == FormDataElement::Type::Data) 369 length += element.m_data.size(); 370 else { 371 // If we're sending the file range, use the existing range length for now. 372 // We will detect if the file has been changed right before we read the file and abort the operation if necessary. 373 if (element.m_fileLength != BlobDataItem::toEndOfFile) { 374 length += element.m_fileLength; 375 continue; 376 } 377 long long fileSize; 378 if (FileSystem::getFileSize(element.m_shouldGenerateFile ? element.m_generatedFilename : element.m_filename, fileSize)) 379 length += fileSize; 380 } 381 } 377 for (auto& element : resolvedFormData->elements()) 378 length += element.lengthInBytes(); 382 379 383 380 FormCreationContext formContext = { WTFMove(resolvedFormData), length }; … … 394 391 auto& elements = formData->elements(); 395 392 if (elements.size() == 1 && !formData->alwaysStream()) { 396 auto& element = elements[0]; 397 if (element.m_type == FormDataElement::Type::Data) { 398 auto& vector = element.m_data; 399 auto data = adoptCF(CFDataCreate(nullptr, reinterpret_cast<const UInt8*>(vector.data()), vector.size())); 393 if (auto* vector = WTF::get_if<Vector<char>>(elements[0].data)) { 394 auto data = adoptCF(CFDataCreate(nullptr, reinterpret_cast<const UInt8*>(vector->data()), vector->size())); 400 395 CFURLRequestSetHTTPRequestBody(request, data.get()); 401 396 return; … … 409 404 { 410 405 if (!stream) 411 return 0;406 return nullptr; 412 407 413 408 // Passing the pointer as property appears to be the only way to associate a stream with FormData. … … 418 413 RetainPtr<CFNumberRef> formDataPointerAsCFNumber = adoptCF(static_cast<CFNumberRef>(CFReadStreamCopyProperty(stream, formDataPointerPropertyName))); 419 414 if (!formDataPointerAsCFNumber) 420 return 0;415 return nullptr; 421 416 422 417 long formDataPointerAsNumber; 423 418 if (!CFNumberGetValue(formDataPointerAsCFNumber.get(), kCFNumberLongType, &formDataPointerAsNumber)) 424 return 0;419 return nullptr; 425 420 426 421 return reinterpret_cast<FormData*>(static_cast<intptr_t>(formDataPointerAsNumber)); -
trunk/Source/WebCore/platform/network/curl/CurlFormDataStream.cpp
r231333 r236365 104 104 m_isContentLengthUpdated = true; 105 105 106 for (const auto& element : m_formData->elements()) { 107 if (element.m_type == FormDataElement::Type::EncodedFile) { 108 long long fileSize; 109 if (FileSystem::getFileSize(element.m_filename, fileSize)) { 110 if (fileSize > maxCurlOffT) { 111 // File size is too big for specifying it to curl 112 m_shouldUseChunkTransfer = true; 113 } 114 115 m_totalSize += fileSize; 116 } else 117 m_shouldUseChunkTransfer = true; 118 } else 119 m_totalSize += element.m_data.size(); 120 } 106 for (const auto& element : m_formData->elements()) 107 m_totalSize += element.lengthInBytes(); 121 108 } 122 109 … … 135 122 const auto& element = m_formData->elements().at(m_elementPosition); 136 123 137 std::optional<size_t> readBytes;138 124 size_t bufferSize = size - totalReadBytes; 139 125 char* bufferPosition = buffer + totalReadBytes; 140 126 141 if (element.m_type == FormDataElement::Type::EncodedFile) 142 readBytes = readFromFile(element, bufferPosition, bufferSize); 143 else 144 readBytes = readFromData(element, bufferPosition, bufferSize); 127 std::optional<size_t> readBytes = switchOn(element.data, 128 [&] (const Vector<char>& bytes) { 129 return readFromData(bytes, bufferPosition, bufferSize); 130 }, [&] (const FormDataElement::EncodedFileData& fileData) { 131 return readFromFile(fileData, bufferPosition, bufferSize); 132 }, [] (const FormDataElement::EncodedBlobData& blobData) { 133 ASSERT_NOT_REACHED(); 134 return std::nullopt; 135 } 136 ); 145 137 146 138 if (!readBytes) … … 155 147 } 156 148 157 std::optional<size_t> CurlFormDataStream::readFromFile(const FormDataElement & element, char* buffer, size_t size)149 std::optional<size_t> CurlFormDataStream::readFromFile(const FormDataElement::EncodedFileData& fileData, char* buffer, size_t size) 158 150 { 159 151 if (m_fileHandle == FileSystem::invalidPlatformFileHandle) 160 m_fileHandle = FileSystem::openFile( element.m_filename, FileSystem::FileOpenMode::Read);152 m_fileHandle = FileSystem::openFile(fileData.filename, FileSystem::FileOpenMode::Read); 161 153 162 154 if (!FileSystem::isHandleValid(m_fileHandle)) { 163 LOG(Network, "Curl - Failed while trying to open %s for upload\n", element.m_filename.utf8().data());155 LOG(Network, "Curl - Failed while trying to open %s for upload\n", fileData.filename.utf8().data()); 164 156 m_fileHandle = FileSystem::invalidPlatformFileHandle; 165 157 return std::nullopt; … … 168 160 auto readBytes = FileSystem::readFromFile(m_fileHandle, buffer, size); 169 161 if (readBytes < 0) { 170 LOG(Network, "Curl - Failed while trying to read %s for upload\n", element.m_filename.utf8().data());162 LOG(Network, "Curl - Failed while trying to read %s for upload\n", fileData.filename.utf8().data()); 171 163 FileSystem::closeFile(m_fileHandle); 172 164 m_fileHandle = FileSystem::invalidPlatformFileHandle; … … 183 175 } 184 176 185 std::optional<size_t> CurlFormDataStream::readFromData(const FormDataElement& element, char* buffer, size_t size)177 std::optional<size_t> CurlFormDataStream::readFromData(const Vector<char>& data, char* buffer, size_t size) 186 178 { 187 size_t elementSize = element.m_data.size() - m_dataOffset;188 const char* elementBuffer = element.m_data.data() + m_dataOffset;179 size_t elementSize = data.size() - m_dataOffset; 180 const char* elementBuffer = data.data() + m_dataOffset; 189 181 190 182 size_t readBytes = elementSize > size ? size : elementSize; -
trunk/Source/WebCore/platform/network/curl/CurlFormDataStream.h
r231333 r236365 52 52 void computeContentLength(); 53 53 54 std::optional<size_t> readFromFile(const FormDataElement &, char*, size_t);55 std::optional<size_t> readFromData(const FormDataElement&, char*, size_t);54 std::optional<size_t> readFromFile(const FormDataElement::EncodedFileData&, char*, size_t); 55 std::optional<size_t> readFromData(const Vector<char>&, char*, size_t); 56 56 57 57 RefPtr<FormData> m_formData; -
trunk/Source/WebCore/platform/network/soup/ResourceRequestSoup.cpp
r235026 r236365 75 75 uint64_t bodySize = 0; 76 76 for (const auto& element : formData->elements()) { 77 switch (element.m_type) { 78 case FormDataElement::Type::Data: 79 bodySize += element.m_data.size(); 80 soup_message_body_append(soupMessage->request_body, SOUP_MEMORY_TEMPORARY, element.m_data.data(), element.m_data.size()); 81 break; 82 case FormDataElement::Type::EncodedFile: 83 if (RefPtr<SharedBuffer> buffer = SharedBuffer::createWithContentsOfFile(element.m_filename)) { 84 if (buffer->isEmpty()) 85 break; 86 87 GUniquePtr<SoupBuffer> soupBuffer(buffer->createSoupBuffer()); 88 bodySize += buffer->size(); 89 if (soupBuffer->length) 90 soup_message_body_append_buffer(soupMessage->request_body, soupBuffer.get()); 77 return switchOn(element.data, 78 [&] (const Vector<char>& bytes) { 79 bodySize += bytes.size(); 80 soup_message_body_append(soupMessage->request_body, SOUP_MEMORY_TEMPORARY, bytes.data(), bytes.size()); 81 }, [&] (const FormDataElement::EncodedFileData& fileData) { 82 if (RefPtr<SharedBuffer> buffer = SharedBuffer::createWithContentsOfFile(fileData.filename)) { 83 if (buffer->isEmpty()) 84 return; 85 86 GUniquePtr<SoupBuffer> soupBuffer(buffer->createSoupBuffer()); 87 bodySize += buffer->size(); 88 if (soupBuffer->length) 89 soup_message_body_append_buffer(soupMessage->request_body, soupBuffer.get()); 90 } 91 }, [&] (const FormDataElement::EncodedBlobData& blob) { 92 if (auto* blobData = static_cast<BlobRegistryImpl&>(blobRegistry()).getBlobDataFromURL(blob.url)) { 93 for (const auto& item : blobData->items()) 94 bodySize += appendEncodedBlobItemToSoupMessageBody(soupMessage, item); 95 } 91 96 } 92 break; 93 case FormDataElement::Type::EncodedBlob: 94 if (auto* blobData = static_cast<BlobRegistryImpl&>(blobRegistry()).getBlobDataFromURL(element.m_url)) { 95 for (const auto& item : blobData->items()) 96 bodySize += appendEncodedBlobItemToSoupMessageBody(soupMessage, item); 97 } 98 break; 99 } 97 ); 100 98 } 101 99 -
trunk/Source/WebKit/ChangeLog
r236344 r236365 1 2018-09-21 Alex Christensen <achristensen@webkit.org> 2 3 Use a Variant for FormDataElement 4 https://bugs.webkit.org/show_bug.cgi?id=189777 5 6 Reviewed by Chris Dumez. 7 8 * NetworkProcess/NetworkResourceLoadParameters.cpp: 9 (WebKit::NetworkResourceLoadParameters::encode const): 10 * NetworkProcess/NetworkResourceLoader.cpp: 11 * Shared/SessionState.h: 12 * WebProcess/WebCoreSupport/SessionStateConversion.cpp: 13 (WebKit::toHTTPBody): 14 1 15 2018-09-21 Alex Christensen <achristensen@webkit.org> 2 16 -
trunk/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.cpp
r235101 r236365 50 50 size_t fileCount = 0; 51 51 for (size_t i = 0, count = elements.size(); i < count; ++i) { 52 if ( elements[i].m_type == FormDataElement::Type::EncodedFile)52 if (WTF::holds_alternative<FormDataElement::EncodedFileData>(elements[i].data)) 53 53 ++fileCount; 54 54 } … … 59 59 for (size_t i = 0, count = elements.size(); i < count; ++i) { 60 60 const FormDataElement& element = elements[i]; 61 if ( element.m_type == FormDataElement::Type::EncodedFile) {62 const String& path = element.m_shouldGenerateFile ? element.m_generatedFilename : element.m_filename;61 if (auto* fileData = WTF::get_if<FormDataElement::EncodedFileData>(element.data)) { 62 const String& path = fileData->shouldGenerateFile ? fileData->generatedFilename : fileData->filename; 63 63 SandboxExtension::createHandle(path, SandboxExtension::Type::ReadOnly, requestBodySandboxExtensions[extensionIndex++]); 64 64 } -
trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp
r236216 r236365 113 113 if (originalRequest().httpBody()) { 114 114 for (const auto& element : originalRequest().httpBody()->elements()) { 115 if ( element.m_type == FormDataElement::Type::EncodedBlob)116 m_fileReferences.appendVector(NetworkBlobRegistry::singleton().filesInBlob(connection, element.m_url));115 if (auto* blobData = WTF::get_if<FormDataElement::EncodedBlobData>(element.data)) 116 m_fileReferences.appendVector(NetworkBlobRegistry::singleton().filesInBlob(connection, blobData->url)); 117 117 } 118 118 } -
trunk/Source/WebKit/Platform/IPC/SharedBufferDataReference.h
r235951 r236365 42 42 void encode(Encoder& encoder) const 43 43 { 44 WTF::visit(WTF::makeVisitor(44 switchOn(m_data, 45 45 [encoder = &encoder] (const Ref<const WebCore::SharedBuffer>& buffer) mutable { 46 46 uint64_t bufferSize = buffer->size(); … … 54 54 *encoder << bufferSize; 55 55 encoder->encodeFixedLengthData(pair.first, pair.second, 1); 56 }), m_data); 56 } 57 ); 57 58 } 58 59 -
trunk/Source/WebKit/Shared/SessionState.h
r230812 r236365 60 60 }; 61 61 62 // FIXME: This should be a Variant. It's also unclear why we don't just use FormDataElement here. 62 63 Type type = Type::Data; 63 64 -
trunk/Source/WebKit/WebProcess/WebCoreSupport/SessionStateConversion.cpp
r235205 r236365 43 43 HTTPBody::Element element; 44 44 45 switch (formDataElement.m_type) { 46 case FormDataElement::Type::Data: 47 element.type = HTTPBody::Element::Type::Data; 48 element.data = formDataElement.m_data; 49 break; 50 51 case FormDataElement::Type::EncodedFile: 52 element.filePath = formDataElement.m_filename; 53 element.fileStart = formDataElement.m_fileStart; 54 if (formDataElement.m_fileLength != BlobDataItem::toEndOfFile) 55 element.fileLength = formDataElement.m_fileLength; 56 if (formDataElement.m_expectedFileModificationTime != FileSystem::invalidFileTime()) 57 element.expectedFileModificationTime = formDataElement.m_expectedFileModificationTime; 58 break; 59 60 case FormDataElement::Type::EncodedBlob: 61 element.blobURLString = formDataElement.m_url.string(); 62 break; 63 } 45 switchOn(formDataElement.data, 46 [&] (const Vector<char>& bytes) { 47 element.type = HTTPBody::Element::Type::Data; 48 element.data = bytes; 49 }, [&] (const FormDataElement::EncodedFileData& fileData) { 50 element.filePath = fileData.filename; 51 element.fileStart = fileData.fileStart; 52 if (fileData.fileLength != BlobDataItem::toEndOfFile) 53 element.fileLength = fileData.fileLength; 54 if (fileData.expectedFileModificationTime != FileSystem::invalidFileTime()) 55 element.expectedFileModificationTime = fileData.expectedFileModificationTime; 56 }, [&] (const FormDataElement::EncodedBlobData& blobData) { 57 element.blobURLString = blobData.url.string(); 58 } 59 ); 64 60 65 61 httpBody.elements.append(WTFMove(element)); -
trunk/Source/WebKitLegacy/win/ChangeLog
r236099 r236365 1 2018-09-21 Alex Christensen <achristensen@webkit.org> 2 3 Use a Variant for FormDataElement 4 https://bugs.webkit.org/show_bug.cgi?id=189777 5 6 Reviewed by Chris Dumez. 7 8 * WebMutableURLRequest.cpp: 9 (WebMutableURLRequest::setHTTPBody): 10 1 11 2018-09-17 Fujii Hironori <Hironori.Fujii@sony.com> 2 12 -
trunk/Source/WebKitLegacy/win/WebMutableURLRequest.cpp
r232233 r236365 301 301 return E_FAIL; 302 302 303 RefPtr<FormData> httpBody = FormData::create(); 304 char* formData = httpBody->expandDataStore(stat.cbSize.LowPart); 305 303 size_t length = stat.cbSize.LowPart; 304 Vector<char> vector(length); 306 305 ULONG bytesRead = 0; 307 if (FAILED(data->Read( formData, stat.cbSize.LowPart, &bytesRead)))306 if (FAILED(data->Read(vector.data(), stat.cbSize.LowPart, &bytesRead))) 308 307 return E_FAIL; 309 310 m_request.setHTTPBody(WTFMove(httpBody)); 308 m_request.setHTTPBody(FormData::create(WTFMove(vector))); 311 309 return S_OK; 312 310 }
Note:
See TracChangeset
for help on using the changeset viewer.