Skip to content

Commit

Permalink
Web Inspector: support EventSource resource type in Network Panel
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=240326

Reviewed by Devin Rousso.

* http/tests/inspector/network/eventsource-type-expected.txt: Added.
* http/tests/inspector/network/eventsource-type.html: Added.
* http/tests/inspector/network/resources/event-source.py: Added.
Web Inspector: support EventSource resource type in Network Panel
https://bugs.webkit.org/show_bug.cgi?id=240326

* inspector/protocol/Page.json: added EventSource resource type.
Web Inspector: support EventSource resource type in Network Panel
https://bugs.webkit.org/show_bug.cgi?id=240326

Network requests initiated by EventSource now have their own requester
type which allows to distinguish them from other requests.

Test: http/tests/inspector/network/eventsource-type.html

* inspector/agents/InspectorPageAgent.cpp:
(WebCore::InspectorPageAgent::resourceTypeJSON):
(WebCore::InspectorPageAgent::inspectorResourceType):
* inspector/agents/InspectorPageAgent.h:
* page/EventSource.cpp:
(WebCore::EventSource::connect):
* platform/network/ResourceRequestBase.h:
Web Inspector: support EventSource resource type in Network Panel
https://bugs.webkit.org/show_bug.cgi?id=240326

EventSource initiated requests are now displayed with their own type
in the network panel.

* Localizations/en.lproj/localizedStrings.js:
* UserInterface/Controllers/NetworkManager.js:
(WI.NetworkManager.prototype.canBeOverridden):
* UserInterface/Models/Resource.js:
(WI.Resource.displayNameForType):
* UserInterface/Views/NetworkTableContentView.js:
(WI.NetworkTableContentView.displayNameForResource):

Canonical link: https://commits.webkit.org/250672@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@294374 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
yury-s committed May 18, 2022
1 parent 008baa2 commit 01b7967
Show file tree
Hide file tree
Showing 12 changed files with 149 additions and 3 deletions.
@@ -0,0 +1,20 @@
Tests for Resource.Type.EventSource.


== Running test suite: Resource.Type.EventSource
-- Running test case: Resource.Type.EventSource.1.Event
PASS: Resource should be EventSource type.
PASS: Resource should be a GET request.
EventSource events: onmessage: the end.
PASS: Resource should have a 200 response.
PASS: Resource should receive 'Success' in the response.
PASS: Response should not be base64 encoded.

-- Running test case: Resource.Type.EventSource.3.Events
PASS: Resource should be EventSource type.
PASS: Resource should be a GET request.
EventSource events: user: alice,user: bill,onmessage: the end.
PASS: Resource should have a 200 response.
PASS: Resource should receive 'Success' in the response.
PASS: Response should not be base64 encoded.

74 changes: 74 additions & 0 deletions LayoutTests/http/tests/inspector/network/eventsource-type.html
@@ -0,0 +1,74 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="../resources/inspector-test.js"></script>
<script>
function triggerEventSourceRequest(users) {
const eventSource = new EventSource(`resources/event-source.py?users=${users}`);
const messages = [];
eventSource.addEventListener('user', e => {
messages.push('user: ' + e.data);
});
eventSource.onmessage = e => {
messages.push("onmessage: " + e.data);
TestPage.dispatchEventToFrontend("Completed", messages);
}
}

// ----

function test()
{
const suite = InspectorTest.createAsyncSuite("Resource.Type.EventSource");

function addTestCase({name, description, expression, resourceHandler}) {
suite.addTestCase({
name, description,
async test() {
const completeEvent = InspectorTest.awaitEvent("Completed");
InspectorTest.evaluateInPage(expression);
const event = await WI.Frame.awaitEvent(WI.Frame.Event.ResourceWasAdded);
const resource = event.data.resource;
InspectorTest.assert(resource.url.includes('event-source.py'), `Resource should be "event-source.py"`);
InspectorTest.expectEqual(resource.type, WI.Resource.Type.EventSource, "Resource should be EventSource type.");
InspectorTest.expectEqual(resource.requestMethod, "GET", "Resource should be a GET request.");
await resource.awaitEvent(WI.Resource.Event.LoadingDidFinish);
const content = await resource.requestContentFromBackend()
InspectorTest.log('EventSource events: ' + (await completeEvent).data);
resourceHandler(resource, content);
}
});
}

addTestCase({
name: "Resource.Type.EventSource.1.Event",
description: "Event source that receives 1 event.",
expression: "triggerEventSourceRequest('')",
resourceHandler(resource, content) {
InspectorTest.expectEqual(resource.statusCode, 200, "Resource should have a 200 response.");
InspectorTest.expectEqual(content.body, "data: the end.\n\n", "Resource should receive 'Success' in the response.");
InspectorTest.expectEqual(content.base64Encoded, false, "Response should not be base64 encoded.");
}
});

addTestCase({
name: "Resource.Type.EventSource.3.Events",
description: "Event source that receives 3 events.",
expression: "triggerEventSourceRequest('alice,bill')",
resourceHandler(resource, content) {
InspectorTest.expectEqual(resource.statusCode, 200, "Resource should have a 200 response.");
InspectorTest.expectEqual(content.body, "event: user\ndata: alice\n\nevent: user\ndata: bill\n\ndata: the end.\n\n", "Resource should receive 'Success' in the response.");
InspectorTest.expectEqual(content.base64Encoded, false, "Response should not be base64 encoded.");
}
});

suite.runTestCasesAndFinish();
}
</script>
</head>
<body onload="runTest()">
<p>Tests for Resource.Type.EventSource.</p>
<div id="log"></div>
</body>
</html>
30 changes: 30 additions & 0 deletions LayoutTests/http/tests/inspector/network/resources/event-source.py
@@ -0,0 +1,30 @@
#!/usr/bin/env python3

