Changeset 236365 in webkit


Ignore:
Timestamp:
Sep 21, 2018, 3:50:36 PM (7 years ago)
Author:
achristensen@apple.com
Message:

Use a Variant for FormDataElement
https://bugs.webkit.org/show_bug.cgi?id=189777

Reviewed by Chris Dumez.

Source/WebCore:

  • platform/network/FormData.cpp:

(WebCore::FormData::FormData):
(WebCore::FormDataElement::lengthInBytes const):
(WebCore::FormDataElement::isolatedCopy const):
(WebCore::FormData::appendData):
(WebCore::FormData::flatten const):
(WebCore::FormData::resolveBlobReferences):
(WebCore::FormData::generateFiles):
(WebCore::FormData::hasGeneratedFiles const):
(WebCore::FormData::hasOwnedGeneratedFiles const):
(WebCore::FormData::removeGeneratedFilesIfNeeded):
(WebCore::FormData::asSharedBuffer const):
(WebCore::FormData::asBlobURL const):
(WebCore::FormData::expandDataStore): Deleted.

  • platform/network/FormData.h:

(WebCore::FormDataElement::FormDataElement):
(WebCore::FormDataElement::encode const):
(WebCore::FormDataElement::decode):
(WebCore::FormDataElement::EncodedFileData::isolatedCopy const):
(WebCore::FormDataElement::EncodedFileData::operator== const):
(WebCore::FormDataElement::EncodedFileData::encode const):
(WebCore::FormDataElement::EncodedFileData::decode):
(WebCore::FormDataElement::EncodedBlobData::operator== const):
(WebCore::FormDataElement::EncodedBlobData::encode const):
(WebCore::FormDataElement::EncodedBlobData::decode):
(WebCore::FormDataElement::operator== const):
(WebCore::FormDataElement::operator!= const):

  • platform/network/cf/FormDataStreamCFNet.cpp:

(WebCore::advanceCurrentStream):
(WebCore::createHTTPBodyCFReadStream):
(WebCore::setHTTPBody):

  • platform/network/curl/CurlFormDataStream.cpp:

(WebCore::CurlFormDataStream::computeContentLength):
(WebCore::CurlFormDataStream::read):
(WebCore::CurlFormDataStream::readFromFile):
(WebCore::CurlFormDataStream::readFromData):

  • platform/network/curl/CurlFormDataStream.h:

Source/WebKit:

  • NetworkProcess/NetworkResourceLoadParameters.cpp:

(WebKit::NetworkResourceLoadParameters::encode const):

  • NetworkProcess/NetworkResourceLoader.cpp:
  • Shared/SessionState.h:
  • WebProcess/WebCoreSupport/SessionStateConversion.cpp:

(WebKit::toHTTPBody):

Source/WebKitLegacy/win:

  • WebMutableURLRequest.cpp:

(WebMutableURLRequest::setHTTPBody):

