forked from mirrors/gecko-dev
Bug 1637920 - [devtools] Legacy listeners support for SSE events r=ochameau
Differential Revision: https://phabricator.services.mozilla.com/D102585
This commit is contained in:
parent
169f4272fc
commit
15a8aa84e8
9 changed files with 177 additions and 36 deletions
|
|
@ -154,11 +154,8 @@ class FirefoxConnector {
|
||||||
resourceWatcher: this.toolbox.resourceWatcher,
|
resourceWatcher: this.toolbox.resourceWatcher,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Register target listeners if we switched to a new top level one
|
// If this is the first top level target, lets register all the listeners
|
||||||
if (isTargetSwitching) {
|
if (!isTargetSwitching) {
|
||||||
await this.addTargetListeners();
|
|
||||||
} else {
|
|
||||||
// Otherwise, this is the first top level target, so register all the listeners
|
|
||||||
await this.addListeners();
|
await this.addListeners();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -229,6 +226,21 @@ class FirefoxConnector {
|
||||||
break;
|
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);
|
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 (
|
if (
|
||||||
Services.prefs.getBoolPref(
|
Services.prefs.getBoolPref(
|
||||||
"devtools.netmonitor.features.serverSentEvents"
|
"devtools.netmonitor.features.serverSentEvents"
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
const eventSourceFront = await this.currentTarget.getFront("eventSource");
|
targetResources.push(
|
||||||
eventSourceFront.startListening();
|
this.toolbox.resourceWatcher.TYPES.SERVER_SENT_EVENT
|
||||||
|
|
||||||
eventSourceFront.on(
|
|
||||||
"eventSourceConnectionClosed",
|
|
||||||
this.dataProvider.onEventSourceConnectionClosed
|
|
||||||
);
|
);
|
||||||
eventSourceFront.on("eventReceived", this.dataProvider.onEventReceived);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await this.toolbox.resourceWatcher.watchResources(targetResources, {
|
||||||
|
onAvailable: this.onResourceAvailable,
|
||||||
|
onUpdated: this.onResourceUpdated,
|
||||||
|
ignoreExistingResources,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
removeListeners() {
|
removeListeners() {
|
||||||
|
|
@ -287,21 +289,13 @@ class FirefoxConnector {
|
||||||
this.toolbox.resourceWatcher.TYPES.NETWORK_EVENT,
|
this.toolbox.resourceWatcher.TYPES.NETWORK_EVENT,
|
||||||
this.toolbox.resourceWatcher.TYPES.NETWORK_EVENT_STACKTRACE,
|
this.toolbox.resourceWatcher.TYPES.NETWORK_EVENT_STACKTRACE,
|
||||||
this.toolbox.resourceWatcher.TYPES.WEBSOCKET,
|
this.toolbox.resourceWatcher.TYPES.WEBSOCKET,
|
||||||
|
this.toolbox.resourceWatcher.TYPES.SERVER_SENT_EVENT,
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
onAvailable: this.onResourceAvailable,
|
onAvailable: this.onResourceAvailable,
|
||||||
onUpdated: this.onResourceUpdated,
|
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) {
|
enableActions(enable) {
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ DevToolsModules(
|
||||||
"network-events.js",
|
"network-events.js",
|
||||||
"platform-messages.js",
|
"platform-messages.js",
|
||||||
"root-node.js",
|
"root-node.js",
|
||||||
|
"server-sent-events.js",
|
||||||
"session-storage.js",
|
"session-storage.js",
|
||||||
"source.js",
|
"source.js",
|
||||||
"storage-utils.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",
|
NETWORK_EVENT_STACKTRACE: "network-event-stacktrace",
|
||||||
SOURCE: "source",
|
SOURCE: "source",
|
||||||
BREAKPOINT: "breakpoint",
|
BREAKPOINT: "breakpoint",
|
||||||
|
SERVER_SENT_EVENT: "server-sent-event",
|
||||||
};
|
};
|
||||||
module.exports = { ResourceWatcher, TYPES: ResourceWatcher.TYPES };
|
module.exports = { ResourceWatcher, TYPES: ResourceWatcher.TYPES };
|
||||||
|
|
||||||
|
|
@ -908,6 +909,8 @@ const LegacyListeners = {
|
||||||
.SOURCE]: require("devtools/shared/resources/legacy-listeners/source"),
|
.SOURCE]: require("devtools/shared/resources/legacy-listeners/source"),
|
||||||
[ResourceWatcher.TYPES
|
[ResourceWatcher.TYPES
|
||||||
.BREAKPOINT]: require("devtools/shared/resources/legacy-listeners/breakpoint"),
|
.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.
|
// Optional transformers for each type of resource.
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@ support-files =
|
||||||
service-worker-sources.js
|
service-worker-sources.js
|
||||||
sources.html
|
sources.html
|
||||||
sources.js
|
sources.js
|
||||||
|
sse_backend.sjs
|
||||||
|
sse_frontend.html
|
||||||
style_document.css
|
style_document.css
|
||||||
style_document.html
|
style_document.html
|
||||||
style_iframe.css
|
style_iframe.css
|
||||||
|
|
@ -40,6 +42,7 @@ support-files =
|
||||||
[browser_resources_network_events.js]
|
[browser_resources_network_events.js]
|
||||||
[browser_resources_platform_messages.js]
|
[browser_resources_platform_messages.js]
|
||||||
[browser_resources_root_node.js]
|
[browser_resources_root_node.js]
|
||||||
|
[browser_resources_server_sent_events.js]
|
||||||
[browser_resources_several_resources.js]
|
[browser_resources_several_resources.js]
|
||||||
[browser_resources_sources.js]
|
[browser_resources_sources.js]
|
||||||
[browser_resources_stylesheets.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);
|
||||||
|
}
|
||||||
6
devtools/shared/resources/tests/sse_backend.sjs
Normal file
6
devtools/shared/resources/tests/sse_backend.sjs
Normal file
|
|
@ -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();
|
||||||
|
}
|
||||||
30
devtools/shared/resources/tests/sse_frontend.html
Normal file
30
devtools/shared/resources/tests/sse_frontend.html
Normal file
|
|
@ -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>
|
||||||
Loading…
Reference in a new issue