Changeset 206805 in webkit


Ignore:
Timestamp:
Oct 5, 2016 12:08:38 AM (8 years ago)
Author:
Carlos Garcia Campos
Message:

[SOUP] Move request HTTP body handling to ResourceRequestSoup and simplify it
https://bugs.webkit.org/show_bug.cgi?id=162891

Reviewed by Michael Catanzaro.

We are currently adding the HTTP body to the message in ResourceHandleSoup, but we could do it as part of the
ResourceRequest::updateSoupMessage() method, since the HTTP body is indeed part of the request. The code can be
also simplified, especially the handling of files, by using SharedBuffer that already mmaps the file when
possible, instead of using GMappedFile API.

  • platform/SharedBuffer.h: Add createSoupBuffer() method.
  • platform/network/soup/ResourceHandleSoup.cpp:

(WebCore::createSoupMessageForHandleAndRequest):
(WebCore::milisecondsSinceRequest): Deleted.
(WebCore::ResourceHandle::didStartRequest): Deleted.
(WebCore::startingCallback): Deleted.
(WebCore::networkEventCallback): Deleted.
(WebCore::ResourceHandle::start): Deleted.
(WebCore::ResourceHandle::releaseForDownload): Deleted.
(WebCore::ResourceHandle::timeoutFired): Deleted.

  • platform/network/soup/ResourceRequest.h:
  • platform/network/soup/ResourceRequestSoup.cpp:

(WebCore::appendEncodedBlobItemToSoupMessageBody): Helper method to append the blob to the request message body.
(WebCore::ResourceRequest::updateSoupMessageBody): Add HTTPBody to the request message body.
(WebCore::ResourceRequest::updateSoupMessage): Call updateSoupMessageBody() to also update the body.

  • platform/soup/SharedBufferSoup.cpp:

(WebCore::SharedBuffer::createSoupBuffer): Returns a new SoupBuffer for the SharedBuffer.