import os
import sys
from urllib.parse import parse_qs

sys.stdout.write('Content-Type: text/html\r\n')

users = parse_qs(os.environ.get('QUERY_STRING', '')).get('users', [''])[0].split(',')
users = filter(lambda s: len(s), users)

sys.stdout.write(
'Content-Type: text/event-stream\r\n'
'Connection: keep-alive\r\n'
'Cache-Control: no-cache\r\n'
'status: 200\r\n'
'\r\n'
)

for user in users:
sys.stdout.write(
'event: user\n'
'data: {}\n'
'\n'.format(user)
)

sys.stdout.write(
'data: the end.\n'
'\n'
)
2 changes: 1 addition & 1 deletion Source/JavaScriptCore/inspector/protocol/Page.json
Expand Up @@ -27,7 +27,7 @@
{
"id": "ResourceType",
"type": "string",
"enum": ["Document", "StyleSheet", "Image", "Font", "Script", "XHR", "Fetch", "Ping", "Beacon", "WebSocket", "Other"],
"enum": ["Document", "StyleSheet", "Image", "Font", "Script", "XHR", "Fetch", "Ping", "Beacon", "WebSocket", "EventSource", "Other"],
"description": "Resource type as it was perceived by the rendering engine."
},
{
Expand Down
4 changes: 4 additions & 0 deletions Source/WebCore/inspector/agents/InspectorPageAgent.cpp
Expand Up @@ -235,6 +235,8 @@ Protocol::Page::ResourceType InspectorPageAgent::resourceTypeJSON(InspectorPageA
return Protocol::Page::ResourceType::Beacon;
case WebSocketResource:
return Protocol::Page::ResourceType::WebSocket;
case EventSourceResource:
return Protocol::Page::ResourceType::EventSource;
case OtherResource:
return Protocol::Page::ResourceType::Other;
#if ENABLE(APPLICATION_MANIFEST)
Expand Down Expand Up @@ -286,6 +288,8 @@ InspectorPageAgent::ResourceType InspectorPageAgent::inspectorResourceType(const
return InspectorPageAgent::FetchResource;
case ResourceRequest::Requester::Main:
return InspectorPageAgent::DocumentResource;
case ResourceRequest::Requester::EventSource:
return InspectorPageAgent::EventSourceResource;
default:
return InspectorPageAgent::XHRResource;
}
Expand Down
1 change: 1 addition & 0 deletions Source/WebCore/inspector/agents/InspectorPageAgent.h
Expand Up @@ -72,6 +72,7 @@ class InspectorPageAgent final : public InspectorAgentBase, public Inspector::Pa
#if ENABLE(APPLICATION_MANIFEST)
ApplicationManifestResource,
#endif
EventSourceResource,
OtherResource,
};

Expand Down
1 change: 1 addition & 0 deletions Source/WebCore/page/EventSource.cpp
Expand Up @@ -95,6 +95,7 @@ void EventSource::connect()
ASSERT(!m_requestInFlight);

ResourceRequest request { m_url };
request.setRequester(ResourceRequest::Requester::EventSource);
request.setHTTPMethod("GET"_s);
request.setHTTPHeaderField(HTTPHeaderName::Accept, "text/event-stream"_s);
request.setHTTPHeaderField(HTTPHeaderName::CacheControl, "no-cache"_s);
Expand Down
5 changes: 3 additions & 2 deletions Source/WebCore/platform/network/ResourceRequestBase.h
Expand Up @@ -167,7 +167,7 @@ class ResourceRequestBase {
bool hiddenFromInspector() const { return m_hiddenFromInspector; }
void setHiddenFromInspector(bool hiddenFromInspector) { m_hiddenFromInspector = hiddenFromInspector; }

enum class Requester : uint8_t { Unspecified, Main, XHR, Fetch, Media, Model, ImportScripts, Ping, Beacon };
enum class Requester : uint8_t { Unspecified, Main, XHR, Fetch, Media, Model, ImportScripts, Ping, Beacon, EventSource };
Requester requester() const { return m_requester; }
void setRequester(Requester requester) { m_requester = requester; }

Expand Down Expand Up @@ -432,7 +432,8 @@ template<> struct EnumTraits<WebCore::ResourceRequestBase::Requester> {
WebCore::ResourceRequestBase::Requester::Media,
WebCore::ResourceRequestBase::Requester::ImportScripts,
WebCore::ResourceRequestBase::Requester::Ping,
WebCore::ResourceRequestBase::Requester::Beacon
WebCore::ResourceRequestBase::Requester::Beacon,
WebCore::ResourceRequestBase::Requester::EventSource
>;
};

Expand Down
Expand Up @@ -643,6 +643,10 @@ localizedStrings["Event Breakpoint\u2026"] = "Event Breakpoint\u2026";
localizedStrings["Event Dispatched"] = "Event Dispatched";
localizedStrings["Event Handlers:"] = "Event Handlers:";
localizedStrings["Event Listeners"] = "Event Listeners";
/* Display name for the type of network requests sent via EventSource API (https://developer.mozilla.org/en-US/docs/Web/API/EventSource) */
localizedStrings["EventSource"] = "EventSource";
/* Display name for the type of network requests sent via EventSource(s) API (https://developer.mozilla.org/en-US/docs/Web/API/EventSource) */
localizedStrings["EventSources"] = "EventSources";
localizedStrings["Events"] = "Events";
localizedStrings["Events:"] = "Events:";
localizedStrings["Exception with thrown value: %s"] = "Exception with thrown value: %s";
Expand Down Expand Up @@ -1798,6 +1802,8 @@ localizedStrings["default prevented"] = "default prevented";
/* Shown in the 'Type' column of the Network Table for document resources. */
localizedStrings["document @ Network Tab Resource Type Column Value"] = "document";
localizedStrings["ensuring that common debugging functions are available on every page via the Console"] = "ensuring that common debugging functions are available on every page via the Console";
/* Shown in the 'Type' column of the Network Table for EventSource resources. */
localizedStrings["eventsource @ Network Tab Resource Type Column Value"] = "eventsource";
/* Shown in the 'Type' column of the Network Table for resources loaded via the 'fetch' method. */
localizedStrings["fetch @ Network Tab Resource Type Column Value"] = "fetch";
/* Shown in the 'Type' column of the Network Table for font resources. */
Expand Down
Expand Up @@ -468,6 +468,7 @@ WI.NetworkManager = class NetworkManager extends WI.Object
case WI.Resource.Type.Fetch:
case WI.Resource.Type.Image:
case WI.Resource.Type.Font:
case WI.Resource.Type.EventSource:
case WI.Resource.Type.Other:
break;
case WI.Resource.Type.Ping:
Expand Down
5 changes: 5 additions & 0 deletions Source/WebInspectorUI/UserInterface/Models/Resource.js
Expand Up @@ -172,6 +172,10 @@ WI.Resource = class Resource extends WI.SourceCode
if (plural)
return WI.UIString("Sockets");
return WI.UIString("Socket");
case WI.Resource.Type.EventSource:
if (plural)
return WI.UIString("EventSources", "Display name for the type of network requests sent via EventSource(s) API (https://developer.mozilla.org/en-US/docs/Web/API/EventSource)");
return WI.UIString("EventSource", "Display name for the type of network requests sent via EventSource API (https://developer.mozilla.org/en-US/docs/Web/API/EventSource)");
case WI.Resource.Type.Other:
return WI.UIString("Other");
default:
Expand Down Expand Up @@ -1285,6 +1289,7 @@ WI.Resource.Type = {
Ping: "resource-type-ping",
Beacon: "resource-type-beacon",
WebSocket: "resource-type-websocket",
EventSource: "resource-type-eventsource",
Other: "resource-type-other",
};

Expand Down
Expand Up @@ -224,6 +224,9 @@ WI.NetworkTableContentView = class NetworkTableContentView extends WI.ContentVie
case WI.Resource.Type.WebSocket:
return WI.UIString("socket", "socket @ Network Tab Resource Type Column Value", "Shown in the 'Type' column of the Network Table for WebSocket resources.");

case WI.Resource.Type.EventSource:
return WI.UIString("eventsource", "eventsource @ Network Tab Resource Type Column Value", "Shown in the 'Type' column of the Network Table for resources loaded via the EventSource API.");

case WI.Resource.Type.Other:
return WI.UIString("other", "other @ Network Tab Resource Type Column Value", "Shown in the 'Type' column of the Network Table for resources that don't fall into any of the other known types/categories.");
}
Expand Down

0 comments on commit 01b7967

Please sign in to comment.