Changeset 249481 in webkit


Ignore:
Timestamp:
Sep 4, 2019 9:46:55 AM (5 years ago)
Author:
youenn@apple.com
Message:

Abstract out WebSocketChannel message queue
https://bugs.webkit.org/show_bug.cgi?id=201359

Reviewed by Alex Christensen.

Source/WebCore:

Move BlobLoader in its own file.
Introduce NetworkSendQueue class to handle the sending of messages, some of them being blobs.
This class ensures that messages will be sent in order, even though blob data is resolved asynchronously.

Covered by existing tests.

  • Headers.cmake:
  • Sources.txt:
  • WebCore.xcodeproj/project.pbxproj:
  • fileapi/BlobLoader.h: Added.

(WebCore::BlobLoader::BlobLoader):
(WebCore::BlobLoader::~BlobLoader):
(WebCore::BlobLoader::didFinishLoading):
(WebCore::BlobLoader::didFail):
(WebCore::BlobLoader::complete):

  • fileapi/NetworkSendQueue.cpp: Added.

(WebCore::NetworkSendQueue::NetworkSendQueue):
(WebCore::NetworkSendQueue::enqueue):
(WebCore::NetworkSendQueue::clear):
(WebCore::NetworkSendQueue::processMessages):

  • fileapi/NetworkSendQueue.h: Added.

Source/WebKit:

Make use of newly added NetworkSendQueue.

  • WebProcess/Network/WebSocketChannel.cpp:

(WebKit::WebSocketChannel::createMessageQueue):
(WebKit::WebSocketChannel::WebSocketChannel):
(WebKit::WebSocketChannel::send):
(WebKit::WebSocketChannel::disconnect):

  • WebProcess/Network/WebSocketChannel.h:
