Bug 1637920 - [devtools] Legacy listeners support for SSE events r=ochameau

Differential Revision: https://phabricator.services.mozilla.com/D102585
This commit is contained in:
Hubert Boma Manilla 2021-01-27 13:37:25 +00:00
Родитель 169f4272fc
Коммит 15a8aa84e8
9 изменённых файлов: 177 добавлений и 36 удалений

Просмотреть файл

@ -154,11 +154,8 @@ class FirefoxConnector {
resourceWatcher: this.toolbox.resourceWatcher,
});
// Register target listeners if we switched to a new top level one
if (isTargetSwitching) {
await this.addTargetListeners();
} else {
// Otherwise, this is the first top level target, so register all the listeners
// If this is the first top level target, lets register all the listeners
if (!isTargetSwitching) {
await this.addListeners();
}
@ -229,6 +226,21 @@ class FirefoxConnector {
break;
}
}
continue;
}
if (resource.resourceType === TYPES.SERVER_SENT_EVENT) {
const { messageType, httpChannelId, data } = resource;
switch (messageType) {
case "eventSourceConnectionClosed": {
this.dataProvider.onEventSourceConnectionClosed(httpChannelId);
break;
}
case "eventReceived": {
this.dataProvider.onEventReceived(httpChannelId, data);
break;
}
}
}
}
}
@ -254,31 +266,21 @@ class FirefoxConnector {
targetResources.push(this.toolbox.resourceWatcher.TYPES.WEBSOCKET);
}
await this.toolbox.resourceWatcher.watchResources(targetResources, {
onAvailable: this.onResourceAvailable,
onUpdated: this.onResourceUpdated,
ignoreExistingResources,
});
await this.addTargetListeners();
}
async addTargetListeners() {
// Support for EventSource monitoring is currently hidden behind this pref.
if (
Services.prefs.getBoolPref(
"devtools.netmonitor.features.serverSentEvents"
)
) {
const eventSourceFront = await this.currentTarget.getFront("eventSource");
eventSourceFront.startListening();
eventSourceFront.on(
"eventSourceConnectionClosed",
this.dataProvider.onEventSourceConnectionClosed
targetResources.push(
this.toolbox.resourceWatcher.TYPES.SERVER_SENT_EVENT
);
eventSourceFront.on("eventReceived", this.dataProvider.onEventReceived);
}
await this.toolbox.resourceWatcher.watchResources(targetResources, {
onAvailable: this.onResourceAvailable,
onUpdated: this.onResourceUpdated,
ignoreExistingResources,
});
}
removeListeners() {
@ -287,21 +289,13 @@ class FirefoxConnector {
this.toolbox.resourceWatcher.TYPES.NETWORK_EVENT,
this.toolbox.resourceWatcher.TYPES.NETWORK_EVENT_STACKTRACE,
this.toolbox.resourceWatcher.TYPES.WEBSOCKET,
this.toolbox.resourceWatcher.TYPES.SERVER_SENT_EVENT,
],
{
onAvailable: this.onResourceAvailable,
onUpdated: this.onResourceUpdated,
}
);
const eventSourceFront = this.currentTarget.getCachedFront("eventSource");
if (eventSourceFront) {
eventSourceFront.off(
"eventSourceConnectionClosed",
this.dataProvider.onEventSourceConnectionClosed
);
eventSourceFront.off("eventReceived", this.dataProvider.onEventReceived);
}
}
enableActions(enable) {

Просмотреть файл

@ -1,6 +1,6 @@
function handleRequest(request, response) {
response.processAsync();
response.setHeader("Content-Type", "text/event-stream");
response.write("data: Why so serious?\n\n");
response.finish();
response.processAsync();
response.setHeader("Content-Type", "text/event-stream");
response.write("data: Why so serious?\n\n");
response.finish();
}

Просмотреть файл

@ -17,6 +17,7 @@ DevToolsModules(
"network-events.js",
"platform-messages.js",
"root-node.js",
"server-sent-events.js",
"session-storage.js",
"source.js",
"storage-utils.js",

Просмотреть файл

@ -0,0 +1,34 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const {
ResourceWatcher,
} = require("devtools/shared/resources/resource-watcher");
module.exports = async function({ targetFront, onAvailable }) {
const eventSourceFront = await targetFront.getFront("eventSource");
eventSourceFront.startListening();
eventSourceFront.on("eventSourceConnectionClosed", httpChannelId => {
const resource = createResource("eventSourceConnectionClosed", {
httpChannelId,
});
onAvailable([resource]);
});
eventSourceFront.on("eventReceived", (httpChannelId, data) => {
const resource = createResource("eventReceived", { httpChannelId, data });
onAvailable([resource]);
});
};
function createResource(messageType, eventParams) {
return {
resourceType: ResourceWatcher.TYPES.SERVER_SENT_EVENT,
messageType,
...eventParams,
};
}

Просмотреть файл

@ -848,6 +848,7 @@ ResourceWatcher.TYPES = ResourceWatcher.prototype.TYPES = {
NETWORK_EVENT_STACKTRACE: "network-event-stacktrace",
SOURCE: "source",
BREAKPOINT: "breakpoint",
SERVER_SENT_EVENT: "server-sent-event",
};
module.exports = { ResourceWatcher, TYPES: ResourceWatcher.TYPES };
@ -908,6 +909,8 @@ const LegacyListeners = {
.SOURCE]: require("devtools/shared/resources/legacy-listeners/source"),
[ResourceWatcher.TYPES
.BREAKPOINT]: require("devtools/shared/resources/legacy-listeners/breakpoint"),
[ResourceWatcher.TYPES
.SERVER_SENT_EVENT]: require("devtools/shared/resources/legacy-listeners/server-sent-events"),
};
// Optional transformers for each type of resource.

Просмотреть файл

@ -14,6 +14,8 @@ support-files =
service-worker-sources.js
sources.html
sources.js
sse_backend.sjs
sse_frontend.html
style_document.css
style_document.html
style_iframe.css
@ -40,6 +42,7 @@ support-files =
[browser_resources_network_events.js]
[browser_resources_platform_messages.js]
[browser_resources_root_node.js]
[browser_resources_server_sent_events.js]
[browser_resources_several_resources.js]
[browser_resources_sources.js]
[browser_resources_stylesheets.js]

Просмотреть файл

@ -0,0 +1,70 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test the ResourceWatcher API around SERVER SENT EVENTS.
const {
ResourceWatcher,
} = require("devtools/shared/resources/resource-watcher");
add_task(async function() {
const tab = await addTab(URL_ROOT + "sse_frontend.html");
const { client, resourceWatcher, targetList } = await initResourceWatcher(
tab
);
info("Check available resources");
const availableResources = [];
await resourceWatcher.watchResources(
[ResourceWatcher.TYPES.SERVER_SENT_EVENT],
{
onAvailable: resources => availableResources.push(...resources),
}
);
info("Check resource of opening websocket");
await ContentTask.spawn(tab.linkedBrowser, [], async () => {
await content.wrappedJSObject.openConnection();
});
// We expect only 2 resources
await waitUntil(() => availableResources.length === 2);
// To make sure the channel id are the same
const httpChannelId = availableResources[0].httpChannelId;
ok(httpChannelId, "The channel id is set");
is(typeof httpChannelId, "number", "The channel id is a number");
assertResource(availableResources[0], {
messageType: "eventReceived",
httpChannelId,
data: {
payload: "Why so serious?",
eventName: "message",
lastEventId: "",
retry: 5000,
},
});
assertResource(availableResources[1], {
messageType: "eventSourceConnectionClosed",
httpChannelId,
});
await targetList.destroy();
await client.close();
});
function assertResource(resource, expected) {
is(
resource.resourceType,
ResourceWatcher.TYPES.SERVER_SENT_EVENT,
"Resource type is correct"
);
checkObject(resource, expected);
}

Просмотреть файл

@ -0,0 +1,6 @@
function handleRequest(request, response) {
response.processAsync();
response.setHeader("Content-Type", "text/event-stream");
response.write("data: Why so serious?\n\n");
response.finish();
}

Просмотреть файл

@ -0,0 +1,30 @@
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<!doctype HTML>
<html>
<head>
<meta charset="utf-8"/>
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<title>SSE Inspection Test Page</title>
</head>
<body>
<h1>SSE Inspection Test Page</h1>
<script type="text/javascript">
/* exported openConnection */
"use strict";
function openConnection() {
return new Promise(resolve => {
const es = new EventSource("sse_backend.sjs");
es.onmessage = function (e) {
es.close();
resolve();
};
});
}
</script>
</body>
</html>