diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /devtools/client/netmonitor/src/api.js | |
parent | Initial commit. (diff) | |
download | thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'devtools/client/netmonitor/src/api.js')
-rw-r--r-- | devtools/client/netmonitor/src/api.js | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/devtools/client/netmonitor/src/api.js b/devtools/client/netmonitor/src/api.js new file mode 100644 index 0000000000..8d760de788 --- /dev/null +++ b/devtools/client/netmonitor/src/api.js @@ -0,0 +1,216 @@ +/* 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 EventEmitter = require("resource://devtools/shared/event-emitter.js"); + +const { + bindActionCreators, +} = require("resource://devtools/client/shared/vendor/redux.js"); +const { + Connector, +} = require("resource://devtools/client/netmonitor/src/connector/index.js"); +const { + configureStore, +} = require("resource://devtools/client/netmonitor/src/create-store.js"); +const { + EVENTS, +} = require("resource://devtools/client/netmonitor/src/constants.js"); +const Actions = require("resource://devtools/client/netmonitor/src/actions/index.js"); + +const { + getDisplayedRequestById, + getSortedRequests, +} = require("resource://devtools/client/netmonitor/src/selectors/index.js"); + +/** + * API object for NetMonitor panel (like a facade). This object can be + * consumed by other panels, WebExtension API, etc. + * + * This object doesn't depend on the panel UI and can be created + * and used even if the Network panel UI doesn't exist. + */ +function NetMonitorAPI() { + EventEmitter.decorate(this); + + // Connector to the backend. + this.connector = new Connector(); + + // List of listeners for `devtools.network.onRequestFinished` WebExt API + this._requestFinishedListeners = new Set(); + + // Bind event handlers + this.onPayloadReady = this.onPayloadReady.bind(this); +} + +NetMonitorAPI.prototype = { + async connect(toolbox) { + // Bail out if already connected. + if (this.toolbox) { + return; + } + + this.toolbox = toolbox; + + // Configure store/state object. + this.store = configureStore( + this.connector, + this.toolbox.commands, + this.toolbox.telemetry + ); + this.actions = bindActionCreators(Actions, this.store.dispatch); + + // Register listener for new requests (utilized by WebExtension API). + this.on(EVENTS.PAYLOAD_READY, this.onPayloadReady); + + // Initialize connection to the backend. Pass `this` as the owner, + // so this object can receive all emitted events. + const connection = { + toolbox, + owner: this, + }; + + await this.connector.connect(connection, this.actions, this.store.getState); + }, + + /** + * Clean up (unmount from DOM, remove listeners, disconnect). + */ + destroy() { + this.off(EVENTS.PAYLOAD_READY, this.onPayloadReady); + + this.connector.disconnect(); + + if (this.harExportConnector) { + this.harExportConnector.disconnect(); + } + }, + + // HAR + + /** + * Support for `devtools.network.getHAR` (get collected data as HAR) + */ + async getHar() { + const { + HarExporter, + } = require("resource://devtools/client/netmonitor/src/har/har-exporter.js"); + const state = this.store.getState(); + + const options = { + connector: this.connector, + items: getSortedRequests(state), + }; + + return HarExporter.getHar(options); + }, + + /** + * Support for `devtools.network.onRequestFinished`. A hook for + * every finished HTTP request used by WebExtensions API. + */ + async onPayloadReady(resource) { + if (!this._requestFinishedListeners.size) { + return; + } + + const { + HarExporter, + } = require("resource://devtools/client/netmonitor/src/har/har-exporter.js"); + + const connector = await this.getHarExportConnector(); + const request = getDisplayedRequestById( + this.store.getState(), + resource.actor + ); + if (!request) { + console.error("HAR: request not found " + resource.actor); + return; + } + + const options = { + connector, + includeResponseBodies: false, + items: [request], + }; + + const har = await HarExporter.getHar(options); + + // There is page so remove the page reference. + const harEntry = har.log.entries[0]; + delete harEntry.pageref; + + this._requestFinishedListeners.forEach(listener => + listener({ + harEntry, + requestId: resource.actor, + }) + ); + }, + + /** + * Support for `Request.getContent` WebExt API (lazy loading response body) + */ + async fetchResponseContent(requestId) { + return this.connector.requestData(requestId, "responseContent"); + }, + + /** + * Add listener for `onRequestFinished` events. + * + * @param {Object} listener + * The listener to be called it's expected to be + * a function that takes ({harEntry, requestId}) + * as first argument. + */ + addRequestFinishedListener(listener) { + this._requestFinishedListeners.add(listener); + }, + + removeRequestFinishedListener(listener) { + this._requestFinishedListeners.delete(listener); + }, + + hasRequestFinishedListeners() { + return this._requestFinishedListeners.size > 0; + }, + + /** + * Separate connector for HAR export. + */ + async getHarExportConnector() { + if (this.harExportConnector) { + // Wait for the connector to be ready to avoid exceptions if this method is called + // twice during its initialization. + await this.harExportConnectorReady; + return this.harExportConnector; + } + + const connection = { + toolbox: this.toolbox, + }; + + this.harExportConnector = new Connector(); + this.harExportConnectorReady = this.harExportConnector.connect(connection); + + await this.harExportConnectorReady; + return this.harExportConnector; + }, + + /** + * Resends a given network request + * @param {String} requestId + * Id of the network request + */ + resendRequest(requestId) { + // Flush queued requests. + this.store.dispatch(Actions.batchFlush()); + // Send custom request with same url, headers and body as the request + // with the given requestId. + this.store.dispatch(Actions.sendCustomRequest(requestId)); + }, +}; + +exports.NetMonitorAPI = NetMonitorAPI; |