Location:
trunk/Source/WebCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r206803 r206805  
     12016-10-05  Carlos Garcia Campos  <cgarcia@igalia.com>
     2
     3        [SOUP] Move request HTTP body handling to ResourceRequestSoup and simplify it
     4        https://bugs.webkit.org/show_bug.cgi?id=162891
     5
     6        Reviewed by Michael Catanzaro.
     7
     8        We are currently adding the HTTP body to the message in ResourceHandleSoup, but we could do it as part of the
     9        ResourceRequest::updateSoupMessage() method, since the HTTP body is indeed part of the request. The code can be
     10        also simplified, especially the handling of files, by using SharedBuffer that already mmaps the file when
     11        possible, instead of using GMappedFile API.
     12
     13        * platform/SharedBuffer.h: Add createSoupBuffer() method.
     14        * platform/network/soup/ResourceHandleSoup.cpp:
     15        (WebCore::createSoupMessageForHandleAndRequest):
     16        (WebCore::milisecondsSinceRequest): Deleted.
     17        (WebCore::ResourceHandle::didStartRequest): Deleted.
     18        (WebCore::startingCallback): Deleted.
     19        (WebCore::networkEventCallback): Deleted.
     20        (WebCore::ResourceHandle::start): Deleted.
     21        (WebCore::ResourceHandle::releaseForDownload): Deleted.
     22        (WebCore::ResourceHandle::timeoutFired): Deleted.
     23        * platform/network/soup/ResourceRequest.h:
     24        * platform/network/soup/ResourceRequestSoup.cpp:
     25        (WebCore::appendEncodedBlobItemToSoupMessageBody): Helper method to append the blob to the request message body.
     26        (WebCore::ResourceRequest::updateSoupMessageBody): Add HTTPBody to the request message body.
     27        (WebCore::ResourceRequest::updateSoupMessage): Call updateSoupMessageBody() to also update the body.
     28        * platform/soup/SharedBufferSoup.cpp:
     29        (WebCore::SharedBuffer::createSoupBuffer): Returns a new SoupBuffer for the SharedBuffer.
     30
    1312016-10-04  Chris Dumez  <cdumez@apple.com>
    232
  • trunk/Source/WebCore/platform/SharedBuffer.h

    r201761 r206805  
    7474
    7575#if USE(SOUP)
     76    GUniquePtr<SoupBuffer> createSoupBuffer(unsigned offset = 0, unsigned size = 0);
    7677    static Ref<SharedBuffer> wrapSoupBuffer(SoupBuffer*);
    7778#endif
  • trunk/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp

    r206732 r206805  
    6464#include <wtf/text/CString.h>
    6565
    66 #include "BlobData.h"
    67 #include "BlobRegistryImpl.h"
    68 
    6966namespace WebCore {
    7067
     
    613610    g_input_stream_read_async(d->m_inputStream.get(), const_cast<char*>(d->m_soupBuffer->data), d->m_soupBuffer->length,
    614611        G_PRIORITY_DEFAULT, d->m_cancellable.get(), readCallback, handle);
    615 }
    616 
    617 static bool addFileToSoupMessageBody(SoupMessage* message, const String& fileNameString, size_t offset, size_t lengthToSend, unsigned long& totalBodySize)
    618 {
    619     GUniqueOutPtr<GError> error;
    620     CString fileName = fileSystemRepresentation(fileNameString);
    621     GMappedFile* fileMapping = g_mapped_file_new(fileName.data(), false, &error.outPtr());
    622     if (error)
    623         return false;
    624 
    625     gsize bufferLength = lengthToSend;
    626     if (!lengthToSend)
    627         bufferLength = g_mapped_file_get_length(fileMapping);
    628     totalBodySize += bufferLength;
    629 
    630     SoupBuffer* soupBuffer = soup_buffer_new_with_owner(g_mapped_file_get_contents(fileMapping) + offset,
    631                                                         bufferLength,
    632                                                         fileMapping,
    633                                                         reinterpret_cast<GDestroyNotify>(g_mapped_file_unref));
    634     soup_message_body_append_buffer(message->request_body, soupBuffer);
    635     soup_buffer_free(soupBuffer);
    636     return true;
    637 }
    638 
    639 static bool blobIsOutOfDate(const BlobDataItem& blobItem)
    640 {
    641     ASSERT(blobItem.type() == BlobDataItem::Type::File);
    642     if (!isValidFileTime(blobItem.file()->expectedModificationTime()))
    643         return false;
    644 
    645     time_t fileModificationTime;
    646     if (!getFileModificationTime(blobItem.file()->path(), fileModificationTime))
    647         return true;
    648 
    649     return fileModificationTime != static_cast<time_t>(blobItem.file()->expectedModificationTime());
    650 }
    651 
    652 static void addEncodedBlobItemToSoupMessageBody(SoupMessage* message, const BlobDataItem& blobItem, unsigned long& totalBodySize)
    653 {
    654     if (blobItem.type() == BlobDataItem::Type::Data) {
    655         totalBodySize += blobItem.length();
    656         soup_message_body_append(message->request_body, SOUP_MEMORY_TEMPORARY, blobItem.data().data()->data() + blobItem.offset(), blobItem.length());
    657         return;
    658     }
    659 
    660     ASSERT(blobItem.type() == BlobDataItem::Type::File);
    661     if (blobIsOutOfDate(blobItem))
    662         return;
    663 
    664     addFileToSoupMessageBody(message, blobItem.file()->path(), blobItem.offset(), blobItem.length() == BlobDataItem::toEndOfFile ? 0 : blobItem.length(),  totalBodySize);
    665 }
    666 
    667 static void addEncodedBlobToSoupMessageBody(SoupMessage* message, const FormDataElement& element, unsigned long& totalBodySize)
    668 {
    669     RefPtr<BlobData> blobData = static_cast<BlobRegistryImpl&>(blobRegistry()).getBlobDataFromURL(URL(ParsedURLString, element.m_url));
    670     if (!blobData)
    671         return;
    672 
    673     for (size_t i = 0; i < blobData->items().size(); ++i)
    674         addEncodedBlobItemToSoupMessageBody(message, blobData->items()[i], totalBodySize);
    675 }
    676 
    677 static bool addFormElementsToSoupMessage(SoupMessage* message, const char*, FormData* httpBody, unsigned long& totalBodySize)
    678 {
    679     soup_message_body_set_accumulate(message->request_body, FALSE);
    680     size_t numElements = httpBody->elements().size();
    681     for (size_t i = 0; i < numElements; i++) {
    682         const FormDataElement& element = httpBody->elements()[i];
    683 
    684         if (element.m_type == FormDataElement::Type::Data) {
    685             totalBodySize += element.m_data.size();
    686             soup_message_body_append(message->request_body, SOUP_MEMORY_TEMPORARY,
    687                                      element.m_data.data(), element.m_data.size());
    688             continue;
    689         }
    690 
    691         if (element.m_type == FormDataElement::Type::EncodedFile) {
    692             if (!addFileToSoupMessageBody(message ,
    693                                          element.m_filename,
    694                                          0 /* offset */,
    695                                          0 /* lengthToSend */,
    696                                          totalBodySize))
    697                 return false;
    698             continue;
    699         }
    700 
    701         ASSERT(element.m_type == FormDataElement::Type::EncodedBlob);
    702         addEncodedBlobToSoupMessageBody(message, element, totalBodySize);
    703     }
    704     return true;
    705612}
    706613
     
    789696    SoupMessage* soupMessage = d->m_soupMessage.get();
    790697    request.updateSoupMessage(soupMessage);
     698    d->m_bodySize = soupMessage->request_body->length;
    791699
    792700    g_object_set_data(G_OBJECT(soupMessage), "handle", handle);
     
    796704        soup_message_disable_feature(soupMessage, SOUP_TYPE_AUTH_MANAGER);
    797705
    798     FormData* httpBody = request.httpBody();
    799     CString contentType = request.httpContentType().utf8().data();
    800     if (httpBody && !httpBody->isEmpty() && !addFormElementsToSoupMessage(soupMessage, contentType.data(), httpBody, d->m_bodySize)) {
    801         // We failed to prepare the body data, so just fail this load.
    802         d->m_soupMessage.clear();
    803         return false;
    804     }
    805 
    806706    // Make sure we have an Accept header for subresources; some sites
    807707    // want this to serve some of their subresources
     
    813713    // in the backend here instead of in XHR code since in XHR CORS checking prevents us from this kind of
    814714    // late header manipulation.
    815     if ((request.httpMethod() == "POST" || request.httpMethod() == "PUT")
    816         && (!request.httpBody() || request.httpBody()->isEmpty()))
     715    if ((request.httpMethod() == "POST" || request.httpMethod() == "PUT") && !d->m_bodySize)
    817716        soup_message_headers_set_content_length(soupMessage->request_headers, 0);
    818717
  • trunk/Source/WebCore/platform/network/soup/ResourceRequest.h

    r206740 r206805  
    115115
    116116        void updateSoupMessageMembers(SoupMessage*) const;
     117        void updateSoupMessageBody(SoupMessage*) const;
    117118        void doUpdatePlatformRequest() { }
    118119        void doUpdateResourceRequest() { }
  • trunk/Source/WebCore/platform/network/soup/ResourceRequestSoup.cpp

    r206740 r206805  
    2121
    2222#if USE(SOUP)
    23 
    2423#include "ResourceRequest.h"
    2524
     25#include "BlobData.h"
     26#include "BlobRegistryImpl.h"
    2627#include "GUniquePtrSoup.h"
    2728#include "HTTPParsers.h"
    2829#include "MIMETypeRegistry.h"
     30#include "SharedBuffer.h"
    2931#include "WebKitSoupRequestGeneric.h"
    3032#include <wtf/text/CString.h>
     
    3234
    3335namespace WebCore {
     36
     37static uint64_t appendEncodedBlobItemToSoupMessageBody(SoupMessage* soupMessage, const BlobDataItem& blobItem)
     38{
     39    switch (blobItem.type()) {
     40    case BlobDataItem::Type::Data:
     41        soup_message_body_append(soupMessage->request_body, SOUP_MEMORY_TEMPORARY, blobItem.data().data()->data() + blobItem.offset(), blobItem.length());
     42        return blobItem.length();
     43    case BlobDataItem::Type::File: {
     44        if (!isValidFileTime(blobItem.file()->expectedModificationTime()))
     45            return 0;
     46
     47        time_t fileModificationTime;
     48        if (!getFileModificationTime(blobItem.file()->path(), fileModificationTime)
     49            || fileModificationTime != static_cast<time_t>(blobItem.file()->expectedModificationTime()))
     50            return 0;
     51
     52        if (RefPtr<SharedBuffer> buffer = SharedBuffer::createWithContentsOfFile(blobItem.file()->path())) {
     53            GUniquePtr<SoupBuffer> soupBuffer(buffer->createSoupBuffer(blobItem.offset(), blobItem.length() == BlobDataItem::toEndOfFile ? 0 : blobItem.length()));
     54            soup_message_body_append_buffer(soupMessage->request_body, soupBuffer.get());
     55            return soupBuffer->length;
     56        }
     57        break;
     58    }
     59    }
     60
     61    return 0;
     62}
     63
     64void ResourceRequest::updateSoupMessageBody(SoupMessage* soupMessage) const
     65{
     66    auto* formData = httpBody();
     67    if (!formData || formData->isEmpty())
     68        return;
     69
     70    soup_message_body_set_accumulate(soupMessage->request_body, FALSE);
     71    uint64_t bodySize = 0;
     72    for (const auto& element : formData->elements()) {
     73        switch (element.m_type) {
     74        case FormDataElement::Type::Data:
     75            bodySize += element.m_data.size();
     76            soup_message_body_append(soupMessage->request_body, SOUP_MEMORY_TEMPORARY, element.m_data.data(), element.m_data.size());
     77            break;
     78        case FormDataElement::Type::EncodedFile:
     79            if (RefPtr<SharedBuffer> buffer = SharedBuffer::createWithContentsOfFile(element.m_filename)) {
     80                GUniquePtr<SoupBuffer> soupBuffer(buffer->createSoupBuffer());
     81                bodySize += buffer->size();
     82                soup_message_body_append_buffer(soupMessage->request_body, soupBuffer.get());
     83            }
     84            break;
     85        case FormDataElement::Type::EncodedBlob:
     86            if (auto* blobData = static_cast<BlobRegistryImpl&>(blobRegistry()).getBlobDataFromURL(element.m_url)) {
     87                for (const auto& item : blobData->items())
     88                    bodySize += appendEncodedBlobItemToSoupMessageBody(soupMessage, item);
     89            }
     90            break;
     91        }
     92    }
     93
     94    ASSERT(bodySize == static_cast<uint64_t>(soupMessage->request_body->length));
     95}
    3496
    3597void ResourceRequest::updateSoupMessageMembers(SoupMessage* soupMessage) const
     
    78140
    79141    updateSoupMessageMembers(soupMessage);
     142    updateSoupMessageBody(soupMessage);
    80143}
    81144
  • trunk/Source/WebCore/platform/soup/SharedBufferSoup.cpp

    r201761 r206805  
    3737{
    3838    return adoptRef(*new SharedBuffer(soupBuffer));
     39}
     40
     41GUniquePtr<SoupBuffer> SharedBuffer::createSoupBuffer(unsigned offset, unsigned size)
     42{
     43    if (m_soupBuffer && !offset && !size) {
     44        GUniquePtr<SoupBuffer> buffer(soup_buffer_copy(m_soupBuffer.get()));
     45        return buffer;
     46    }
     47
     48    ref();
     49    GUniquePtr<SoupBuffer> buffer(soup_buffer_new_with_owner(data() + offset, size ? size : this->size(), this, [](void* data) {
     50        static_cast<SharedBuffer*>(data)->deref();
     51    }));
     52    return buffer;
    3953}
    4054
Note: See TracChangeset for help on using the changeset viewer.