Title: [290856] trunk/Source
Revision
290856
Author
pan...@apple.com
Date
2022-03-04 17:06:41 -0800 (Fri, 04 Mar 2022)

Log Message

REGRESSION (r284472): [ Monterey ] http/tests/websocket/tests/hybi/inspector/send-and-recieve-debugger.html is failing
https://bugs.webkit.org/show_bug.cgi?id=237280

Reviewed by Devin Rousso.

Source/WebCore:

Covered by existing http/tests/websocket/tests/hybi/inspector/* test cases.

On macOS Monterey we use NSURLSession-based WebSockets by default, unlike earlier versions of macOS. The channel
for these sockets is implemented in `WebKit::WebSocketChannel`. The non-NSURLSession WebSockets channel (at
least on Cocoa platforms) is implemented in `WebCore::WebSocketChannel`.

As of r284472 the logic to delay the dispatch of received WebSocket message on platforms using
NSURLSession-based WebSockets is handled by `WebCore::WebSocket`, not the `WebKit::WebSocketChannel`.
`WebKit::WebSocketChannel` now immediately does the work it needs to, and only the delegated work to `WebSocket`
is queued and taken care of when the socket has resumed. This resulted in some of the instrumentation in
`WebKit::WebSocketChannel` being able to be called while the socket was suspended leading to events being logged
in the frontend "in the future" (e.g. before the paused script would have been able to be aware of them). To
correct this the `WebKit::WebSocketChannel` now provides a hook into its helper `WebSocketChannelInspector`
object to allow the `WebCore::WebSocket` to notify Web Inspector of events at the same time it is being
logically handled by the page.

Other `ThreadableWebSocketChannel` implementations will instead provide `nullptr` in place of a pointer to a
`WebInspectorChannelInspector`. `WebCore::WebSocketChannel` was not affected by the changes in r284472 as it has
a different way to guarantee that the methods containing InspectorInstrumentation were not called while the
channel was suspended (and enforced with numerous `ASSERT(!m_suspended)` checks).

* Modules/websockets/ThreadableWebSocketChannel.h:
(WebCore::ThreadableWebSocketChannel::channelInspector const):

* Modules/websockets/WebSocketChannelClient.h:
- Add `reason` for error messages so they can be sent to Web Inspector.

* Modules/websockets/WebSocket.cpp:
(WebCore::WebSocket::didReceiveMessage):
(WebCore::WebSocket::didReceiveBinaryData):
(WebCore::WebSocket::didReceiveMessageError):
(WebCore::WebSocket::didClose):
* Modules/websockets/WebSocket.h:
- Move inspector instrumentation calls from `WebKit::WebSocketChannel` to here so that they are not called until
the socket is resumed.
- We also now wrap these instrumentation calls in an unlikely check for frontends to avoid allocating the
simulated call frames when Web Inspector isn't even open.

* Modules/websockets/WebSocketChannelInspector.cpp:
(WebCore::WebSocketChannelInspector::WebSocketChannelInspector):
(WebCore::WebSocketChannelInspector::didCreateWebSocket const):
(WebCore::WebSocketChannelInspector::willSendWebSocketHandshakeRequest const):
(WebCore::WebSocketChannelInspector::didReceiveWebSocketHandshakeResponse const):
(WebCore::WebSocketChannelInspector::didCloseWebSocket const):
(WebCore::WebSocketChannelInspector::didReceiveWebSocketFrame const):
(WebCore::WebSocketChannelInspector::didSendWebSocketFrame const):
(WebCore::WebSocketChannelInspector::didReceiveWebSocketFrameError const):
(WebCore::WebSocketChannelInspector::createFrame):
(WebCore::WebSocketChannelInspector::didCreateWebSocket): Deleted.
(WebCore::WebSocketChannelInspector::willSendWebSocketHandshakeRequest): Deleted.
(WebCore::WebSocketChannelInspector::didReceiveWebSocketHandshakeResponse): Deleted.
(WebCore::WebSocketChannelInspector::didCloseWebSocket): Deleted.
(WebCore::WebSocketChannelInspector::didReceiveWebSocketFrame): Deleted.
(WebCore::WebSocketChannelInspector::didSendWebSocketFrame): Deleted.
(WebCore::WebSocketChannelInspector::didReceiveWebSocketFrameError): Deleted.
* Modules/websockets/WebSocketChannelInspector.h:
- Update to keep a WeakRef to the `Document` to reduce the amount of plumbing necessary to call these methods
from `WebSocket`.
- Move static utility method `createFrame` here from `WebKit::WebSocketChannel` since it is only used for
inspector instrumentation.

* Modules/websockets/WorkerThreadableWebSocketChannel.cpp:
(WebCore::WorkerThreadableWebSocketChannel::Peer::didReceiveMessageError):
(WebCore::WorkerThreadableWebSocketChannel::Bridge::connect):
* Modules/websockets/WorkerThreadableWebSocketChannel.h:
* Modules/websockets/ThreadableWebSocketChannelClientWrapper.cpp:
(WebCore::ThreadableWebSocketChannelClientWrapper::didReceiveMessageError):
* Modules/websockets/ThreadableWebSocketChannelClientWrapper.h:
* Modules/websockets/WebSocketChannel.cpp:
(WebCore::WebSocketChannel::fail):
(WebCore::WebSocketChannel::didFailSocketStream):
* Modules/websockets/WebSocketChannel.h:
- Update these classes to pass along a reason, if available, for errors.

Source/WebKit:

Move inspector instrumentation for things that should be delayed until the websocket has resumed (in general,
these are instrumentation points for receiving messages) into WebCore::WebSocket so that they are sent at the
expected time in the frontend, not "in the future" when script execution is suspended (e.g. while debugging).

* WebProcess/Network/WebSocketChannel.cpp:
(WebKit::WebSocketChannel::notifySendFrame):
(WebKit::WebSocketChannel::connect):
(WebKit::WebSocketChannel::close):
(WebKit::WebSocketChannel::fail):
(WebKit::WebSocketChannel::disconnect):
(WebKit::WebSocketChannel::didReceiveText):
(WebKit::WebSocketChannel::didReceiveBinaryData):
(WebKit::WebSocketChannel::didClose):
(WebKit::WebSocketChannel::didReceiveMessageError):
(WebKit::WebSocketChannel::didSendHandshakeRequest):
(WebKit::WebSocketChannel::didReceiveHandshakeResponse):
(WebKit::createWebSocketFrameForWebInspector): Deleted.
* WebProcess/Network/WebSocketChannel.h:

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (290855 => 290856)


--- trunk/Source/WebCore/ChangeLog	2022-03-05 01:01:11 UTC (rev 290855)
+++ trunk/Source/WebCore/ChangeLog	2022-03-05 01:06:41 UTC (rev 290856)
@@ -1,3 +1,84 @@
+2022-03-04  Patrick Angle  <pan...@apple.com>
+
+        REGRESSION (r284472): [ Monterey ] http/tests/websocket/tests/hybi/inspector/send-and-recieve-debugger.html is failing
+        https://bugs.webkit.org/show_bug.cgi?id=237280
+
+        Reviewed by Devin Rousso.
+
+        Covered by existing http/tests/websocket/tests/hybi/inspector/* test cases.
+
+        On macOS Monterey we use NSURLSession-based WebSockets by default, unlike earlier versions of macOS. The channel
+        for these sockets is implemented in `WebKit::WebSocketChannel`. The non-NSURLSession WebSockets channel (at
+        least on Cocoa platforms) is implemented in `WebCore::WebSocketChannel`.
+
+        As of r284472 the logic to delay the dispatch of received WebSocket message on platforms using
+        NSURLSession-based WebSockets is handled by `WebCore::WebSocket`, not the `WebKit::WebSocketChannel`.
+        `WebKit::WebSocketChannel` now immediately does the work it needs to, and only the delegated work to `WebSocket`
+        is queued and taken care of when the socket has resumed. This resulted in some of the instrumentation in
+        `WebKit::WebSocketChannel` being able to be called while the socket was suspended leading to events being logged
+        in the frontend "in the future" (e.g. before the paused script would have been able to be aware of them). To
+        correct this the `WebKit::WebSocketChannel` now provides a hook into its helper `WebSocketChannelInspector`
+        object to allow the `WebCore::WebSocket` to notify Web Inspector of events at the same time it is being
+        logically handled by the page.
+
+        Other `ThreadableWebSocketChannel` implementations will instead provide `nullptr` in place of a pointer to a
+        `WebInspectorChannelInspector`. `WebCore::WebSocketChannel` was not affected by the changes in r284472 as it has
+        a different way to guarantee that the methods containing InspectorInstrumentation were not called while the
+        channel was suspended (and enforced with numerous `ASSERT(!m_suspended)` checks).
+
+        * Modules/websockets/ThreadableWebSocketChannel.h:
+        (WebCore::ThreadableWebSocketChannel::channelInspector const):
+
+        * Modules/websockets/WebSocketChannelClient.h:
+        - Add `reason` for error messages so they can be sent to Web Inspector.
+
+        * Modules/websockets/WebSocket.cpp:
+        (WebCore::WebSocket::didReceiveMessage):
+        (WebCore::WebSocket::didReceiveBinaryData):
+        (WebCore::WebSocket::didReceiveMessageError):
+        (WebCore::WebSocket::didClose):
+        * Modules/websockets/WebSocket.h:
+        - Move inspector instrumentation calls from `WebKit::WebSocketChannel` to here so that they are not called until
+        the socket is resumed.
+        - We also now wrap these instrumentation calls in an unlikely check for frontends to avoid allocating the 
+        simulated call frames when Web Inspector isn't even open.
+        
+        * Modules/websockets/WebSocketChannelInspector.cpp:
+        (WebCore::WebSocketChannelInspector::WebSocketChannelInspector):
+        (WebCore::WebSocketChannelInspector::didCreateWebSocket const):
+        (WebCore::WebSocketChannelInspector::willSendWebSocketHandshakeRequest const):
+        (WebCore::WebSocketChannelInspector::didReceiveWebSocketHandshakeResponse const):
+        (WebCore::WebSocketChannelInspector::didCloseWebSocket const):
+        (WebCore::WebSocketChannelInspector::didReceiveWebSocketFrame const):
+        (WebCore::WebSocketChannelInspector::didSendWebSocketFrame const):
+        (WebCore::WebSocketChannelInspector::didReceiveWebSocketFrameError const):
+        (WebCore::WebSocketChannelInspector::createFrame):
+        (WebCore::WebSocketChannelInspector::didCreateWebSocket): Deleted.
+        (WebCore::WebSocketChannelInspector::willSendWebSocketHandshakeRequest): Deleted.
+        (WebCore::WebSocketChannelInspector::didReceiveWebSocketHandshakeResponse): Deleted.
+        (WebCore::WebSocketChannelInspector::didCloseWebSocket): Deleted.
+        (WebCore::WebSocketChannelInspector::didReceiveWebSocketFrame): Deleted.
+        (WebCore::WebSocketChannelInspector::didSendWebSocketFrame): Deleted.
+        (WebCore::WebSocketChannelInspector::didReceiveWebSocketFrameError): Deleted.
+        * Modules/websockets/WebSocketChannelInspector.h:
+        - Update to keep a WeakRef to the `Document` to reduce the amount of plumbing necessary to call these methods
+        from `WebSocket`.
+        - Move static utility method `createFrame` here from `WebKit::WebSocketChannel` since it is only used for
+        inspector instrumentation.
+
+        * Modules/websockets/WorkerThreadableWebSocketChannel.cpp:
+        (WebCore::WorkerThreadableWebSocketChannel::Peer::didReceiveMessageError):
+        (WebCore::WorkerThreadableWebSocketChannel::Bridge::connect):
+        * Modules/websockets/WorkerThreadableWebSocketChannel.h:
+        * Modules/websockets/ThreadableWebSocketChannelClientWrapper.cpp:
+        (WebCore::ThreadableWebSocketChannelClientWrapper::didReceiveMessageError):
+        * Modules/websockets/ThreadableWebSocketChannelClientWrapper.h:
+        * Modules/websockets/WebSocketChannel.cpp:
+        (WebCore::WebSocketChannel::fail):
+        (WebCore::WebSocketChannel::didFailSocketStream):
+        * Modules/websockets/WebSocketChannel.h:
+        - Update these classes to pass along a reason, if available, for errors.
+
 2022-03-04  Chris Dumez  <cdu...@apple.com>
 
         Modernize OriginLock

Modified: trunk/Source/WebCore/Modules/websockets/ThreadableWebSocketChannel.h (290855 => 290856)


--- trunk/Source/WebCore/Modules/websockets/ThreadableWebSocketChannel.h	2022-03-05 01:01:11 UTC (rev 290855)
+++ trunk/Source/WebCore/Modules/websockets/ThreadableWebSocketChannel.h	2022-03-05 01:06:41 UTC (rev 290856)
@@ -49,6 +49,7 @@
 class ScriptExecutionContext;
 class SocketProvider;
 class WebSocketChannel;
+class WebSocketChannelInspector;
 class WebSocketChannelClient;
 
 using WebSocketChannelIdentifier = ObjectIdentifier<WebSocketChannel>;
@@ -84,6 +85,7 @@
     virtual void suspend() = 0;
     virtual void resume() = 0;
 
+    virtual const WebSocketChannelInspector* channelInspector() const { return nullptr; };
     virtual WebSocketChannelIdentifier progressIdentifier() const = 0;
     virtual bool hasCreatedHandshake() const = 0;
     virtual bool isConnected() const = 0;

Modified: trunk/Source/WebCore/Modules/websockets/ThreadableWebSocketChannelClientWrapper.cpp (290855 => 290856)


--- trunk/Source/WebCore/Modules/websockets/ThreadableWebSocketChannelClientWrapper.cpp	2022-03-05 01:01:11 UTC (rev 290855)
+++ trunk/Source/WebCore/Modules/websockets/ThreadableWebSocketChannelClientWrapper.cpp	2022-03-05 01:06:41 UTC (rev 290856)
@@ -217,11 +217,11 @@
         processPendingTasks();
 }
 
-void ThreadableWebSocketChannelClientWrapper::didReceiveMessageError()
+void ThreadableWebSocketChannelClientWrapper::didReceiveMessageError(const String& reason)
 {
-    m_pendingTasks.append(makeUnique<ScriptExecutionContext::Task>([this, protectedThis = Ref { *this }] (ScriptExecutionContext&) {
+    m_pendingTasks.append(makeUnique<ScriptExecutionContext::Task>([this, protectedThis = Ref { *this }, reason = reason.isolatedCopy()] (ScriptExecutionContext&) {
         if (m_client)
-            m_client->didReceiveMessageError();
+            m_client->didReceiveMessageError(reason);
     }));
 
     if (!m_suspended)

Modified: trunk/Source/WebCore/Modules/websockets/ThreadableWebSocketChannelClientWrapper.h (290855 => 290856)


--- trunk/Source/WebCore/Modules/websockets/ThreadableWebSocketChannelClientWrapper.h	2022-03-05 01:01:11 UTC (rev 290855)
+++ trunk/Source/WebCore/Modules/websockets/ThreadableWebSocketChannelClientWrapper.h	2022-03-05 01:06:41 UTC (rev 290856)
@@ -79,7 +79,7 @@
     void didUpdateBufferedAmount(unsigned bufferedAmount);
     void didStartClosingHandshake();
     void didClose(unsigned unhandledBufferedAmount, WebSocketChannelClient::ClosingHandshakeCompletionStatus, unsigned short code, const String& reason);
-    void didReceiveMessageError();
+    void didReceiveMessageError(const String& reason);
     void didUpgradeURL();
 
     void suspend();

Modified: trunk/Source/WebCore/Modules/websockets/WebSocket.cpp (290855 => 290856)


--- trunk/Source/WebCore/Modules/websockets/WebSocket.cpp	2022-03-05 01:01:11 UTC (rev 290855)
+++ trunk/Source/WebCore/Modules/websockets/WebSocket.cpp	2022-03-05 01:06:41 UTC (rev 290856)
@@ -43,6 +43,7 @@
 #include "Frame.h"
 #include "FrameLoader.h"
 #include "FrameLoaderClient.h"
+#include "InspectorInstrumentation.h"
 #include "Logging.h"
 #include "MessageEvent.h"
 #include "MixedContentChecker.h"
@@ -565,6 +566,13 @@
     queueTaskKeepingObjectAlive(*this, TaskSource::WebSocket, [this, msg] {
         if (m_state != OPEN)
             return;
+
+        if (UNLIKELY(InspectorInstrumentation::hasFrontends())) {
+            if (auto* inspector = m_channel->channelInspector()) {
+                auto utf8Message = msg.utf8();
+                inspector->didReceiveWebSocketFrame(WebSocketChannelInspector::createFrame(utf8Message.dataAsUInt8Ptr(), utf8Message.length(), WebSocketFrame::OpCode::OpCodeText));
+            }
+        }
         ASSERT(scriptExecutionContext());
         dispatchEvent(MessageEvent::create(msg, SecurityOrigin::create(m_url)->toString()));
     });
@@ -576,6 +584,12 @@
     queueTaskKeepingObjectAlive(*this, TaskSource::WebSocket, [this, binaryData = WTFMove(binaryData)]() mutable {
         if (m_state != OPEN)
             return;
+
+        if (UNLIKELY(InspectorInstrumentation::hasFrontends())) {
+            if (auto* inspector = m_channel->channelInspector())
+                inspector->didReceiveWebSocketFrame(WebSocketChannelInspector::createFrame(binaryData.data(), binaryData.size(), WebSocketFrame::OpCode::OpCodeBinary));
+        }
+
         switch (m_binaryType) {
         case BinaryType::Blob:
             // FIXME: We just received the data from NetworkProcess, and are sending it back. This is inefficient.
@@ -588,14 +602,20 @@
     });
 }
 
-void WebSocket::didReceiveMessageError()
+void WebSocket::didReceiveMessageError(const String& reason)
 {
     LOG(Network, "WebSocket %p didReceiveErrorMessage()", this);
-    queueTaskKeepingObjectAlive(*this, TaskSource::WebSocket, [this] {
+    queueTaskKeepingObjectAlive(*this, TaskSource::WebSocket, [this, reason] {
         if (m_state == CLOSED)
             return;
         m_state = CLOSED;
         ASSERT(scriptExecutionContext());
+
+        if (UNLIKELY(InspectorInstrumentation::hasFrontends())) {
+            if (auto* inspector = m_channel->channelInspector())
+                inspector->didReceiveWebSocketFrameError(reason);
+        }
+
         // FIXME: As per https://html.spec.whatwg.org/multipage/web-sockets.html#feedback-from-the-protocol:concept-websocket-closed, we should synchronously fire a close event.
         dispatchErrorEventIfNeeded();
     });
@@ -626,6 +646,14 @@
         if (!m_channel)
             return;
 
+        if (UNLIKELY(InspectorInstrumentation::hasFrontends())) {
+            if (auto* inspector = m_channel->channelInspector()) {
+                WebSocketFrame closingFrame(WebSocketFrame::OpCodeClose, true, false, false);
+                inspector->didReceiveWebSocketFrame(closingFrame);
+                inspector->didCloseWebSocket();
+            }
+        }
+
         bool wasClean = m_state == CLOSING && !unhandledBufferedAmount && closingHandshakeCompletion == ClosingHandshakeComplete && code != WebSocketChannel::CloseEventCodeAbnormalClosure;
         m_state = CLOSED;
         m_bufferedAmount = unhandledBufferedAmount;

Modified: trunk/Source/WebCore/Modules/websockets/WebSocket.h (290855 => 290856)


--- trunk/Source/WebCore/Modules/websockets/WebSocket.h	2022-03-05 01:01:11 UTC (rev 290855)
+++ trunk/Source/WebCore/Modules/websockets/WebSocket.h	2022-03-05 01:06:41 UTC (rev 290856)
@@ -115,7 +115,7 @@
     void didConnect() final;
     void didReceiveMessage(const String& message) final;
     void didReceiveBinaryData(Vector<uint8_t>&&) final;
-    void didReceiveMessageError() final;
+    void didReceiveMessageError(const String& reason) final;
     void didUpdateBufferedAmount(unsigned bufferedAmount) final;
     void didStartClosingHandshake() final;
     void didClose(unsigned unhandledBufferedAmount, ClosingHandshakeCompletionStatus, unsigned short code, const String& reason) final;

Modified: trunk/Source/WebCore/Modules/websockets/WebSocketChannel.cpp (290855 => 290856)


--- trunk/Source/WebCore/Modules/websockets/WebSocketChannel.cpp	2022-03-05 01:01:11 UTC (rev 290855)
+++ trunk/Source/WebCore/Modules/websockets/WebSocketChannel.cpp	2022-03-05 01:06:41 UTC (rev 290856)
@@ -239,7 +239,7 @@
     m_hasContinuousFrame = false;
     m_continuousFrameData.clear();
     if (m_client)
-        m_client->didReceiveMessageError();
+        m_client->didReceiveMessageError(reason);
 
     if (m_handle && !m_closed)
         m_handle->disconnect(); // Will call didCloseSocketStream() but maybe not synchronously.
@@ -365,14 +365,16 @@
 {
     LOG(Network, "WebSocketChannel %p didFailSocketStream()", this);
     ASSERT(&handle == m_handle || !m_handle);
+
+    String message;
+    if (error.isNull())
+        message = "WebSocket network error"_s;
+    else if (error.localizedDescription().isNull())
+        message = makeString("WebSocket network error: error code ", error.errorCode());
+    else
+        message = "WebSocket network error: " + error.localizedDescription();
+
     if (m_document) {
-        String message;
-        if (error.isNull())
-            message = "WebSocket network error"_s;
-        else if (error.localizedDescription().isNull())
-            message = makeString("WebSocket network error: error code ", error.errorCode());
-        else
-            message = "WebSocket network error: " + error.localizedDescription();
         InspectorInstrumentation::didReceiveWebSocketFrameError(m_document.get(), m_progressIdentifier, message);
         m_document->addConsoleMessage(MessageSource::Network, MessageLevel::Error, message);
         LOG_ERROR("%s", message.utf8().data());
@@ -379,7 +381,7 @@
     }
     m_shouldDiscardReceivedData = true;
     if (m_client)
-        m_client->didReceiveMessageError();
+        m_client->didReceiveMessageError(message);
     handle.disconnect();
 }
 

Modified: trunk/Source/WebCore/Modules/websockets/WebSocketChannel.h (290855 => 290856)


--- trunk/Source/WebCore/Modules/websockets/WebSocketChannel.h	2022-03-05 01:01:11 UTC (rev 290855)
+++ trunk/Source/WebCore/Modules/websockets/WebSocketChannel.h	2022-03-05 01:06:41 UTC (rev 290856)
@@ -35,6 +35,7 @@
 #include "SocketStreamHandleClient.h"
 #include "ThreadableWebSocketChannel.h"
 #include "Timer.h"
+#include "WebSocketChannelInspector.h"
 #include "WebSocketDeflateFramer.h"
 #include "WebSocketFrame.h"
 #include "WebSocketHandshake.h"

Modified: trunk/Source/WebCore/Modules/websockets/WebSocketChannelClient.h (290855 => 290856)


--- trunk/Source/WebCore/Modules/websockets/WebSocketChannelClient.h	2022-03-05 01:01:11 UTC (rev 290855)
+++ trunk/Source/WebCore/Modules/websockets/WebSocketChannelClient.h	2022-03-05 01:06:41 UTC (rev 290856)
@@ -41,7 +41,7 @@
     virtual void didConnect() = 0;
     virtual void didReceiveMessage(const String&) = 0;
     virtual void didReceiveBinaryData(Vector<uint8_t>&&) = 0;
-    virtual void didReceiveMessageError() = 0;
+    virtual void didReceiveMessageError(const String&) = 0;
     virtual void didUpdateBufferedAmount(unsigned bufferedAmount) = 0;
     virtual void didStartClosingHandshake() = 0;
     enum ClosingHandshakeCompletionStatus {

Modified: trunk/Source/WebCore/Modules/websockets/WebSocketChannelInspector.cpp (290855 => 290856)


--- trunk/Source/WebCore/Modules/websockets/WebSocketChannelInspector.cpp	2022-03-05 01:01:11 UTC (rev 290855)
+++ trunk/Source/WebCore/Modules/websockets/WebSocketChannelInspector.cpp	2022-03-05 01:06:41 UTC (rev 290856)
@@ -30,66 +30,70 @@
 #include "InspectorInstrumentation.h"
 #include "Page.h"
 #include "ProgressTracker.h"
+#include "WebSocketFrame.h"
 
 namespace WebCore {
 
-WebSocketChannelInspector::WebSocketChannelInspector(Document&)
-    : m_progressIdentifier(WebSocketChannelIdentifier::generateThreadSafe()) { }
+WebSocketChannelInspector::WebSocketChannelInspector(Document& document)
+    : m_document(document)
+    , m_progressIdentifier(WebSocketChannelIdentifier::generateThreadSafe())
+{
+}
 
-void WebSocketChannelInspector::didCreateWebSocket(Document* document, const URL& url)
+void WebSocketChannelInspector::didCreateWebSocket(const URL& url) const
 {
-    if (!m_progressIdentifier || !document)
+    if (!m_progressIdentifier || !m_document)
         return;
 
-    InspectorInstrumentation::didCreateWebSocket(document, m_progressIdentifier, url);
+    InspectorInstrumentation::didCreateWebSocket(m_document.get(), m_progressIdentifier, url);
 }
 
-void WebSocketChannelInspector::willSendWebSocketHandshakeRequest(Document* document, const ResourceRequest& request)
+void WebSocketChannelInspector::willSendWebSocketHandshakeRequest(const ResourceRequest& request) const
 {
-    if (!m_progressIdentifier || !document)
+    if (!m_progressIdentifier || !m_document)
         return;
 
-    InspectorInstrumentation::willSendWebSocketHandshakeRequest(document, m_progressIdentifier, request);
+    InspectorInstrumentation::willSendWebSocketHandshakeRequest(m_document.get(), m_progressIdentifier, request);
 }
 
-void WebSocketChannelInspector::didReceiveWebSocketHandshakeResponse(Document* document, const ResourceResponse& response)
+void WebSocketChannelInspector::didReceiveWebSocketHandshakeResponse(const ResourceResponse& response) const
 {
-    if (!m_progressIdentifier || !document)
+    if (!m_progressIdentifier || !m_document)
         return;
 
-    InspectorInstrumentation::didReceiveWebSocketHandshakeResponse(document, m_progressIdentifier, response);
+    InspectorInstrumentation::didReceiveWebSocketHandshakeResponse(m_document.get(), m_progressIdentifier, response);
 }
 
-void WebSocketChannelInspector::didCloseWebSocket(Document* document)
+void WebSocketChannelInspector::didCloseWebSocket() const
 {
-    if (!m_progressIdentifier || !document)
+    if (!m_progressIdentifier || !m_document)
         return;
 
-    InspectorInstrumentation::didCloseWebSocket(document, m_progressIdentifier);
+    InspectorInstrumentation::didCloseWebSocket(m_document.get(), m_progressIdentifier);
 }
 
-void WebSocketChannelInspector::didReceiveWebSocketFrame(Document* document, const WebSocketFrame& frame)
+void WebSocketChannelInspector::didReceiveWebSocketFrame(const WebSocketFrame& frame) const
 {
-    if (!m_progressIdentifier || !document)
+    if (!m_progressIdentifier || !m_document)
         return;
 
-    InspectorInstrumentation::didReceiveWebSocketFrame(document, m_progressIdentifier, frame);
+    InspectorInstrumentation::didReceiveWebSocketFrame(m_document.get(), m_progressIdentifier, frame);
 }
 
-void WebSocketChannelInspector::didSendWebSocketFrame(Document* document, const WebSocketFrame& frame)
+void WebSocketChannelInspector::didSendWebSocketFrame(const WebSocketFrame& frame) const
 {
-    if (!m_progressIdentifier || !document)
+    if (!m_progressIdentifier || !m_document)
         return;
 
-    InspectorInstrumentation::didSendWebSocketFrame(document, m_progressIdentifier, frame);
+    InspectorInstrumentation::didSendWebSocketFrame(m_document.get(), m_progressIdentifier, frame);
 }
 
-void WebSocketChannelInspector::didReceiveWebSocketFrameError(Document* document, const String& errorMessage)
+void WebSocketChannelInspector::didReceiveWebSocketFrameError(const String& errorMessage) const
 {
-    if (!m_progressIdentifier || !document)
+    if (!m_progressIdentifier || !m_document)
         return;
 
-    InspectorInstrumentation::didReceiveWebSocketFrameError(document, m_progressIdentifier, errorMessage);
+    InspectorInstrumentation::didReceiveWebSocketFrameError(m_document.get(), m_progressIdentifier, errorMessage);
 }
 
 WebSocketChannelIdentifier WebSocketChannelInspector::progressIdentifier() const
@@ -97,4 +101,22 @@
     return m_progressIdentifier;
 }
 
+WebSocketFrame WebSocketChannelInspector::createFrame(const uint8_t* data, size_t length, WebSocketFrame::OpCode opCode)
+{
+    // This is an approximation since frames can be merged on a single message.
+    WebSocketFrame frame;
+    frame.opCode = opCode;
+    frame.masked = false;
+    frame.payload = data;
+    frame.payloadLength = length;
+
+    // WebInspector does not use them.
+    frame.final = false;
+    frame.compress = false;
+    frame.reserved2 = false;
+    frame.reserved3 = false;
+
+    return frame;
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/Modules/websockets/WebSocketChannelInspector.h (290855 => 290856)


--- trunk/Source/WebCore/Modules/websockets/WebSocketChannelInspector.h	2022-03-05 01:01:11 UTC (rev 290855)
+++ trunk/Source/WebCore/Modules/websockets/WebSocketChannelInspector.h	2022-03-05 01:06:41 UTC (rev 290856)
@@ -25,6 +25,7 @@
 
 #pragma once
 
+#include "WebSocketFrame.h"
 #include <wtf/Forward.h>
 #include <wtf/ObjectIdentifier.h>
 
@@ -35,7 +36,6 @@
 class ResourceResponse;
 class WebSocketChannel;
 class WebSocketChannelInspector;
-struct WebSocketFrame;
 
 using WebSocketChannelIdentifier = ObjectIdentifier<WebSocketChannel>;
 
@@ -43,17 +43,20 @@
 public:
     explicit WebSocketChannelInspector(Document&);
 
-    void didCreateWebSocket(Document*, const URL&);
-    void willSendWebSocketHandshakeRequest(Document*, const ResourceRequest&);
-    void didReceiveWebSocketHandshakeResponse(Document*, const ResourceResponse&);
-    void didCloseWebSocket(Document*);
-    void didReceiveWebSocketFrame(Document*, const WebSocketFrame&);
-    void didSendWebSocketFrame(Document*, const WebSocketFrame&);
-    void didReceiveWebSocketFrameError(Document*, const String& errorMessage);
+    void didCreateWebSocket(const URL&) const;
+    void willSendWebSocketHandshakeRequest(const ResourceRequest&) const;
+    void didReceiveWebSocketHandshakeResponse(const ResourceResponse&) const;
+    void didCloseWebSocket() const;
+    void didReceiveWebSocketFrame(const WebSocketFrame&) const;
+    void didSendWebSocketFrame(const WebSocketFrame&) const;
+    void didReceiveWebSocketFrameError(const String& errorMessage) const;
     
     WebSocketChannelIdentifier progressIdentifier() const;
 
+    static WebSocketFrame createFrame(const uint8_t* data, size_t length, WebSocketFrame::OpCode);
+
 private:
+    WeakPtr<Document> m_document;
     WebSocketChannelIdentifier m_progressIdentifier;
 };
 

Modified: trunk/Source/WebCore/Modules/websockets/WorkerThreadableWebSocketChannel.cpp (290855 => 290856)


--- trunk/Source/WebCore/Modules/websockets/WorkerThreadableWebSocketChannel.cpp	2022-03-05 01:01:11 UTC (rev 290855)
+++ trunk/Source/WebCore/Modules/websockets/WorkerThreadableWebSocketChannel.cpp	2022-03-05 01:06:41 UTC (rev 290856)
@@ -323,13 +323,13 @@
     }, m_taskMode);
 }
 
-void WorkerThreadableWebSocketChannel::Peer::didReceiveMessageError()
+void WorkerThreadableWebSocketChannel::Peer::didReceiveMessageError(const String& reason)
 {
     ASSERT(isMainThread());
 
-    m_loaderProxy.postTaskForModeToWorkerOrWorkletGlobalScope([workerClientWrapper = m_workerClientWrapper](ScriptExecutionContext& context) mutable {
+    m_loaderProxy.postTaskForModeToWorkerOrWorkletGlobalScope([workerClientWrapper = m_workerClientWrapper, reason = reason.isolatedCopy()](ScriptExecutionContext& context) mutable {
         ASSERT_UNUSED(context, context.isWorkerGlobalScope() || context.isWorkletGlobalScope());
-        workerClientWrapper->didReceiveMessageError();
+        workerClientWrapper->didReceiveMessageError(reason);
     }, m_taskMode);
 }
 
@@ -420,7 +420,7 @@
         }
 
         if (peer->connect(url, protocol) == ThreadableWebSocketChannel::ConnectStatus::KO)
-            peer->didReceiveMessageError();
+            peer->didReceiveMessageError(nullString());
     });
 }
 

Modified: trunk/Source/WebCore/Modules/websockets/WorkerThreadableWebSocketChannel.h (290855 => 290856)


--- trunk/Source/WebCore/Modules/websockets/WorkerThreadableWebSocketChannel.h	2022-03-05 01:01:11 UTC (rev 290855)
+++ trunk/Source/WebCore/Modules/websockets/WorkerThreadableWebSocketChannel.h	2022-03-05 01:06:41 UTC (rev 290856)
@@ -94,7 +94,7 @@
         void didUpdateBufferedAmount(unsigned bufferedAmount) final;
         void didStartClosingHandshake() final;
         void didClose(unsigned unhandledBufferedAmount, ClosingHandshakeCompletionStatus, unsigned short code, const String& reason) final;
-        void didReceiveMessageError() final;
+        void didReceiveMessageError(const String& reason) final;
         void didUpgradeURL() final;
 
     private:

Modified: trunk/Source/WebKit/ChangeLog (290855 => 290856)


--- trunk/Source/WebKit/ChangeLog	2022-03-05 01:01:11 UTC (rev 290855)
+++ trunk/Source/WebKit/ChangeLog	2022-03-05 01:06:41 UTC (rev 290856)
@@ -1,5 +1,31 @@
 2022-03-04  Patrick Angle  <pan...@apple.com>
 
+        REGRESSION (r284472): [ Monterey ] http/tests/websocket/tests/hybi/inspector/send-and-recieve-debugger.html is failing
+        https://bugs.webkit.org/show_bug.cgi?id=237280
+
+        Reviewed by Devin Rousso.
+
+        Move inspector instrumentation for things that should be delayed until the websocket has resumed (in general,
+        these are instrumentation points for receiving messages) into WebCore::WebSocket so that they are sent at the
+        expected time in the frontend, not "in the future" when script execution is suspended (e.g. while debugging).
+
+        * WebProcess/Network/WebSocketChannel.cpp:
+        (WebKit::WebSocketChannel::notifySendFrame):
+        (WebKit::WebSocketChannel::connect):
+        (WebKit::WebSocketChannel::close):
+        (WebKit::WebSocketChannel::fail):
+        (WebKit::WebSocketChannel::disconnect):
+        (WebKit::WebSocketChannel::didReceiveText):
+        (WebKit::WebSocketChannel::didReceiveBinaryData):
+        (WebKit::WebSocketChannel::didClose):
+        (WebKit::WebSocketChannel::didReceiveMessageError):
+        (WebKit::WebSocketChannel::didSendHandshakeRequest):
+        (WebKit::WebSocketChannel::didReceiveHandshakeResponse):
+        (WebKit::createWebSocketFrameForWebInspector): Deleted.
+        * WebProcess/Network/WebSocketChannel.h:
+
+2022-03-04  Patrick Angle  <pan...@apple.com>
+
         Web Inspector: [Cocoa] Continually opening and closing Web Inspector sometimes crashes
         https://bugs.webkit.org/show_bug.cgi?id=237484
 

Modified: trunk/Source/WebKit/WebProcess/Network/WebSocketChannel.cpp (290855 => 290856)


--- trunk/Source/WebKit/WebProcess/Network/WebSocketChannel.cpp	2022-03-05 01:01:11 UTC (rev 290855)
+++ trunk/Source/WebKit/WebProcess/Network/WebSocketChannel.cpp	2022-03-05 01:06:41 UTC (rev 290856)
@@ -51,7 +51,7 @@
 void WebSocketChannel::notifySendFrame(WebSocketFrame::OpCode opCode, const uint8_t* data, size_t length)
 {
     WebSocketFrame frame(opCode, true, false, true, data, length);
-    m_inspector.didSendWebSocketFrame(m_document.get(), frame);
+    m_inspector.didSendWebSocketFrame(frame);
 }
 
 NetworkSendQueue WebSocketChannel::createMessageQueue(Document& document, WebSocketChannel& channel)
@@ -116,7 +116,7 @@
     if (request->url() != url && m_client)
         m_client->didUpgradeURL();
 
-    m_inspector.didCreateWebSocket(m_document.get(), url);
+    m_inspector.didCreateWebSocket(url);
     m_url = request->url();
     MessageSender::send(Messages::NetworkConnectionToWebProcess::CreateSocketChannel { *request, protocol, m_identifier, m_webPageProxyID, m_document->clientOrigin(), WebProcess::singleton().hadMainFrameMainResourcePrivateRelayed() });
     return ConnectStatus::OK;
@@ -208,7 +208,7 @@
     ASSERT(code >= 0 || code == WebCore::WebSocketChannel::CloseEventCodeNotSpecified);
 
     WebSocketFrame closingFrame(WebSocketFrame::OpCodeClose, true, false, true);
-    m_inspector.didSendWebSocketFrame(m_document.get(), closingFrame);
+    m_inspector.didSendWebSocketFrame(closingFrame);
 
     MessageSender::send(Messages::NetworkSocketChannel::Close { code, reason });
 }
@@ -220,7 +220,7 @@
 
     logErrorMessage(reason);
     if (m_client)
-        m_client->didReceiveMessageError();
+        m_client->didReceiveMessageError(reason);
 
     if (m_isClosing)
         return;
@@ -235,7 +235,7 @@
     m_document = nullptr;
     m_messageQueue.clear();
 
-    m_inspector.didCloseWebSocket(m_document.get());
+    m_inspector.didCloseWebSocket();
 
     MessageSender::send(Messages::NetworkSocketChannel::Close { WebCore::WebSocketChannel::CloseEventCodeGoingAway, { } });
 }
@@ -253,24 +253,6 @@
     m_client->didConnect();
 }
 
-static inline WebSocketFrame createWebSocketFrameForWebInspector(const uint8_t* data, size_t length, WebSocketFrame::OpCode opCode)
-{
-    // This is an approximation since frames can be merged on a single message.
-    WebSocketFrame frame;
-    frame.opCode = opCode;
-    frame.masked = false;
-    frame.payload = data;
-    frame.payloadLength = length;
-
-    // WebInspector does not use them.
-    frame.final = false;
-    frame.compress = false;
-    frame.reserved2 = false;
-    frame.reserved3 = false;
-
-    return frame;
-}
-
 void WebSocketChannel::didReceiveText(String&& message)
 {
     if (m_isClosing)
@@ -279,9 +261,6 @@
     if (!m_client)
         return;
 
-    auto utf8Message = message.utf8();
-    m_inspector.didReceiveWebSocketFrame(m_document.get(), createWebSocketFrameForWebInspector(utf8Message.dataAsUInt8Ptr(), utf8Message.length(), WebSocketFrame::OpCode::OpCodeText));
-
     m_client->didReceiveMessage(message);
 }
 
@@ -293,8 +272,6 @@
     if (!m_client)
         return;
 
-    m_inspector.didReceiveWebSocketFrame(m_document.get(), createWebSocketFrameForWebInspector(data.data(), data.size(), WebSocketFrame::OpCode::OpCodeBinary));
-
     m_client->didReceiveBinaryData({ data });
 }
 
@@ -303,10 +280,6 @@
     if (!m_client)
         return;
 
-    WebSocketFrame closingFrame(WebSocketFrame::OpCodeClose, true, false, false);
-    m_inspector.didReceiveWebSocketFrame(m_document.get(), closingFrame);
-    m_inspector.didCloseWebSocket(m_document.get());
-
     // An attempt to send closing handshake may fail, which will get the channel closed and dereferenced.
     Ref protectedThis { *this };
 
@@ -336,7 +309,7 @@
         return;
 
     logErrorMessage(errorMessage);
-    m_client->didReceiveMessageError();
+    m_client->didReceiveMessageError(errorMessage);
 }
 
 void WebSocketChannel::networkProcessCrashed()
@@ -354,13 +327,13 @@
 
 void WebSocketChannel::didSendHandshakeRequest(ResourceRequest&& request)
 {
-    m_inspector.willSendWebSocketHandshakeRequest(m_document.get(), request);
+    m_inspector.willSendWebSocketHandshakeRequest(request);
     m_handshakeRequest = WTFMove(request);
 }
 
 void WebSocketChannel::didReceiveHandshakeResponse(ResourceResponse&& response)
 {
-    m_inspector.didReceiveWebSocketHandshakeResponse(m_document.get(), response);
+    m_inspector.didReceiveWebSocketHandshakeResponse(response);
     m_handshakeResponse = WTFMove(response);
 }
 

Modified: trunk/Source/WebKit/WebProcess/Network/WebSocketChannel.h (290855 => 290856)


--- trunk/Source/WebKit/WebProcess/Network/WebSocketChannel.h	2022-03-05 01:01:11 UTC (rev 290855)
+++ trunk/Source/WebKit/WebProcess/Network/WebSocketChannel.h	2022-03-05 01:06:41 UTC (rev 290856)
@@ -97,6 +97,7 @@
     void decreaseBufferedAmount(size_t);
     template<typename T> void sendMessage(T&&, size_t byteLength);
 
+    const WebCore::WebSocketChannelInspector* channelInspector() const final { return &m_inspector; }
     WebCore::WebSocketChannelIdentifier progressIdentifier() const final { return m_inspector.progressIdentifier(); }
     bool hasCreatedHandshake() const final { return !m_url.isNull(); }
     bool isConnected() const final { return !m_handshakeResponse.isNull(); }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to