Location:
trunk/Source
Files:
3 added
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r249480 r249481  
     12019-09-04  Youenn Fablet  <youenn@apple.com>
     2
     3        Abstract out WebSocketChannel message queue
     4        https://bugs.webkit.org/show_bug.cgi?id=201359
     5
     6        Reviewed by Alex Christensen.
     7
     8        Move BlobLoader in its own file.
     9        Introduce NetworkSendQueue class to handle the sending of messages, some of them being blobs.
     10        This class ensures that messages will be sent in order, even though blob data is resolved asynchronously.
     11
     12        Covered by existing tests.
     13
     14        * Headers.cmake:
     15        * Sources.txt:
     16        * WebCore.xcodeproj/project.pbxproj:
     17        * fileapi/BlobLoader.h: Added.
     18        (WebCore::BlobLoader::BlobLoader):
     19        (WebCore::BlobLoader::~BlobLoader):
     20        (WebCore::BlobLoader::didFinishLoading):
     21        (WebCore::BlobLoader::didFail):
     22        (WebCore::BlobLoader::complete):
     23        * fileapi/NetworkSendQueue.cpp: Added.
     24        (WebCore::NetworkSendQueue::NetworkSendQueue):
     25        (WebCore::NetworkSendQueue::enqueue):
     26        (WebCore::NetworkSendQueue::clear):
     27        (WebCore::NetworkSendQueue::processMessages):
     28        * fileapi/NetworkSendQueue.h: Added.
     29
    1302019-09-04  Rob Buis  <rbuis@igalia.com>
    231
  • trunk/Source/WebCore/Headers.cmake

    r249217 r249481  
    520520    fileapi/FileReaderLoader.h
    521521    fileapi/FileReaderLoaderClient.h
     522    fileapi/NetworkSendQueue.h
    522523
    523524    history/BackForwardClient.h
  • trunk/Source/WebCore/Sources.txt

    r249378 r249481  
    10571057fileapi/FileReaderLoader.cpp
    10581058fileapi/FileReaderSync.cpp
     1059fileapi/NetworkSendQueue.cpp
    10591060fileapi/ThreadableBlobRegistry.cpp
    10601061
  • trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj

    r249379 r249481  
    11241124                41DEFCB61E56C1BD000D9E5F /* JSDOMMapLike.h in Headers */ = {isa = PBXBuildFile; fileRef = 41DEFCB41E56C1B9000D9E5F /* JSDOMMapLike.h */; };
    11251125                41E1B1D10FF5986900576B3B /* AbstractWorker.h in Headers */ = {isa = PBXBuildFile; fileRef = 41E1B1CB0FF5986900576B3B /* AbstractWorker.h */; };
     1126                41E9DCE7231974BF00F35949 /* BlobLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 41E9DCE4231973FE00F35949 /* BlobLoader.h */; settings = {ATTRIBUTES = (Private, ); }; };
     1127                41E9DCE92319CA7600F35949 /* NetworkSendQueue.h in Headers */ = {isa = PBXBuildFile; fileRef = 41E9DCE82319CA7500F35949 /* NetworkSendQueue.h */; settings = {ATTRIBUTES = (Private, ); }; };
    11261128                41F062140F5F192600A07EAC /* InspectorDatabaseResource.h in Headers */ = {isa = PBXBuildFile; fileRef = 41F062120F5F192600A07EAC /* InspectorDatabaseResource.h */; };
    11271129                41F1D21F0EF35C2A00DA8753 /* ScriptCachedFrameData.h in Headers */ = {isa = PBXBuildFile; fileRef = 41F1D21D0EF35C2A00DA8753 /* ScriptCachedFrameData.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    73877389                41E59400214865AA00D3CB61 /* RTCRtpHeaderExtensionParameters.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = RTCRtpHeaderExtensionParameters.idl; sourceTree = "<group>"; };
    73887390                41E59401214865AB00D3CB61 /* RTCRtpFecParameters.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = RTCRtpFecParameters.idl; sourceTree = "<group>"; };
     7391                41E9DCE4231973FE00F35949 /* BlobLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlobLoader.h; sourceTree = "<group>"; };
     7392                41E9DCE62319742300F35949 /* BlobLineEndings.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = BlobLineEndings.idl; sourceTree = "<group>"; };
     7393                41E9DCE82319CA7500F35949 /* NetworkSendQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkSendQueue.h; sourceTree = "<group>"; };
     7394                41E9DCEA2319CAE800F35949 /* NetworkSendQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkSendQueue.cpp; sourceTree = "<group>"; };
    73897395                41F062120F5F192600A07EAC /* InspectorDatabaseResource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorDatabaseResource.h; sourceTree = "<group>"; };
    73907396                41F062130F5F192600A07EAC /* InspectorDatabaseResource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorDatabaseResource.cpp; sourceTree = "<group>"; };
     
    97319737                7C77C3D31DEF178E00A50BFA /* JSBlobPropertyBag.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSBlobPropertyBag.h; sourceTree = "<group>"; };
    97329738                7C77C3D61DEF850A00A50BFA /* BlobLineEndings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlobLineEndings.h; sourceTree = "<group>"; };
    9733                 7C77C3D81DEF854000A50BFA /* BlobLineEndings.idl */ = {isa = PBXFileReference; lastKnownFileType = text; path = BlobLineEndings.idl; sourceTree = "<group>"; };
    97349739                7C77C3D91DEF86D700A50BFA /* JSBlobLineEndings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSBlobLineEndings.cpp; sourceTree = "<group>"; };
    97359740                7C77C3DA1DEF86D700A50BFA /* JSBlobLineEndings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSBlobLineEndings.h; sourceTree = "<group>"; };
     
    2197321978                                A15D75141E68F7B100A35FBC /* BlobCallback.idl */,
    2197421979                                7C77C3D61DEF850A00A50BFA /* BlobLineEndings.h */,
    21975                                 7C77C3D81DEF854000A50BFA /* BlobLineEndings.idl */,
     21980                                41E9DCE62319742300F35949 /* BlobLineEndings.idl */,
     21981                                41E9DCE4231973FE00F35949 /* BlobLoader.h */,
    2197621982                                7C77C3D01DEE472400A50BFA /* BlobPropertyBag.h */,
    2197721983                                7C77C3CF1DEE471800A50BFA /* BlobPropertyBag.idl */,
     
    2199622002                                2EDF369B122C94B4002F7D4E /* FileReaderSync.h */,
    2199722003                                E1AB1EBD14E9E3A800449E13 /* FileReaderSync.idl */,
     22004                                41E9DCEA2319CAE800F35949 /* NetworkSendQueue.cpp */,
     22005                                41E9DCE82319CA7500F35949 /* NetworkSendQueue.h */,
    2199822006                                976D6C75122B8A3D001FD1F7 /* ThreadableBlobRegistry.cpp */,
    2199922007                                976D6C76122B8A3D001FD1F7 /* ThreadableBlobRegistry.h */,
     
    2848428492                                4D3B00AF215D6A690076B983 /* BlobEvent.h in Headers */,
    2848528493                                7C77C3D71DEF850A00A50BFA /* BlobLineEndings.h in Headers */,
     28494                                41E9DCE7231974BF00F35949 /* BlobLoader.h in Headers */,
    2848628495                                E1C94AF9191303F000D5A893 /* BlobPart.h in Headers */,
    2848728496                                7C77C3D11DEE472400A50BFA /* BlobPropertyBag.h in Headers */,
     
    3084330852                                8A81BF8511DCFD9000DA2B98 /* NetworkLoadMetrics.h in Headers */,
    3084430853                                59C27F07138D28CF0079B7E2 /* NetworkResourcesData.h in Headers */,
     30854                                41E9DCE92319CA7600F35949 /* NetworkSendQueue.h in Headers */,
    3084530855                                1A7FA6190DDA3B3A0028F8A5 /* NetworkStateNotifier.h in Headers */,
    3084630856                                E13EF3441684ECF40034C83F /* NetworkStorageSession.h in Headers */,
  • trunk/Source/WebKit/ChangeLog

    r249479 r249481  
     12019-09-04  Youenn Fablet  <youenn@apple.com>
     2
     3        Abstract out WebSocketChannel message queue
     4        https://bugs.webkit.org/show_bug.cgi?id=201359
     5
     6        Reviewed by Alex Christensen.
     7
     8        Make use of newly added NetworkSendQueue.
     9
     10        * WebProcess/Network/WebSocketChannel.cpp:
     11        (WebKit::WebSocketChannel::createMessageQueue):
     12        (WebKit::WebSocketChannel::WebSocketChannel):
     13        (WebKit::WebSocketChannel::send):
     14        (WebKit::WebSocketChannel::disconnect):
     15        * WebProcess/Network/WebSocketChannel.h:
     16
    1172019-09-04  Youenn Fablet  <youenn@apple.com>
    218
  • trunk/Source/WebKit/WebProcess/Network/WebSocketChannel.cpp

    r248846 r249481  
    3535#include <WebCore/Blob.h>
    3636#include <WebCore/Document.h>
    37 #include <WebCore/FileReaderLoader.h>
    38 #include <WebCore/FileReaderLoaderClient.h>
    39 #include <WebCore/NotImplemented.h>
    4037#include <WebCore/WebSocketChannel.h>
    4138#include <WebCore/WebSocketChannelClient.h>
    42 #include <pal/SessionID.h>
    4339#include <wtf/CheckedArithmetic.h>
    4440
     41using namespace WebCore;
     42
    4543namespace WebKit {
    4644
    47 Ref<WebSocketChannel> WebSocketChannel::create(WebCore::Document& document, WebCore::WebSocketChannelClient& client)
     45Ref<WebSocketChannel> WebSocketChannel::create(Document& document, WebSocketChannelClient& client)
    4846{
    4947    return adoptRef(*new WebSocketChannel(document, client));
    5048}
    5149
    52 WebSocketChannel::WebSocketChannel(WebCore::Document& document, WebCore::WebSocketChannelClient& client)
     50NetworkSendQueue WebSocketChannel::createMessageQueue(Document& document, WebSocketChannel& channel)
     51{
     52    return { document, [&channel](auto& string) {
     53        auto byteLength = string.sizeInBytes();
     54        channel.sendMessage(Messages::NetworkSocketChannel::SendString { string }, byteLength);
     55    }, [&channel](const char* data, size_t byteLength) {
     56        channel.sendMessage(Messages::NetworkSocketChannel::SendData { IPC::DataReference { reinterpret_cast<const uint8_t*>(data), byteLength } }, byteLength);
     57    }, [&channel](auto errorCode) {
     58        channel.fail(makeString("Failed to load Blob: error code = ", errorCode));
     59        return NetworkSendQueue::Continue::No;
     60    } };
     61}
     62
     63WebSocketChannel::WebSocketChannel(Document& document, WebSocketChannelClient& client)
    5364    : m_document(makeWeakPtr(document))
    5465    , m_client(makeWeakPtr(client))
     66    , m_messageQueue(createMessageQueue(document, *this))
    5567{
    5668}
     
    133145}
    134146
    135 class BlobLoader final : public WebCore::FileReaderLoaderClient {
    136     WTF_MAKE_FAST_ALLOCATED;
    137 public:
    138     BlobLoader(WebCore::Document* document, WebCore::Blob& blob, CompletionHandler<void()>&& completionHandler)
    139         : m_loader(makeUnique<WebCore::FileReaderLoader>(WebCore::FileReaderLoader::ReadAsArrayBuffer, this))
    140         , m_completionHandler(WTFMove(completionHandler))
    141     {
    142         m_loader->start(document, blob);
    143     }
    144 
    145     ~BlobLoader()
    146     {
    147         if (m_loader)
    148             m_loader->cancel();
    149     }
    150 
    151     bool isLoading() const { return !!m_loader; }
    152     const RefPtr<JSC::ArrayBuffer>& result() const { return m_buffer; }
    153     Optional<int> errorCode() const { return m_errorCode; }
    154 
    155 private:
    156     void didStartLoading() final { }
    157     void didReceiveData() final { }
    158 
    159     void didFinishLoading() final
    160     {
    161         m_buffer = m_loader->arrayBufferResult();
    162         complete();
    163     }
    164 
    165     void didFail(int errorCode) final
    166     {
    167         m_errorCode = errorCode;
    168         complete();
    169     }
    170 
    171     void complete()
    172     {
    173         m_loader = nullptr;
    174         m_completionHandler();
    175     }
    176 
    177     std::unique_ptr<WebCore::FileReaderLoader> m_loader;
    178     RefPtr<JSC::ArrayBuffer> m_buffer;
    179     Optional<int> m_errorCode;
    180     CompletionHandler<void()> m_completionHandler;
    181 };
    182 
    183 class PendingMessage {
    184     WTF_MAKE_FAST_ALLOCATED;
    185 public:
    186     enum class Type { Text, Binary, Blob };
    187 
    188     explicit PendingMessage(const String& message)
    189         : m_type(Type::Text)
    190         , m_textMessage(message)
    191     {
    192     }
    193 
    194     PendingMessage(const JSC::ArrayBuffer& binaryData, unsigned byteOffset, unsigned byteLength)
    195         : m_type(Type::Binary)
    196         , m_binaryData(WebCore::SharedBuffer::create(static_cast<const uint8_t*>(binaryData.data()) + byteOffset, byteLength))
    197     {
    198     }
    199 
    200     PendingMessage(WebCore::Document* document, WebCore::Blob& blob, CompletionHandler<void()>&& completionHandler)
    201         : m_type(Type::Blob)
    202         , m_blobLoader(makeUnique<BlobLoader>(document, blob, WTFMove(completionHandler)))
    203     {
    204     }
    205 
    206     ~PendingMessage() = default;
    207 
    208     Type type() const { return m_type; }
    209     const String& textMessage() const { ASSERT(m_type == Type::Text); return m_textMessage; }
    210     const WebCore::SharedBuffer& binaryData() const { ASSERT(m_type == Type::Binary); return *m_binaryData; }
    211     const BlobLoader& blobLoader() const { ASSERT(m_type == Type::Blob); return *m_blobLoader; }
    212 
    213 private:
    214     Type m_type;
    215     String m_textMessage;
    216     RefPtr<WebCore::SharedBuffer> m_binaryData;
    217     std::unique_ptr<BlobLoader> m_blobLoader;
    218 };
    219 
    220147WebSocketChannel::SendResult WebSocketChannel::send(const String& message)
    221148{
     
    224151        return SendFail;
    225152
    226     if (m_pendingMessages.isEmpty())
    227         sendMessage(Messages::NetworkSocketChannel::SendString { message }, byteLength);
    228     else
    229         m_pendingMessages.append(makeUnique<PendingMessage>(message));
    230 
     153    m_messageQueue.enqueue(message);
    231154    return SendSuccess;
    232155}
     
    237160        return SendFail;
    238161
    239     if (m_pendingMessages.isEmpty())
    240         sendMessage(Messages::NetworkSocketChannel::SendData { IPC::DataReference { static_cast<const uint8_t*>(binaryData.data()) + byteOffset, byteLength } }, byteLength);
    241     else
    242         m_pendingMessages.append(makeUnique<PendingMessage>(binaryData, byteOffset, byteLength));
    243 
     162    m_messageQueue.enqueue(binaryData, byteOffset, byteLength);
    244163    return SendSuccess;
    245164}
    246165
    247 WebSocketChannel::SendResult WebSocketChannel::send(WebCore::Blob& blob)
    248 {
    249     // Avoid the Blob queue and loading for empty blobs.
     166WebSocketChannel::SendResult WebSocketChannel::send(Blob& blob)
     167{
     168    auto byteLength = blob.size();
    250169    if (!blob.size())
    251         return send(JSC::ArrayBuffer::create(blob.size(), 1), 0, 0);
    252 
    253     m_pendingMessages.append(makeUnique<PendingMessage>(m_document.get(), blob, [this] {
    254         while (!m_pendingMessages.isEmpty()) {
    255             auto& message = m_pendingMessages.first();
    256 
    257             switch (message->type()) {
    258             case PendingMessage::Type::Text:
    259                 sendMessage(Messages::NetworkSocketChannel::SendString { message->textMessage() }, message->textMessage().sizeInBytes());
    260                 break;
    261             case PendingMessage::Type::Binary: {
    262                 const auto& binaryData = message->binaryData();
    263                 sendMessage(Messages::NetworkSocketChannel::SendData { IPC::DataReference { reinterpret_cast<const uint8_t*>(binaryData.data()), binaryData.size() } }, binaryData.size());
    264                 break;
    265             }
    266             case PendingMessage::Type::Blob: {
    267                 auto& loader = message->blobLoader();
    268                 if (loader.isLoading())
    269                     return;
    270 
    271                 if (const auto& result = loader.result()) {
    272                     auto byteLength = result->byteLength();
    273                     if (increaseBufferedAmount(byteLength))
    274                         sendMessage(Messages::NetworkSocketChannel::SendData { IPC::DataReference { reinterpret_cast<const uint8_t*>(result->data()), byteLength } }, byteLength);
    275                 } else if (auto errorCode = loader.errorCode())
    276                     fail(makeString("Failed to load Blob: error code = ", errorCode.value()));
    277                 else
    278                     ASSERT_NOT_REACHED();
    279                 break;
    280             }
    281             }
    282 
    283             m_pendingMessages.removeFirst();
    284         }
    285     }));
     170        return send(JSC::ArrayBuffer::create(byteLength, 1), 0, 0);
     171
     172    if (!increaseBufferedAmount(byteLength))
     173        return SendFail;
     174
     175    m_messageQueue.enqueue(blob);
    286176    return SendSuccess;
    287177}
     
    317207    m_document = nullptr;
    318208    m_pendingTasks.clear();
    319     m_pendingMessages.clear();
     209    m_messageQueue.clear();
    320210
    321211    MessageSender::send(Messages::NetworkSocketChannel::Close { 0, { } });
  • trunk/Source/WebKit/WebProcess/Network/WebSocketChannel.h

    r248102 r249481  
    2828#include "MessageReceiver.h"
    2929#include "MessageSender.h"
     30#include <WebCore/NetworkSendQueue.h>
    3031#include <WebCore/ThreadableWebSocketChannel.h>
    3132#include <pal/SessionID.h>
    32 #include <wtf/Deque.h>
    3333#include <wtf/Identified.h>
    3434#include <wtf/WeakPtr.h>
     
    4141
    4242namespace WebKit {
    43 
    44 class PendingMessage;
    4543
    4644class WebSocketChannel : public IPC::MessageSender, public IPC::MessageReceiver, public WebCore::ThreadableWebSocketChannel, public RefCounted<WebSocketChannel>, public Identified<WebSocketChannel> {
     
    5856private:
    5957    WebSocketChannel(WebCore::Document&, WebCore::WebSocketChannelClient&);
     58
     59    static WebCore::NetworkSendQueue createMessageQueue(WebCore::Document&, WebSocketChannel&);
    6060
    6161    // ThreadableWebSocketChannel
     
    9999    bool m_isSuspended { false };
    100100    Deque<Function<void()>> m_pendingTasks;
    101     Deque<std::unique_ptr<PendingMessage>> m_pendingMessages;
     101    WebCore::NetworkSendQueue m_messageQueue;
    102102};
    103103
Note: See TracChangeset for help on using the changeset viewer.