Location:
trunk/Source
Files:
16 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r236356 r236365  
     12018-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
    1462018-09-20  Simon Fraser  <simon.fraser@apple.com>
    247
  • trunk/Source/WebCore/html/HTMLMediaElement.cpp

    r236006 r236365  
    14851485            // 2. End the synchronous section, continuing the remaining steps in parallel.
    14861486            // 3. Run the resource fetch algorithm with the assigned media provider object.
    1487             WTF::visit(WTF::makeVisitor(
     1487            switchOn(m_mediaProvider.value(),
    14881488#if ENABLE(MEDIA_STREAM)
    14891489                [this](RefPtr<MediaStream> stream) { m_mediaStreamSrcObject = stream; },
     
    14931493#endif
    14941494                [this](RefPtr<Blob> blob) { m_blob = blob; }
    1495             ), m_mediaProvider.value());
     1495            );
    14961496
    14971497            ContentType contentType;
  • trunk/Source/WebCore/platform/network/FormData.cpp

    r235573 r236365  
    5454    // but just in case, make sure the new FormData is ready to generate its own files.
    5555    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;
    5959        }
    6060    }
     
    9191}
    9292
     93Ref<FormData> FormData::create(Vector<char>&& vector)
     94{
     95    auto data = create();
     96    data->m_elements.append(WTFMove(vector));
     97    return data;
     98}
     99
    93100Ref<FormData> FormData::create(const Vector<uint8_t>& vector)
    94101{
     
    133140uint64_t FormDataElement::lengthInBytes() const
    134141{
    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    );
    151156}
    152157
    153158FormDataElement FormDataElement::isolatedCopy() const
    154159{
    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    );
    165171}
    166172
    167173void FormData::appendData(const void* data, size_t size)
    168174{
    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));
    170185}
    171186
     
    280295}
    281296
    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 
    297297Vector<char> FormData::flatten() const
    298298{
     
    300300    Vector<char> data;
    301301    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());
    304304    }
    305305    return data;
     
    341341    bool hasBlob = false;
    342342    for (auto& element : m_elements) {
    343         if (element.m_type == FormDataElement::Type::EncodedBlob) {
     343        if (WTF::holds_alternative<FormDataElement::EncodedBlobData>(element.data)) {
    344344            hasBlob = true;
    345345            break;
     
    356356
    357357    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        );
    366367    }
    367368    return newFormData;
     
    375376
    376377    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            }
    385388        }
    386389    }
     
    390393{
    391394    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        }
    394399    }
    395400    return false;
     
    399404{
    400405    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            }
    404411        }
    405412    }
     
    410417{
    411418    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            }
    420429        }
    421430    }
     
    436445{
    437446    for (auto& element : m_elements) {
    438         if (element.m_type != FormDataElement::Type::Data)
     447        if (!WTF::holds_alternative<Vector<char>>(element.data))
    439448            return nullptr;
    440449    }
     
    447456        return { };
    448457
    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 { };
    451461}
    452462
  • trunk/Source/WebCore/platform/network/FormData.h

    r226066 r236365  
    2424#include <wtf/Forward.h>
    2525#include <wtf/RefCounted.h>
     26#include <wtf/Variant.h>
    2627#include <wtf/Vector.h>
    2728#include <wtf/text/WTFString.h>
     
    3536class TextEncoding;
    3637
    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 
     38struct 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 }) { }
    6550    explicit FormDataElement(const URL& blobURL)
    66         : m_type(Type::EncodedBlob)
    67         , m_url(blobURL)
    68     {
    69     }
     51        : data(EncodedBlobData { blobURL }) { }
    7052
    7153    uint64_t lengthInBytes() const;
     
    7355    FormDataElement isolatedCopy() const;
    7456
    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;
    91189};
    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) const
    117 {
    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 }
    188190
    189191class FormData : public RefCounted<FormData> {
     
    198200    WEBCORE_EXPORT static Ref<FormData> create(const void*, size_t);
    199201    static Ref<FormData> create(const CString&);
     202    static Ref<FormData> create(Vector<char>&&);
    200203    static Ref<FormData> create(const Vector<char>&);
    201204    static Ref<FormData> create(const Vector<uint8_t>&);
     
    218221    WEBCORE_EXPORT void appendFileRange(const String& filename, long long start, long long length, double expectedModificationTime, bool shouldGenerateFile = false);
    219222    WEBCORE_EXPORT void appendBlob(const URL& blobURL);
    220     char* expandDataStore(size_t);
    221223
    222224    Vector<char> flatten() const; // omits files
  • trunk/Source/WebCore/platform/network/cf/FormDataStreamCFNet.cpp

    r235521 r236365  
    137137    FormDataElement& nextInput = form->remainingElements.last();
    138138
    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.
    149157                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();
    155167            return false;
    156168        }
    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
    163174    form->remainingElements.removeLast();
    164175
     
    364375    // Precompute the content length so CFNetwork doesn't use chunked mode.
    365376    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();
    382379
    383380    FormCreationContext formContext = { WTFMove(resolvedFormData), length };
     
    394391    auto& elements = formData->elements();
    395392    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()));
    400395            CFURLRequestSetHTTPRequestBody(request, data.get());
    401396            return;
     
    409404{
    410405    if (!stream)
    411         return 0;
     406        return nullptr;
    412407
    413408    // Passing the pointer as property appears to be the only way to associate a stream with FormData.
     
    418413    RetainPtr<CFNumberRef> formDataPointerAsCFNumber = adoptCF(static_cast<CFNumberRef>(CFReadStreamCopyProperty(stream, formDataPointerPropertyName)));
    419414    if (!formDataPointerAsCFNumber)
    420         return 0;
     415        return nullptr;
    421416
    422417    long formDataPointerAsNumber;
    423418    if (!CFNumberGetValue(formDataPointerAsCFNumber.get(), kCFNumberLongType, &formDataPointerAsNumber))
    424         return 0;
     419        return nullptr;
    425420
    426421    return reinterpret_cast<FormData*>(static_cast<intptr_t>(formDataPointerAsNumber));
  • trunk/Source/WebCore/platform/network/curl/CurlFormDataStream.cpp

    r231333 r236365  
    104104    m_isContentLengthUpdated = true;
    105105
    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();
    121108}
    122109
     
    135122        const auto& element = m_formData->elements().at(m_elementPosition);
    136123
    137         std::optional<size_t> readBytes;
    138124        size_t bufferSize = size - totalReadBytes;
    139125        char* bufferPosition = buffer + totalReadBytes;
    140126
    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        );
    145137
    146138        if (!readBytes)
     
    155147}
    156148
    157 std::optional<size_t> CurlFormDataStream::readFromFile(const FormDataElement& element, char* buffer, size_t size)
     149std::optional<size_t> CurlFormDataStream::readFromFile(const FormDataElement::EncodedFileData& fileData, char* buffer, size_t size)
    158150{
    159151    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);
    161153
    162154    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());
    164156        m_fileHandle = FileSystem::invalidPlatformFileHandle;
    165157        return std::nullopt;
     
    168160    auto readBytes = FileSystem::readFromFile(m_fileHandle, buffer, size);
    169161    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());
    171163        FileSystem::closeFile(m_fileHandle);
    172164        m_fileHandle = FileSystem::invalidPlatformFileHandle;
     
    183175}
    184176
    185 std::optional<size_t> CurlFormDataStream::readFromData(const FormDataElement& element, char* buffer, size_t size)
     177std::optional<size_t> CurlFormDataStream::readFromData(const Vector<char>& data, char* buffer, size_t size)
    186178{
    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;
    189181
    190182    size_t readBytes = elementSize > size ? size : elementSize;
  • trunk/Source/WebCore/platform/network/curl/CurlFormDataStream.h

    r231333 r236365  
    5252    void computeContentLength();
    5353
    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);
    5656
    5757    RefPtr<FormData> m_formData;
  • trunk/Source/WebCore/platform/network/soup/ResourceRequestSoup.cpp

    r235026 r236365  
    7575    uint64_t bodySize = 0;
    7676    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                }
    9196            }
    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        );
    10098    }
    10199
  • trunk/Source/WebKit/ChangeLog

    r236344 r236365  
     12018-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
    1152018-09-21  Alex Christensen  <achristensen@webkit.org>
    216
  • trunk/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.cpp

    r235101 r236365  
    5050        size_t fileCount = 0;
    5151        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))
    5353                ++fileCount;
    5454        }
     
    5959        for (size_t i = 0, count = elements.size(); i < count; ++i) {
    6060            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;
    6363                SandboxExtension::createHandle(path, SandboxExtension::Type::ReadOnly, requestBodySandboxExtensions[extensionIndex++]);
    6464            }
  • trunk/Source/WebKit/NetworkProcess/NetworkResourceLoader.cpp

    r236216 r236365  
    113113    if (originalRequest().httpBody()) {
    114114        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));
    117117        }
    118118    }
  • trunk/Source/WebKit/Platform/IPC/SharedBufferDataReference.h

    r235951 r236365  
    4242    void encode(Encoder& encoder) const
    4343    {
    44         WTF::visit(WTF::makeVisitor(
     44        switchOn(m_data,
    4545            [encoder = &encoder] (const Ref<const WebCore::SharedBuffer>& buffer) mutable {
    4646                uint64_t bufferSize = buffer->size();
     
    5454                *encoder << bufferSize;
    5555                encoder->encodeFixedLengthData(pair.first, pair.second, 1);
    56             }), m_data);
     56            }
     57        );
    5758    }
    5859
  • trunk/Source/WebKit/Shared/SessionState.h

    r230812 r236365  
    6060        };
    6161
     62        // FIXME: This should be a Variant. It's also unclear why we don't just use FormDataElement here.
    6263        Type type = Type::Data;
    6364
  • trunk/Source/WebKit/WebProcess/WebCoreSupport/SessionStateConversion.cpp

    r235205 r236365  
    4343        HTTPBody::Element element;
    4444
    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        );
    6460
    6561        httpBody.elements.append(WTFMove(element));
  • trunk/Source/WebKitLegacy/win/ChangeLog

    r236099 r236365  
     12018-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
    1112018-09-17  Fujii Hironori  <Hironori.Fujii@sony.com>
    212
  • trunk/Source/WebKitLegacy/win/WebMutableURLRequest.cpp

    r232233 r236365  
    301301        return E_FAIL;
    302302
    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);
    306305    ULONG bytesRead = 0;
    307     if (FAILED(data->Read(formData, stat.cbSize.LowPart, &bytesRead)))
     306    if (FAILED(data->Read(vector.data(), stat.cbSize.LowPart, &bytesRead)))
    308307        return E_FAIL;
    309 
    310     m_request.setHTTPBody(WTFMove(httpBody));
     308    m_request.setHTTPBody(FormData::create(WTFMove(vector)));
    311309    return S_OK;
    312310}
Note: See TracChangeset for help on using the changeset viewer.