WebKit Bugzilla
Attachment 373095 Details for
Bug 199189
: WebSockets: add support for sending blob messages when using web sockets platform APIs
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Try to fix apple builds
wk2-websockets-blobs.diff (text/plain), 19.26 KB, created by
Carlos Garcia Campos
on 2019-06-28 00:55:54 PDT
(
hide
)
Description:
Try to fix apple builds
Filename:
MIME Type:
Creator:
Carlos Garcia Campos
Created:
2019-06-28 00:55:54 PDT
Size:
19.26 KB
patch
obsolete
>diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 0e9bd6338db..8a9de115218 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,12 @@ >+2019-06-27 Carlos Garcia Campos <cgarcia@igalia.com> >+ >+ WebSockets: add support for sending blob messages when using web sockets platform APIs >+ https://bugs.webkit.org/show_bug.cgi?id=199189 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * Headers.cmake: Add missing headers. >+ > 2019-06-28 Fujii Hironori <Hironori.Fujii@sony.com> > > [Win] unresolved external symbol "JSC::JSObject::didBecomePrototype(void)" referenced in function "JSC::Structure::create(...)" >diff --git a/Source/WebCore/Headers.cmake b/Source/WebCore/Headers.cmake >index a81d82ab8df..017c9129ef0 100644 >--- a/Source/WebCore/Headers.cmake >+++ b/Source/WebCore/Headers.cmake >@@ -515,7 +515,9 @@ set(WebCore_PRIVATE_FRAMEWORK_HEADERS > fileapi/BlobLineEndings.h > fileapi/BlobPropertyBag.h > fileapi/File.h >+ fileapi/FileError.h > fileapi/FileList.h >+ fileapi/FileReaderLoader.h > fileapi/FileReaderLoaderClient.h > > history/BackForwardClient.h >@@ -1168,6 +1170,7 @@ set(WebCore_PRIVATE_FRAMEWORK_HEADERS > platform/network/BlobPart.h > platform/network/BlobRegistry.h > platform/network/BlobRegistryImpl.h >+ platform/network/BlobResourceHandle.h > platform/network/CacheValidation.h > platform/network/CertificateInfoBase.h > platform/network/CookieRequestHeaderFieldProxy.h >diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >index ae4802efa5b..5c849c758b0 100644 >--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj >+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >@@ -857,12 +857,12 @@ > 2E4346510F546A8200B0F1BA /* WorkerObjectProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E43463F0F546A8200B0F1BA /* WorkerObjectProxy.h */; }; > 2E4346530F546A8200B0F1BA /* WorkerRunLoop.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E4346410F546A8200B0F1BA /* WorkerRunLoop.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 2E4346550F546A8200B0F1BA /* WorkerThread.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E4346430F546A8200B0F1BA /* WorkerThread.h */; settings = {ATTRIBUTES = (Private, ); }; }; >- 2E75841E12779ADA0062628B /* FileReaderLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E75841B12779ADA0062628B /* FileReaderLoader.h */; }; >+ 2E75841E12779ADA0062628B /* FileReaderLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E75841B12779ADA0062628B /* FileReaderLoader.h */; settings = {ATTRIBUTES = (Private, ); };}; > 2E75841F12779ADA0062628B /* FileReaderLoaderClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E75841C12779ADA0062628B /* FileReaderLoaderClient.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 2E94F43C119207DA00B7F75D /* JSFileReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E94F43A119207DA00B7F75D /* JSFileReader.h */; }; > 2E9B5D8F1B66A94E008C6A24 /* WheelEventDeltaFilterMac.h in Headers */ = {isa = PBXBuildFile; fileRef = 2E9B5D8E1B66A94E008C6A24 /* WheelEventDeltaFilterMac.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 2EA768040FE7126400AB9C8A /* WorkerScriptLoaderClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EA768030FE7126400AB9C8A /* WorkerScriptLoaderClient.h */; settings = {ATTRIBUTES = (Private, ); }; }; >- 2EB4BCD3121F03E300EC4885 /* BlobResourceHandle.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EB4BCD1121F03E300EC4885 /* BlobResourceHandle.h */; }; >+ 2EB4BCD3121F03E300EC4885 /* BlobResourceHandle.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EB4BCD1121F03E300EC4885 /* BlobResourceHandle.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 2EB767571DA19BDF003E23B5 /* InputEvent.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EB767541DA19B67003E23B5 /* InputEvent.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 2EBBC3D81B65988300F5253D /* WheelEventDeltaFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2EBBC3D71B65988300F5253D /* WheelEventDeltaFilter.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 2ECDBAD121D8903400F00ECD /* UndoManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ECDBACE21D8903400F00ECD /* UndoManager.h */; }; >@@ -2804,7 +2804,7 @@ > 976D6C7C122B8A3D001FD1F7 /* BlobBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 976D6C5D122B8A3D001FD1F7 /* BlobBuilder.h */; }; > 976D6C7F122B8A3D001FD1F7 /* BlobURL.h in Headers */ = {isa = PBXBuildFile; fileRef = 976D6C60122B8A3D001FD1F7 /* BlobURL.h */; }; > 976D6C81122B8A3D001FD1F7 /* File.h in Headers */ = {isa = PBXBuildFile; fileRef = 976D6C62122B8A3D001FD1F7 /* File.h */; settings = {ATTRIBUTES = (Private, ); }; }; >- 976D6C83122B8A3D001FD1F7 /* FileError.h in Headers */ = {isa = PBXBuildFile; fileRef = 976D6C64122B8A3D001FD1F7 /* FileError.h */; }; >+ 976D6C83122B8A3D001FD1F7 /* FileError.h in Headers */ = {isa = PBXBuildFile; fileRef = 976D6C64122B8A3D001FD1F7 /* FileError.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 976D6C86122B8A3D001FD1F7 /* FileList.h in Headers */ = {isa = PBXBuildFile; fileRef = 976D6C67122B8A3D001FD1F7 /* FileList.h */; settings = {ATTRIBUTES = (Private, ); }; }; > 976D6C89122B8A3D001FD1F7 /* FileReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 976D6C6A122B8A3D001FD1F7 /* FileReader.h */; }; > 976D6C95122B8A3D001FD1F7 /* ThreadableBlobRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = 976D6C76122B8A3D001FD1F7 /* ThreadableBlobRegistry.h */; }; >diff --git a/Source/WebCore/fileapi/FileReaderLoader.h b/Source/WebCore/fileapi/FileReaderLoader.h >index 1f7778e889e..7a428be5057 100644 >--- a/Source/WebCore/fileapi/FileReaderLoader.h >+++ b/Source/WebCore/fileapi/FileReaderLoader.h >@@ -61,11 +61,11 @@ public: > }; > > // If client is given, do the loading asynchronously. Otherwise, load synchronously. >- FileReaderLoader(ReadType, FileReaderLoaderClient*); >+ WEBCORE_EXPORT FileReaderLoader(ReadType, FileReaderLoaderClient*); > ~FileReaderLoader(); > >- void start(ScriptExecutionContext*, Blob&); >- void cancel(); >+ WEBCORE_EXPORT void start(ScriptExecutionContext*, Blob&); >+ WEBCORE_EXPORT void cancel(); > > // ThreadableLoaderClient > void didReceiveResponse(unsigned long, const ResourceResponse&) override; >@@ -74,7 +74,7 @@ public: > void didFail(const ResourceError&) override; > > String stringResult(); >- RefPtr<JSC::ArrayBuffer> arrayBufferResult() const; >+ WEBCORE_EXPORT RefPtr<JSC::ArrayBuffer> arrayBufferResult() const; > unsigned bytesLoaded() const { return m_bytesLoaded; } > unsigned totalBytes() const { return m_totalBytes; } > FileError::ErrorCode errorCode() const { return m_errorCode; } >diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog >index 14aeb3d89dd..33a191acb2c 100644 >--- a/Source/WebKit/ChangeLog >+++ b/Source/WebKit/ChangeLog >@@ -1,3 +1,30 @@ >+2019-06-27 Carlos Garcia Campos <cgarcia@igalia.com> >+ >+ WebSockets: add support for sending blob messages when using web sockets platform APIs >+ https://bugs.webkit.org/show_bug.cgi?id=199189 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add helper private class BlobLoader that uses FileReaderLoader to load the blobs. Since blob loads are >+ asynchronous, the messages are queued using another helper internal class PendingMessage. >+ >+ * WebProcess/Network/WebSocketChannel.cpp: >+ (WebKit::WebSocketChannel::increaseBufferedAmount): Increase the buffered amount checking we don't overlofw. >+ (WebKit::WebSocketChannel::decreaseBufferedAmount): Decrease the buffered amount. >+ (WebKit::WebSocketChannel::sendMessage): Helper class to send message to the network process and decrease the >+ buffered amount when done. >+ (WebKit::WebSocketChannel::send): Queue the message in pending queue if there are pending messages in the queue >+ for text and binary messages. For blobs, always queue the message unless it's an empty blob that we can handle >+ as empty binary data directly. >+ (WebKit::PendingMessage::PendingMessage): Helper class to queue message requests. >+ (WebKit::PendingMessage::type const): Type of message: Text, Binary, Blob. >+ (WebKit::PendingMessage::textMessage const): The text message. >+ (WebKit::PendingMessage::binaryData const): The binary data. >+ (WebKit::PendingMessage::blobLoader const): The blob loader. >+ (WebKit::WebSocketChannel::fail): Notify the client about the error to ensure onclose is emitted. >+ (WebKit::WebSocketChannel::disconnect): Clear the pending messages queue. >+ * WebProcess/Network/WebSocketChannel.h: >+ > 2019-06-28 Carlos Garcia Campos <cgarcia@igalia.com> > > [SOUP] WebSockets: runtime critical warning when closing the connection in some cases >diff --git a/Source/WebKit/WebProcess/Network/WebSocketChannel.cpp b/Source/WebKit/WebProcess/Network/WebSocketChannel.cpp >index 56cb7b8941d..d46b349bff8 100644 >--- a/Source/WebKit/WebProcess/Network/WebSocketChannel.cpp >+++ b/Source/WebKit/WebProcess/Network/WebSocketChannel.cpp >@@ -32,11 +32,15 @@ > #include "NetworkSocketChannelMessages.h" > #include "WebCoreArgumentCoders.h" > #include "WebProcess.h" >+#include <WebCore/Blob.h> > #include <WebCore/Document.h> >+#include <WebCore/FileReaderLoader.h> >+#include <WebCore/FileReaderLoaderClient.h> > #include <WebCore/NotImplemented.h> > #include <WebCore/WebSocketChannel.h> > #include <WebCore/WebSocketChannelClient.h> > #include <pal/SessionID.h> >+#include <wtf/CheckedArithmetic.h> > > namespace WebKit { > >@@ -92,43 +96,195 @@ WebSocketChannel::ConnectStatus WebSocketChannel::connect(const URL& url, const > return ConnectStatus::OK; > } > >-WebSocketChannel::SendResult WebSocketChannel::send(const String& message) >+bool WebSocketChannel::increaseBufferedAmount(size_t byteLength) > { >- auto byteLength = message.sizeInBytes(); >- m_bufferedAmount += byteLength; >+ if (!byteLength) >+ return true; >+ >+ Checked<size_t, RecordOverflow> checkedNewBufferedAmount = m_bufferedAmount; >+ checkedNewBufferedAmount += byteLength; >+ if (UNLIKELY(checkedNewBufferedAmount.hasOverflowed())) { >+ fail("Failed to send WebSocket frame: buffer has no more space"); >+ return false; >+ } >+ >+ m_bufferedAmount = checkedNewBufferedAmount.unsafeGet(); > if (m_client) > m_client->didUpdateBufferedAmount(m_bufferedAmount); >+ return true; >+} > >+void WebSocketChannel::decreaseBufferedAmount(size_t byteLength) >+{ >+ if (!byteLength) >+ return; >+ >+ ASSERT(m_bufferedAmount >= byteLength); >+ m_bufferedAmount -= byteLength; >+ if (m_client) >+ m_client->didUpdateBufferedAmount(m_bufferedAmount); >+} >+ >+template<typename T> void WebSocketChannel::sendMessage(T&& message, size_t byteLength) >+{ > CompletionHandler<void()> completionHandler = [this, protectedThis = makeRef(*this), byteLength] { >- ASSERT(m_bufferedAmount >= byteLength); >- m_bufferedAmount -= byteLength; >- if (m_client) >- m_client->didUpdateBufferedAmount(m_bufferedAmount); >+ decreaseBufferedAmount(byteLength); > }; >- sendWithAsyncReply(Messages::NetworkSocketChannel::SendString { message }, WTFMove(completionHandler)); >+ sendWithAsyncReply(WTFMove(message), WTFMove(completionHandler)); >+} >+ >+WebSocketChannel::SendResult WebSocketChannel::send(const String& message) >+{ >+ auto byteLength = message.sizeInBytes(); >+ if (!increaseBufferedAmount(byteLength)) >+ return SendFail; >+ >+ if (m_pendingMessages.isEmpty()) >+ sendMessage(Messages::NetworkSocketChannel::SendString { message }, byteLength); >+ else >+ m_pendingMessages.append(std::make_unique<PendingMessage>(message)); >+ > return SendSuccess; > } > > WebSocketChannel::SendResult WebSocketChannel::send(const JSC::ArrayBuffer& binaryData, unsigned byteOffset, unsigned byteLength) > { >- m_bufferedAmount += byteLength; >- if (m_client) >- m_client->didUpdateBufferedAmount(m_bufferedAmount); >+ if (!increaseBufferedAmount(byteLength)) >+ return SendFail; >+ >+ if (m_pendingMessages.isEmpty()) >+ sendMessage(Messages::NetworkSocketChannel::SendData { IPC::DataReference { static_cast<const uint8_t*>(binaryData.data()) + byteOffset, byteLength } }, byteLength); >+ else >+ m_pendingMessages.append(std::make_unique<PendingMessage>(binaryData, byteOffset, byteLength)); > >- CompletionHandler<void()> completionHandler = [this, protectedThis = makeRef(*this), byteLength] { >- ASSERT(m_bufferedAmount >= byteLength); >- m_bufferedAmount -= byteLength; >- if (m_client) >- m_client->didUpdateBufferedAmount(m_bufferedAmount); >- }; >- sendWithAsyncReply(Messages::NetworkSocketChannel::SendData { IPC::DataReference { static_cast<const uint8_t*>(binaryData.data()) + byteOffset, byteLength } }, WTFMove(completionHandler)); > return SendSuccess; > } > >-WebSocketChannel::SendResult WebSocketChannel::send(WebCore::Blob&) >+class BlobLoader final : public WebCore::FileReaderLoaderClient { >+ WTF_MAKE_FAST_ALLOCATED; >+public: >+ BlobLoader(WebCore::Document* document, Blob& blob, CompletionHandler<void()>&& completionHandler) >+ : m_loader(std::make_unique<FileReaderLoader>(FileReaderLoader::ReadAsArrayBuffer, this)) >+ , m_completionHandler(WTFMove(completionHandler)) >+ { >+ m_loader->start(document, blob); >+ } >+ >+ ~BlobLoader() >+ { >+ if (m_loader) >+ m_loader->cancel(); >+ } >+ >+ bool isLoading() const { return !!m_loader; } >+ const RefPtr<JSC::ArrayBuffer>& result() const { return m_buffer; } >+ Optional<int> errorCode() const { return m_errorCode; } >+ >+private: >+ void didStartLoading() final { } >+ void didReceiveData() final { } >+ >+ void didFinishLoading() final >+ { >+ m_buffer = m_loader->arrayBufferResult(); >+ complete(); >+ } >+ >+ void didFail(int errorCode) final >+ { >+ m_errorCode = errorCode; >+ complete(); >+ } >+ >+ void complete() >+ { >+ m_loader = nullptr; >+ m_completionHandler(); >+ } >+ >+ std::unique_ptr<WebCore::FileReaderLoader> m_loader; >+ RefPtr<JSC::ArrayBuffer> m_buffer; >+ Optional<int> m_errorCode; >+ CompletionHandler<void()> m_completionHandler; >+}; >+ >+class PendingMessage { >+ WTF_MAKE_FAST_ALLOCATED; >+public: >+ enum class Type { Text, Binary, Blob }; >+ >+ explicit PendingMessage(const String& message) >+ : m_type(Type::Text) >+ , m_textMessage(message) >+ { >+ } >+ >+ PendingMessage(const JSC::ArrayBuffer& binaryData, unsigned byteOffset, unsigned byteLength) >+ : m_type(Type::Binary) >+ , m_binaryData(WebCore::SharedBuffer::create(static_cast<const uint8_t*>(binaryData.data()) + byteOffset, byteLength)) >+ { >+ } >+ >+ PendingMessage(WebCore::Document* document, Blob& blob, CompletionHandler<void()>&& completionHandler) >+ : m_type(Type::Blob) >+ , m_blobLoader(std::make_unique<BlobLoader>(document, blob, WTFMove(completionHandler))) >+ { >+ } >+ >+ ~PendingMessage() = default; >+ >+ Type type() const { return m_type; } >+ const String& textMessage() const { ASSERT(m_type == Type::Text); return m_textMessage; } >+ const WebCore::SharedBuffer& binaryData() const { ASSERT(m_type == Type::Binary); return *m_binaryData; } >+ const BlobLoader& blobLoader() const { ASSERT(m_type == Type::Blob); return *m_blobLoader; } >+ >+private: >+ Type m_type; >+ String m_textMessage; >+ RefPtr<WebCore::SharedBuffer> m_binaryData; >+ std::unique_ptr<BlobLoader> m_blobLoader; >+}; >+ >+WebSocketChannel::SendResult WebSocketChannel::send(WebCore::Blob& blob) > { >- notImplemented(); >- return SendFail; >+ // Avoid the Blob queue and loading for empty blobs. >+ if (!blob.size()) >+ return send(JSC::ArrayBuffer::create(blob.size(), 1), 0, 0); >+ >+ m_pendingMessages.append(std::make_unique<PendingMessage>(m_document.get(), blob, [this] { >+ while (!m_pendingMessages.isEmpty()) { >+ auto& message = m_pendingMessages.first(); >+ >+ switch (message->type()) { >+ case PendingMessage::Type::Text: >+ sendMessage(Messages::NetworkSocketChannel::SendString { message->textMessage() }, message->textMessage().sizeInBytes()); >+ break; >+ case PendingMessage::Type::Binary: { >+ const auto& binaryData = message->binaryData(); >+ sendMessage(Messages::NetworkSocketChannel::SendData { IPC::DataReference { reinterpret_cast<const uint8_t*>(binaryData.data()), binaryData.size() } }, binaryData.size()); >+ break; >+ } >+ case PendingMessage::Type::Blob: { >+ auto& loader = message->blobLoader(); >+ if (loader.isLoading()) >+ return; >+ >+ if (const auto& result = loader.result()) { >+ auto byteLength = result->byteLength(); >+ if (increaseBufferedAmount(byteLength)) >+ sendMessage(Messages::NetworkSocketChannel::SendData { IPC::DataReference { reinterpret_cast<const uint8_t*>(result->data()), byteLength } }, byteLength); >+ } else if (auto errorCode = loader.errorCode()) >+ fail(makeString("Failed to load Blob: error code = ", errorCode.value())); >+ else >+ ASSERT_NOT_REACHED(); >+ break; >+ } >+ } >+ >+ m_pendingMessages.removeFirst(); >+ } >+ })); >+ return SendSuccess; > } > > unsigned WebSocketChannel::bufferedAmount() const >@@ -149,7 +305,11 @@ void WebSocketChannel::close(int code, const String& reason) > > void WebSocketChannel::fail(const String& reason) > { >- MessageSender::send(Messages::NetworkSocketChannel::Close { 0, reason }); >+ if (m_client) >+ m_client->didReceiveMessageError(); >+ >+ if (!m_isClosing) >+ MessageSender::send(Messages::NetworkSocketChannel::Close { 0, reason }); > } > > void WebSocketChannel::disconnect() >@@ -157,6 +317,7 @@ void WebSocketChannel::disconnect() > m_client = nullptr; > m_document = nullptr; > m_pendingTasks.clear(); >+ m_pendingMessages.clear(); > > MessageSender::send(Messages::NetworkSocketChannel::Close { 0, { } }); > } >diff --git a/Source/WebKit/WebProcess/Network/WebSocketChannel.h b/Source/WebKit/WebProcess/Network/WebSocketChannel.h >index 9937df17223..ff16f9e0943 100644 >--- a/Source/WebKit/WebProcess/Network/WebSocketChannel.h >+++ b/Source/WebKit/WebProcess/Network/WebSocketChannel.h >@@ -41,6 +41,8 @@ class DataReference; > > namespace WebKit { > >+class PendingMessage; >+ > class WebSocketChannel : public IPC::MessageSender, public IPC::MessageReceiver, public WebCore::ThreadableWebSocketChannel, public RefCounted<WebSocketChannel>, public Identified<WebSocketChannel> { > public: > static Ref<WebSocketChannel> create(WebCore::Document&, WebCore::WebSocketChannelClient&); >@@ -83,6 +85,9 @@ private: > IPC::Connection* messageSenderConnection() const final; > uint64_t messageSenderDestinationID() const final; > >+ bool increaseBufferedAmount(size_t); >+ void decreaseBufferedAmount(size_t); >+ template<typename T> void sendMessage(T&&, size_t byteLength); > void enqueueTask(Function<void()>&&); > > WeakPtr<WebCore::Document> m_document; >@@ -92,6 +97,7 @@ private: > bool m_isClosing { false }; > bool m_isSuspended { false }; > Deque<Function<void()>> m_pendingTasks; >+ Deque<std::unique_ptr<PendingMessage>> m_pendingMessages; > }; > > } // namespace WebKit
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Flags:
youennf
:
review+
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 199189
:
372834
|
372915
|
373016
|
373019
|
373029
|
373031
| 373095