mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-25 11:15:34 +00:00
Backed out 3 changesets (bug 1436665) for talos damp failures on netmonitor/simple.js. CLOSED TREE
Backed out changeset 09030f59fbea (bug 1436665) Backed out changeset 513c72b05382 (bug 1436665) Backed out changeset 4b8fe40857db (bug 1436665)
This commit is contained in:
parent
bd6343c26c
commit
c1f14b1d28
@ -76,11 +76,15 @@ function devtools_page() {
|
||||
|
||||
browser.devtools.network.onRequestFinished.removeListener(requestFinishedListener);
|
||||
};
|
||||
browser.devtools.network.onRequestFinished.addListener(requestFinishedListener);
|
||||
}
|
||||
|
||||
browser.test.onMessage.addListener(msg => {
|
||||
if (msg === "addOnRequestFinishedListener") {
|
||||
browser.devtools.network.onRequestFinished.addListener(requestFinishedListener);
|
||||
}
|
||||
function waitForRequestAdded(toolbox) {
|
||||
return new Promise(resolve => {
|
||||
let netPanel = toolbox.getPanel("netmonitor");
|
||||
netPanel.panelWin.once("NetMonitor:RequestAdded", () => {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -104,26 +108,6 @@ let extData = {
|
||||
},
|
||||
};
|
||||
|
||||
function waitForRequestAdded(toolbox) {
|
||||
return new Promise(async resolve => {
|
||||
let netPanel = await toolbox.getNetMonitorAPI();
|
||||
netPanel.once("NetMonitor:RequestAdded", () => {
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function navigateToolboxTarget(extension, toolbox) {
|
||||
extension.sendMessage("navigate");
|
||||
|
||||
// Wait till the navigation is complete.
|
||||
await Promise.all([
|
||||
extension.awaitMessage("tabUpdated"),
|
||||
extension.awaitMessage("onNavigatedFired"),
|
||||
waitForRequestAdded(toolbox),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for `chrome.devtools.network.onNavigate()` API
|
||||
*/
|
||||
@ -178,14 +162,35 @@ add_task(async function test_devtools_network_get_har() {
|
||||
let toolbox = await gDevTools.showToolbox(target, "webconsole");
|
||||
info("Developer toolbox opened.");
|
||||
|
||||
// Get HAR, it should be empty since no data collected yet.
|
||||
// Get HAR, it should be empty since the Net panel wasn't selected.
|
||||
const getHAREmptyPromise = extension.awaitMessage("getHAR-result");
|
||||
extension.sendMessage("getHAR");
|
||||
const getHAREmptyResult = await getHAREmptyPromise;
|
||||
is(getHAREmptyResult.entries.length, 0, "HAR log should be empty");
|
||||
|
||||
// Select the Net panel.
|
||||
await toolbox.selectTool("netmonitor");
|
||||
|
||||
// Get HAR again, it should be empty because the Panel is selected
|
||||
// but no data collected yet.
|
||||
const getHAREmptyPromiseWithPanel = extension.awaitMessage("getHAR-result");
|
||||
extension.sendMessage("getHAR");
|
||||
const emptyResultWithPanel = await getHAREmptyPromiseWithPanel;
|
||||
is(emptyResultWithPanel.entries.length, 0, "HAR log should be empty");
|
||||
|
||||
// Reload the page to collect some HTTP requests.
|
||||
await navigateToolboxTarget(extension, toolbox);
|
||||
extension.sendMessage("navigate");
|
||||
|
||||
// Wait till the navigation is complete and request
|
||||
// added into the net panel.
|
||||
await Promise.all([
|
||||
extension.awaitMessage("tabUpdated"),
|
||||
extension.awaitMessage("onNavigatedFired"),
|
||||
extension.awaitMessage("onRequestFinished"),
|
||||
extension.awaitMessage("onRequestFinished-callbackExecuted"),
|
||||
extension.awaitMessage("onRequestFinished-promiseResolved"),
|
||||
waitForRequestAdded(toolbox),
|
||||
]);
|
||||
|
||||
// Get HAR, it should not be empty now.
|
||||
const getHARPromise = extension.awaitMessage("getHAR-result");
|
||||
@ -193,17 +198,6 @@ add_task(async function test_devtools_network_get_har() {
|
||||
const getHARResult = await getHARPromise;
|
||||
is(getHARResult.entries.length, 1, "HAR log should not be empty");
|
||||
|
||||
// Select the Net panel and reload page again.
|
||||
await toolbox.selectTool("netmonitor");
|
||||
await navigateToolboxTarget(extension, toolbox);
|
||||
|
||||
// Get HAR again, it should not be empty even if
|
||||
// the Network panel is selected now.
|
||||
const getHAREmptyPromiseWithPanel = extension.awaitMessage("getHAR-result");
|
||||
extension.sendMessage("getHAR");
|
||||
const emptyResultWithPanel = await getHAREmptyPromiseWithPanel;
|
||||
is(emptyResultWithPanel.entries.length, 1, "HAR log should not be empty");
|
||||
|
||||
// Shutdown
|
||||
await gDevTools.closeToolbox(target);
|
||||
|
||||
@ -223,23 +217,25 @@ add_task(async function test_devtools_network_on_request_finished() {
|
||||
|
||||
await extension.startup();
|
||||
await extension.awaitMessage("ready");
|
||||
|
||||
let target = gDevTools.getTargetForTab(tab);
|
||||
|
||||
// Open the Toolbox
|
||||
let toolbox = await gDevTools.showToolbox(target, "webconsole");
|
||||
let toolbox = await gDevTools.showToolbox(target, "netmonitor");
|
||||
info("Developer toolbox opened.");
|
||||
|
||||
// Wait the extension to subscribe the onRequestFinished listener.
|
||||
await extension.sendMessage("addOnRequestFinishedListener");
|
||||
// Reload and wait for onRequestFinished event.
|
||||
extension.sendMessage("navigate");
|
||||
|
||||
// Reload the page
|
||||
await navigateToolboxTarget(extension, toolbox);
|
||||
await Promise.all([
|
||||
extension.awaitMessage("tabUpdated"),
|
||||
extension.awaitMessage("onNavigatedFired"),
|
||||
waitForRequestAdded(toolbox),
|
||||
]);
|
||||
|
||||
info("Wait for an onRequestFinished event");
|
||||
await extension.awaitMessage("onRequestFinished");
|
||||
|
||||
// Wait for response content being fetched.
|
||||
info("Wait for request.getBody results");
|
||||
let [callbackRes, promiseRes] = await Promise.all([
|
||||
extension.awaitMessage("onRequestFinished-callbackExecuted"),
|
||||
extension.awaitMessage("onRequestFinished-promiseResolved"),
|
||||
@ -249,6 +245,7 @@ add_task(async function test_devtools_network_on_request_finished() {
|
||||
"The expected content has been retrieved.");
|
||||
is(callbackRes[1], "text/html; charset=utf-8",
|
||||
"The expected content has been retrieved.");
|
||||
|
||||
is(promiseRes[0], callbackRes[0],
|
||||
"The resolved value is equal to the one received in the callback API mode");
|
||||
is(promiseRes[1], callbackRes[1],
|
||||
|
@ -74,8 +74,6 @@ loader.lazyRequireGetter(this, "buildHarLog",
|
||||
"devtools/client/netmonitor/src/har/har-builder-utils", true);
|
||||
loader.lazyRequireGetter(this, "getKnownDeviceFront",
|
||||
"devtools/shared/fronts/device", true);
|
||||
loader.lazyRequireGetter(this, "NetMonitorAPI",
|
||||
"devtools/client/netmonitor/src/api", true);
|
||||
|
||||
loader.lazyGetter(this, "domNodeConstants", () => {
|
||||
return require("devtools/shared/dom-node-constants");
|
||||
@ -118,12 +116,14 @@ function Toolbox(target, selectedTool, hostType, contentWindow, frameId) {
|
||||
this._initInspector = null;
|
||||
this._inspector = null;
|
||||
this._styleSheets = null;
|
||||
this._netMonitorAPI = null;
|
||||
|
||||
// Map of frames (id => frame-info) and currently selected frame id.
|
||||
this.frameMap = new Map();
|
||||
this.selectedFrameId = null;
|
||||
|
||||
// List of listeners for `devtools.network.onRequestFinished` WebExt API
|
||||
this._requestFinishedListeners = new Set();
|
||||
|
||||
this._toolRegistered = this._toolRegistered.bind(this);
|
||||
this._toolUnregistered = this._toolUnregistered.bind(this);
|
||||
this._onWillNavigate = this._onWillNavigate.bind(this);
|
||||
@ -2687,6 +2687,7 @@ Toolbox.prototype = {
|
||||
this._sourceMapURLService.destroy();
|
||||
this._sourceMapURLService = null;
|
||||
}
|
||||
|
||||
if (this._sourceMapService) {
|
||||
this._sourceMapService.stopSourceMapWorker();
|
||||
this._sourceMapService = null;
|
||||
@ -2784,11 +2785,6 @@ Toolbox.prototype = {
|
||||
// target.
|
||||
deferred.resolve(settleAll(outstanding)
|
||||
.catch(console.error)
|
||||
.then(() => {
|
||||
let api = this._netMonitorAPI;
|
||||
this._netMonitorAPI = null;
|
||||
return api ? api.destroy() : null;
|
||||
}, console.error)
|
||||
.then(() => {
|
||||
this._removeHostListeners();
|
||||
|
||||
@ -3048,39 +3044,22 @@ Toolbox.prototype = {
|
||||
|
||||
// Support for WebExtensions API (`devtools.network.*`)
|
||||
|
||||
/**
|
||||
* Return Netmonitor API object. This object offers Network monitor
|
||||
* public API that can be consumed by other panels or WE API.
|
||||
*/
|
||||
getNetMonitorAPI: async function() {
|
||||
let netPanel = this.getPanel("netmonitor");
|
||||
|
||||
// Return Net panel if it exists.
|
||||
if (netPanel) {
|
||||
return netPanel.panelWin.Netmonitor.api;
|
||||
}
|
||||
|
||||
if (this._netMonitorAPI) {
|
||||
return this._netMonitorAPI;
|
||||
}
|
||||
|
||||
// Create and initialize Network monitor API object.
|
||||
// This object is only connected to the backend - not to the UI.
|
||||
this._netMonitorAPI = new NetMonitorAPI();
|
||||
await this._netMonitorAPI.connect(this);
|
||||
|
||||
return this._netMonitorAPI;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns data (HAR) collected by the Network panel.
|
||||
*/
|
||||
getHARFromNetMonitor: async function() {
|
||||
let netMonitor = await this.getNetMonitorAPI();
|
||||
let har = await netMonitor.getHar();
|
||||
let netPanel = this.getPanel("netmonitor");
|
||||
|
||||
// Return default empty HAR file if needed.
|
||||
har = har || buildHarLog(Services.appinfo);
|
||||
// The panel doesn't have to exist (it must be selected
|
||||
// by the user at least once to be created).
|
||||
// Return default empty HAR log in such case.
|
||||
if (!netPanel) {
|
||||
let har = await buildHarLog(Services.appinfo);
|
||||
return har.log;
|
||||
}
|
||||
|
||||
// Use Netmonitor object to get the current HAR log.
|
||||
let har = await netPanel.panelWin.Netmonitor.getHar();
|
||||
|
||||
// Return the log directly to be compatible with
|
||||
// Chrome WebExtension API.
|
||||
@ -3095,26 +3074,24 @@ Toolbox.prototype = {
|
||||
* a function that takes ({harEntry, requestId})
|
||||
* as first argument.
|
||||
*/
|
||||
addRequestFinishedListener: async function(listener) {
|
||||
let netMonitor = await this.getNetMonitorAPI();
|
||||
netMonitor.addRequestFinishedListener(listener);
|
||||
addRequestFinishedListener: function(listener) {
|
||||
// Log console message informing the extension developer
|
||||
// that the Network panel needs to be selected at least
|
||||
// once in order to receive `onRequestFinished` events.
|
||||
let message = "The Network panel needs to be selected at least" +
|
||||
" once in order to receive 'onRequestFinished' events.";
|
||||
this.target.logWarningInPage(message, "har");
|
||||
|
||||
// Add the listener into internal list.
|
||||
this._requestFinishedListeners.add(listener);
|
||||
},
|
||||
|
||||
removeRequestFinishedListener: async function(listener) {
|
||||
let netMonitor = await this.getNetMonitorAPI();
|
||||
netMonitor.removeRequestFinishedListener(listener);
|
||||
removeRequestFinishedListener: function(listener) {
|
||||
this._requestFinishedListeners.delete(listener);
|
||||
},
|
||||
|
||||
// Destroy Network monitor API object if the following is true:
|
||||
// 1) there is no listener
|
||||
// 2) the Net panel doesn't exist/use the API object (if the panel
|
||||
// exists it's also responsible for destroying it,
|
||||
// see `NetMonitorPanel.open` for more details)
|
||||
let netPanel = this.getPanel("netmonitor");
|
||||
let hasListeners = netMonitor.hasRequestFinishedListeners();
|
||||
if (this._netMonitorAPI && !hasListeners && !netPanel) {
|
||||
this._netMonitorAPI.destroy();
|
||||
this._netMonitorAPI = null;
|
||||
}
|
||||
getRequestFinishedListeners: function() {
|
||||
return this._requestFinishedListeners;
|
||||
},
|
||||
|
||||
/**
|
||||
@ -3125,9 +3102,17 @@ Toolbox.prototype = {
|
||||
* Id of the request for which the response content
|
||||
* should be fetched.
|
||||
*/
|
||||
fetchResponseContent: async function(requestId) {
|
||||
let netMonitor = await this.getNetMonitorAPI();
|
||||
return netMonitor.fetchResponseContent(requestId);
|
||||
fetchResponseContent: function(requestId) {
|
||||
let netPanel = this.getPanel("netmonitor");
|
||||
|
||||
// The panel doesn't have to exist (it must be selected
|
||||
// by the user at least once to be created).
|
||||
// Return undefined content in such case.
|
||||
if (!netPanel) {
|
||||
return Promise.resolve({content: {}});
|
||||
}
|
||||
|
||||
return netPanel.panelWin.Netmonitor.fetchResponseContent(requestId);
|
||||
},
|
||||
|
||||
// Support management of installed WebExtensions that provide a devtools_page.
|
||||
|
@ -1,7 +1,6 @@
|
||||
/* 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/. */
|
||||
/* exported initialize */
|
||||
|
||||
"use strict";
|
||||
|
||||
@ -17,52 +16,185 @@ const require = window.windowRequire = BrowserLoader({
|
||||
window,
|
||||
}).require;
|
||||
|
||||
const { NetMonitorAPI } = require("./src/api");
|
||||
const { NetMonitorApp } = require("./src/app");
|
||||
const EventEmitter = require("devtools/shared/event-emitter");
|
||||
const { createFactory } = require("devtools/client/shared/vendor/react");
|
||||
const { render, unmountComponentAtNode } = require("devtools/client/shared/vendor/react-dom");
|
||||
const Provider = createFactory(require("devtools/client/shared/vendor/react-redux").Provider);
|
||||
const { bindActionCreators } = require("devtools/client/shared/vendor/redux");
|
||||
const { Connector } = require("./src/connector/index");
|
||||
const { configureStore } = require("./src/create-store");
|
||||
const App = createFactory(require("./src/components/App"));
|
||||
const { EVENTS } = require("./src/constants");
|
||||
const {
|
||||
getDisplayedRequestById,
|
||||
getSortedRequests
|
||||
} = require("./src/selectors/index");
|
||||
|
||||
// Inject EventEmitter into global window.
|
||||
EventEmitter.decorate(window);
|
||||
|
||||
/**
|
||||
* This is the initialization point for the Network monitor.
|
||||
*
|
||||
* @param {Object} api Allows reusing existing API object.
|
||||
*/
|
||||
function initialize(api) {
|
||||
const app = new NetMonitorApp(api);
|
||||
// Configure store/state object.
|
||||
let connector = new Connector();
|
||||
const store = configureStore(connector);
|
||||
const actions = bindActionCreators(require("./src/actions/index"), store.dispatch);
|
||||
|
||||
// Inject to global window for testing
|
||||
window.Netmonitor = app;
|
||||
window.api = api;
|
||||
window.store = app.api.store;
|
||||
window.connector = app.api.connector;
|
||||
window.actions = app.api.actions;
|
||||
|
||||
return app;
|
||||
}
|
||||
// Inject to global window for testing
|
||||
window.store = store;
|
||||
window.connector = connector;
|
||||
window.actions = actions;
|
||||
|
||||
/**
|
||||
* The following code is used to open Network monitor in a tab.
|
||||
* Like the Launchpad, but without Launchpad.
|
||||
*
|
||||
* For example:
|
||||
* chrome://devtools/content/netmonitor/index.html?type=process
|
||||
* loads the netmonitor for the parent process, exactly like the
|
||||
* one in the browser toolbox
|
||||
*
|
||||
* It's also possible to connect to a tab.
|
||||
* 1) go in about:debugging
|
||||
* 2) In menu Tabs, click on a Debug button for particular tab
|
||||
*
|
||||
* This will open an about:devtools-toolbox url, from which you can
|
||||
* take type and id query parameters and reuse them for the chrome url
|
||||
* of the netmonitor
|
||||
*
|
||||
* chrome://devtools/content/netmonitor/index.html?type=tab&id=1234 URLs
|
||||
* where 1234 is the tab id, you can retrieve from about:debugging#tabs links.
|
||||
* Simply copy the id from about:devtools-toolbox?type=tab&id=1234 URLs.
|
||||
* Global Netmonitor object in this panel. This object can be consumed
|
||||
* by other panels (e.g. Console is using inspectRequest), by the
|
||||
* Launchpad (bootstrap), WebExtension API (getHAR), etc.
|
||||
*/
|
||||
window.Netmonitor = {
|
||||
bootstrap({ toolbox, panel }) {
|
||||
this.mount = document.querySelector("#mount");
|
||||
this.toolbox = toolbox;
|
||||
|
||||
const connection = {
|
||||
tabConnection: {
|
||||
tabTarget: toolbox.target,
|
||||
},
|
||||
toolbox,
|
||||
panel,
|
||||
};
|
||||
|
||||
const openLink = (link) => {
|
||||
let parentDoc = toolbox.doc;
|
||||
let iframe = parentDoc.getElementById("toolbox-panel-iframe-netmonitor");
|
||||
let top = iframe.ownerDocument.defaultView.top;
|
||||
top.openWebLinkIn(link, "tab");
|
||||
};
|
||||
|
||||
const openSplitConsole = (err) => {
|
||||
toolbox.openSplitConsole().then(() => {
|
||||
toolbox.target.logErrorInPage(err, "har");
|
||||
});
|
||||
};
|
||||
|
||||
this.onRequestAdded = this.onRequestAdded.bind(this);
|
||||
window.on(EVENTS.REQUEST_ADDED, this.onRequestAdded);
|
||||
|
||||
// Render the root Application component.
|
||||
const sourceMapService = toolbox.sourceMapURLService;
|
||||
const app = App({
|
||||
actions,
|
||||
connector,
|
||||
openLink,
|
||||
openSplitConsole,
|
||||
sourceMapService
|
||||
});
|
||||
render(Provider({ store }, app), this.mount);
|
||||
|
||||
// Connect to the Firefox backend by default.
|
||||
return connector.connectFirefox(connection, actions, store.getState);
|
||||
},
|
||||
|
||||
destroy() {
|
||||
unmountComponentAtNode(this.mount);
|
||||
window.off(EVENTS.REQUEST_ADDED, this.onRequestAdded);
|
||||
return connector.disconnect();
|
||||
},
|
||||
|
||||
// Support for WebExtensions API
|
||||
|
||||
/**
|
||||
* Support for `devtools.network.getHAR` (get collected data as HAR)
|
||||
*/
|
||||
getHar() {
|
||||
let { HarExporter } = require("devtools/client/netmonitor/src/har/har-exporter");
|
||||
let state = store.getState();
|
||||
|
||||
let options = {
|
||||
connector,
|
||||
items: getSortedRequests(state),
|
||||
// Always generate HAR log even if there are no requests.
|
||||
forceExport: true,
|
||||
};
|
||||
|
||||
return HarExporter.getHar(options);
|
||||
},
|
||||
|
||||
/**
|
||||
* Support for `devtools.network.onRequestFinished`. A hook for
|
||||
* every finished HTTP request used by WebExtensions API.
|
||||
*/
|
||||
onRequestAdded(requestId) {
|
||||
let listeners = this.toolbox.getRequestFinishedListeners();
|
||||
if (!listeners.size) {
|
||||
return;
|
||||
}
|
||||
|
||||
let { HarExporter } = require("devtools/client/netmonitor/src/har/har-exporter");
|
||||
let options = {
|
||||
connector,
|
||||
includeResponseBodies: false,
|
||||
items: [getDisplayedRequestById(store.getState(), requestId)],
|
||||
};
|
||||
|
||||
// Build HAR for specified request only.
|
||||
HarExporter.getHar(options).then(har => {
|
||||
let harEntry = har.log.entries[0];
|
||||
delete harEntry.pageref;
|
||||
listeners.forEach(listener => listener({
|
||||
harEntry,
|
||||
requestId,
|
||||
}));
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Support for `Request.getContent` WebExt API (lazy loading response body)
|
||||
*/
|
||||
fetchResponseContent(requestId) {
|
||||
return connector.requestData(requestId, "responseContent");
|
||||
},
|
||||
|
||||
/**
|
||||
* Selects the specified request in the waterfall and opens the details view.
|
||||
* This is a firefox toolbox specific API, which providing an ability to inspect
|
||||
* a network request directly from other internal toolbox panel.
|
||||
*
|
||||
* @param {string} requestId The actor ID of the request to inspect.
|
||||
* @return {object} A promise resolved once the task finishes.
|
||||
*/
|
||||
inspectRequest(requestId) {
|
||||
// Look for the request in the existing ones or wait for it to appear, if
|
||||
// the network monitor is still loading.
|
||||
return new Promise((resolve) => {
|
||||
let request = null;
|
||||
let inspector = () => {
|
||||
request = getDisplayedRequestById(store.getState(), requestId);
|
||||
if (!request) {
|
||||
// Reset filters so that the request is visible.
|
||||
actions.toggleRequestFilterType("all");
|
||||
request = getDisplayedRequestById(store.getState(), requestId);
|
||||
}
|
||||
|
||||
// If the request was found, select it. Otherwise this function will be
|
||||
// called again once new requests arrive.
|
||||
if (request) {
|
||||
window.off(EVENTS.REQUEST_ADDED, inspector);
|
||||
actions.selectRequest(request.id);
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
|
||||
inspector();
|
||||
|
||||
if (!request) {
|
||||
window.on(EVENTS.REQUEST_ADDED, inspector);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Implement support for:
|
||||
// chrome://devtools/content/netmonitor/index.html?type=tab&id=1234 URLs
|
||||
// where 1234 is the tab id, you can retrieve from about:debugging#tabs links.
|
||||
// Simply copy the id from about:devtools-toolbox?type=tab&id=1234 URLs.
|
||||
|
||||
// URL constructor doesn't support chrome: scheme
|
||||
let href = window.location.href.replace(/chrome:/, "http://");
|
||||
@ -90,13 +222,7 @@ if (window.location.protocol === "chrome:" && url.search.length > 1) {
|
||||
}
|
||||
};
|
||||
|
||||
let api = new NetMonitorAPI();
|
||||
await api.connect(toolbox);
|
||||
let app = window.initialize(api);
|
||||
app.bootstrap({
|
||||
toolbox,
|
||||
document: window.document,
|
||||
});
|
||||
window.Netmonitor.bootstrap({ toolbox });
|
||||
} catch (err) {
|
||||
window.alert("Unable to start the network monitor:" + err);
|
||||
}
|
||||
|
@ -14,22 +14,12 @@ NetMonitorPanel.prototype = {
|
||||
if (!this.toolbox.target.isRemote) {
|
||||
await this.toolbox.target.makeRemote();
|
||||
}
|
||||
|
||||
// Reuse an existing Network monitor API object if available.
|
||||
// It could have been created for WE API before Net panel opens.
|
||||
let api = await this.toolbox.getNetMonitorAPI();
|
||||
let app = this.panelWin.initialize(api);
|
||||
|
||||
// Connect the application object to the UI.
|
||||
await app.bootstrap({
|
||||
await this.panelWin.Netmonitor.bootstrap({
|
||||
toolbox: this.toolbox,
|
||||
document: this.panelWin.document,
|
||||
panel: this,
|
||||
});
|
||||
|
||||
// Ready to go!
|
||||
this.emit("ready");
|
||||
this.isReady = true;
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
|
@ -1,197 +0,0 @@
|
||||
/* 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("devtools/shared/event-emitter");
|
||||
|
||||
const { bindActionCreators } = require("devtools/client/shared/vendor/redux");
|
||||
const { Connector } = require("./connector/index");
|
||||
const { configureStore } = require("./create-store");
|
||||
const { EVENTS } = require("./constants");
|
||||
const Actions = require("./actions/index");
|
||||
|
||||
const {
|
||||
getDisplayedRequestById,
|
||||
getSortedRequests
|
||||
} = require("./selectors/index");
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
// Configure store/state object.
|
||||
this.store = configureStore(this.connector);
|
||||
|
||||
// List of listeners for `devtools.network.onRequestFinished` WebExt API
|
||||
this._requestFinishedListeners = new Set();
|
||||
|
||||
// Bind event handlers
|
||||
this.onRequestAdded = this.onRequestAdded.bind(this);
|
||||
this.actions = bindActionCreators(Actions, this.store.dispatch);
|
||||
}
|
||||
|
||||
NetMonitorAPI.prototype = {
|
||||
async connect(toolbox) {
|
||||
// Bail out if already connected.
|
||||
if (this.toolbox) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.toolbox = toolbox;
|
||||
|
||||
// Register listener for new requests (utilized by WebExtension API).
|
||||
this.on(EVENTS.REQUEST_ADDED, this.onRequestAdded);
|
||||
|
||||
// Initialize connection to the backend. Pass `this` as the owner,
|
||||
// so this object can receive all emitted events.
|
||||
const connection = {
|
||||
tabConnection: {
|
||||
tabTarget: toolbox.target,
|
||||
},
|
||||
toolbox,
|
||||
owner: this,
|
||||
};
|
||||
|
||||
await this.connectBackend(this.connector, connection, this.actions,
|
||||
this.store.getState);
|
||||
},
|
||||
|
||||
/**
|
||||
* Clean up (unmount from DOM, remove listeners, disconnect).
|
||||
*/
|
||||
async destroy() {
|
||||
this.off(EVENTS.REQUEST_ADDED, this.onRequestAdded);
|
||||
|
||||
await this.connector.disconnect();
|
||||
|
||||
if (this.harExportConnector) {
|
||||
await this.harExportConnector.disconnect();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Connect to the Firefox backend by default.
|
||||
*
|
||||
* As soon as connections to different back-ends is supported
|
||||
* this function should be responsible for picking the right API.
|
||||
*/
|
||||
async connectBackend(connector, connection, actions, getState) {
|
||||
// The connection might happen during Toolbox initialization
|
||||
// so make sure the target is ready.
|
||||
await connection.tabConnection.tabTarget.makeRemote();
|
||||
return connector.connectFirefox(connection, actions, getState);
|
||||
},
|
||||
|
||||
// HAR
|
||||
|
||||
/**
|
||||
* Support for `devtools.network.getHAR` (get collected data as HAR)
|
||||
*/
|
||||
async getHar() {
|
||||
let { HarExporter } = require("devtools/client/netmonitor/src/har/har-exporter");
|
||||
let state = this.store.getState();
|
||||
|
||||
let 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 onRequestAdded(requestId) {
|
||||
if (!this._requestFinishedListeners.size) {
|
||||
return;
|
||||
}
|
||||
|
||||
let { HarExporter } = require("devtools/client/netmonitor/src/har/har-exporter");
|
||||
|
||||
let connector = await this.getHarExportConnector();
|
||||
let request = getDisplayedRequestById(this.store.getState(), requestId);
|
||||
if (!request) {
|
||||
console.error("HAR: request not found " + requestId);
|
||||
return;
|
||||
}
|
||||
|
||||
let options = {
|
||||
connector,
|
||||
includeResponseBodies: false,
|
||||
items: [request],
|
||||
};
|
||||
|
||||
let har = await HarExporter.getHar(options);
|
||||
|
||||
// There is page so remove the page reference.
|
||||
let harEntry = har.log.entries[0];
|
||||
delete harEntry.pageref;
|
||||
|
||||
this._requestFinishedListeners.forEach(listener => listener({
|
||||
harEntry,
|
||||
requestId,
|
||||
}));
|
||||
},
|
||||
|
||||
/**
|
||||
* 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: function(listener) {
|
||||
this._requestFinishedListeners.add(listener);
|
||||
},
|
||||
|
||||
removeRequestFinishedListener: function(listener) {
|
||||
this._requestFinishedListeners.delete(listener);
|
||||
},
|
||||
|
||||
hasRequestFinishedListeners: function() {
|
||||
return this._requestFinishedListeners.size > 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* Separate connector for HAR export.
|
||||
*/
|
||||
async getHarExportConnector() {
|
||||
if (this.harExportConnector) {
|
||||
return this.harExportConnector;
|
||||
}
|
||||
|
||||
const connection = {
|
||||
tabConnection: {
|
||||
tabTarget: this.toolbox.target,
|
||||
},
|
||||
toolbox: this.toolbox,
|
||||
};
|
||||
|
||||
this.harExportConnector = new Connector();
|
||||
await this.connectBackend(this.harExportConnector, connection);
|
||||
return this.harExportConnector;
|
||||
},
|
||||
};
|
||||
|
||||
exports.NetMonitorAPI = NetMonitorAPI;
|
@ -1,124 +0,0 @@
|
||||
/* 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 { createFactory } = require("devtools/client/shared/vendor/react");
|
||||
const { render, unmountComponentAtNode } = require("devtools/client/shared/vendor/react-dom");
|
||||
const Provider = createFactory(require("devtools/client/shared/vendor/react-redux").Provider);
|
||||
const App = createFactory(require("./components/App"));
|
||||
const { EVENTS } = require("./constants");
|
||||
|
||||
const {
|
||||
getDisplayedRequestById,
|
||||
} = require("./selectors/index");
|
||||
|
||||
/**
|
||||
* Global App object for Network panel. This object depends
|
||||
* on the UI and can't be created independently.
|
||||
*
|
||||
* This object can be consumed by other panels (e.g. Console
|
||||
* is using inspectRequest), by the Launchpad (bootstrap), etc.
|
||||
*
|
||||
* @param {Object} api An existing API object to be reused.
|
||||
*/
|
||||
function NetMonitorApp(api) {
|
||||
this.api = api;
|
||||
}
|
||||
|
||||
NetMonitorApp.prototype = {
|
||||
async bootstrap({ toolbox, document }) {
|
||||
// Get the root element for mounting.
|
||||
this.mount = document.querySelector("#mount");
|
||||
|
||||
const openLink = (link) => {
|
||||
let parentDoc = toolbox.doc;
|
||||
let iframe = parentDoc.getElementById("toolbox-panel-iframe-netmonitor");
|
||||
let top = iframe.ownerDocument.defaultView.top;
|
||||
top.openUILinkIn(link, "tab");
|
||||
};
|
||||
|
||||
const openSplitConsole = (err) => {
|
||||
toolbox.openSplitConsole().then(() => {
|
||||
toolbox.target.logErrorInPage(err, "har");
|
||||
});
|
||||
};
|
||||
|
||||
let {
|
||||
actions,
|
||||
connector,
|
||||
store,
|
||||
} = this.api;
|
||||
|
||||
const sourceMapService = toolbox.sourceMapURLService;
|
||||
const app = App({
|
||||
actions,
|
||||
connector,
|
||||
openLink,
|
||||
openSplitConsole,
|
||||
sourceMapService
|
||||
});
|
||||
|
||||
// Render the root Application component.
|
||||
render(Provider({ store: store }, app), this.mount);
|
||||
},
|
||||
|
||||
/**
|
||||
* Clean up (unmount from DOM, remove listeners, disconnect).
|
||||
*/
|
||||
async destroy() {
|
||||
unmountComponentAtNode(this.mount);
|
||||
|
||||
// Make sure to destroy the API object. It's usually destroyed
|
||||
// in the Toolbox destroy method, but we need it here for case
|
||||
// where the Network panel is initialized without the toolbox
|
||||
// and running in a tab (see initialize.js for details).
|
||||
await this.api.destroy();
|
||||
},
|
||||
|
||||
/**
|
||||
* Selects the specified request in the waterfall and opens the details view.
|
||||
* This is a firefox toolbox specific API, which providing an ability to inspect
|
||||
* a network request directly from other internal toolbox panel.
|
||||
*
|
||||
* @param {string} requestId The actor ID of the request to inspect.
|
||||
* @return {object} A promise resolved once the task finishes.
|
||||
*/
|
||||
async inspectRequest(requestId) {
|
||||
let {
|
||||
actions,
|
||||
store,
|
||||
} = this.api;
|
||||
|
||||
// Look for the request in the existing ones or wait for it to appear,
|
||||
// if the network monitor is still loading.
|
||||
return new Promise((resolve) => {
|
||||
let request = null;
|
||||
let inspector = () => {
|
||||
request = getDisplayedRequestById(store.getState(), requestId);
|
||||
if (!request) {
|
||||
// Reset filters so that the request is visible.
|
||||
actions.toggleRequestFilterType("all");
|
||||
request = getDisplayedRequestById(store.getState(), requestId);
|
||||
}
|
||||
|
||||
// If the request was found, select it. Otherwise this function will be
|
||||
// called again once new requests arrive.
|
||||
if (request) {
|
||||
this.api.off(EVENTS.REQUEST_ADDED, inspector);
|
||||
actions.selectRequest(request.id);
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
|
||||
inspector();
|
||||
|
||||
if (!request) {
|
||||
this.api.on(EVENTS.REQUEST_ADDED, inspector);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
exports.NetMonitorApp = NetMonitorApp;
|
@ -98,4 +98,4 @@ class ChromeConnector {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ChromeConnector;
|
||||
module.exports = new ChromeConnector();
|
||||
|
@ -35,28 +35,18 @@ class FirefoxConnector {
|
||||
this.getNetworkRequest = this.getNetworkRequest.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to the backend.
|
||||
*
|
||||
* @param {Object} connection object with e.g. reference to the Toolbox.
|
||||
* @param {Object} actions (optional) is used to fire Redux actions to update store.
|
||||
* @param {Object} getState (optional) is used to get access to the state.
|
||||
*/
|
||||
async connect(connection, actions, getState) {
|
||||
this.actions = actions;
|
||||
this.getState = getState;
|
||||
this.tabTarget = connection.tabConnection.tabTarget;
|
||||
this.toolbox = connection.toolbox;
|
||||
|
||||
// The owner object (NetMonitorAPI) received all events.
|
||||
this.owner = connection.owner;
|
||||
this.panel = connection.panel;
|
||||
|
||||
this.webConsoleClient = this.tabTarget.activeConsole;
|
||||
|
||||
this.dataProvider = new FirefoxDataProvider({
|
||||
webConsoleClient: this.webConsoleClient,
|
||||
actions: this.actions,
|
||||
owner: this.owner,
|
||||
});
|
||||
|
||||
await this.addListeners();
|
||||
@ -66,32 +56,25 @@ class FirefoxConnector {
|
||||
// these are used to pause/resume the connector.
|
||||
// Paused network panel should be automatically resumed when page
|
||||
// reload, so `will-navigate` listener needs to be there all the time.
|
||||
if (this.tabTarget) {
|
||||
this.tabTarget.on("will-navigate", this.willNavigate);
|
||||
this.tabTarget.on("navigate", this.navigate);
|
||||
}
|
||||
this.tabTarget.on("will-navigate", this.willNavigate);
|
||||
this.tabTarget.on("navigate", this.navigate);
|
||||
|
||||
// Displaying cache events is only intended for the UI panel.
|
||||
if (this.actions) {
|
||||
this.displayCachedEvents();
|
||||
}
|
||||
this.displayCachedEvents();
|
||||
}
|
||||
|
||||
async disconnect() {
|
||||
if (this.actions) {
|
||||
this.actions.batchReset();
|
||||
}
|
||||
this.actions.batchReset();
|
||||
|
||||
await this.removeListeners();
|
||||
|
||||
if (this.tabTarget) {
|
||||
this.tabTarget.off("will-navigate", this.willNavigate);
|
||||
this.tabTarget.off("navigate", this.navigate);
|
||||
this.tabTarget.off("will-navigate");
|
||||
this.tabTarget = null;
|
||||
}
|
||||
|
||||
this.webConsoleClient = null;
|
||||
this.dataProvider = null;
|
||||
this.panel = null;
|
||||
}
|
||||
|
||||
async pause() {
|
||||
@ -149,22 +132,18 @@ class FirefoxConnector {
|
||||
}
|
||||
|
||||
willNavigate() {
|
||||
if (this.actions) {
|
||||
if (!Services.prefs.getBoolPref("devtools.netmonitor.persistlog")) {
|
||||
this.actions.batchReset();
|
||||
this.actions.clearRequests();
|
||||
} else {
|
||||
// If the log is persistent, just clear all accumulated timing markers.
|
||||
this.actions.clearTimingMarkers();
|
||||
}
|
||||
if (!Services.prefs.getBoolPref("devtools.netmonitor.persistlog")) {
|
||||
this.actions.batchReset();
|
||||
this.actions.clearRequests();
|
||||
} else {
|
||||
// If the log is persistent, just clear all accumulated timing markers.
|
||||
this.actions.clearTimingMarkers();
|
||||
}
|
||||
|
||||
// Resume is done automatically on page reload/navigation.
|
||||
if (this.actions && this.getState) {
|
||||
let state = this.getState();
|
||||
if (!state.requests.recording) {
|
||||
this.actions.toggleRecording();
|
||||
}
|
||||
let state = this.getState();
|
||||
if (!state.requests.recording) {
|
||||
this.actions.toggleRecording();
|
||||
}
|
||||
}
|
||||
|
||||
@ -177,24 +156,19 @@ class FirefoxConnector {
|
||||
if (this.dataProvider && !this.dataProvider.isPayloadQueueEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (this.owner) {
|
||||
this.owner.off(EVENTS.PAYLOAD_READY, listener);
|
||||
}
|
||||
window.off(EVENTS.PAYLOAD_READY, listener);
|
||||
// Netmonitor may already be destroyed,
|
||||
// so do not try to notify the listeners
|
||||
if (this.dataProvider) {
|
||||
this.onReloaded();
|
||||
}
|
||||
};
|
||||
if (this.owner) {
|
||||
this.owner.on(EVENTS.PAYLOAD_READY, listener);
|
||||
}
|
||||
window.on(EVENTS.PAYLOAD_READY, listener);
|
||||
}
|
||||
|
||||
onReloaded() {
|
||||
let panel = this.toolbox.getPanel("netmonitor");
|
||||
if (panel) {
|
||||
panel.emit("reloaded");
|
||||
if (this.panel) {
|
||||
this.panel.emit("reloaded");
|
||||
}
|
||||
}
|
||||
|
||||
@ -230,12 +204,8 @@ class FirefoxConnector {
|
||||
"dom-interactive" : "dom-complete",
|
||||
time: marker.unixTime / 1000
|
||||
};
|
||||
|
||||
if (this.actions) {
|
||||
this.actions.addTimingMarker(event);
|
||||
}
|
||||
|
||||
this.emit(EVENTS.TIMELINE_EVENT, event);
|
||||
this.actions.addTimingMarker(event);
|
||||
window.emit(EVENTS.TIMELINE_EVENT, event);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -246,11 +216,8 @@ class FirefoxConnector {
|
||||
* @param {object} marker
|
||||
*/
|
||||
onDocEvent(event) {
|
||||
if (this.actions) {
|
||||
this.actions.addTimingMarker(event);
|
||||
}
|
||||
|
||||
this.emit(EVENTS.TIMELINE_EVENT, event);
|
||||
this.actions.addTimingMarker(event);
|
||||
window.emit(EVENTS.TIMELINE_EVENT, event);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -404,22 +371,9 @@ class FirefoxConnector {
|
||||
}
|
||||
|
||||
getTimingMarker(name) {
|
||||
if (!this.getState) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
let state = this.getState();
|
||||
return getDisplayedTimingMarker(state, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire events for the owner object.
|
||||
*/
|
||||
emit(type, data) {
|
||||
if (this.owner) {
|
||||
this.owner.emit(type, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FirefoxConnector;
|
||||
module.exports = new FirefoxConnector();
|
||||
|
@ -18,19 +18,11 @@ const { fetchHeaders } = require("../utils/request-utils");
|
||||
* or not.
|
||||
*/
|
||||
class FirefoxDataProvider {
|
||||
/**
|
||||
* Constructor for data provider
|
||||
*
|
||||
* @param {Object} webConcoleClient represents the client object for Console actor.
|
||||
* @param {Object} actions set of actions fired during data fetching process
|
||||
* @params {Object} owner all events are fired on this object
|
||||
*/
|
||||
constructor({webConsoleClient, actions, owner}) {
|
||||
constructor({webConsoleClient, actions}) {
|
||||
// Options
|
||||
this.webConsoleClient = webConsoleClient;
|
||||
this.actions = actions || {};
|
||||
this.actions = actions;
|
||||
this.actionsEnabled = true;
|
||||
this.owner = owner;
|
||||
|
||||
// Internal properties
|
||||
this.payloadQueue = new Map();
|
||||
@ -92,7 +84,7 @@ class FirefoxDataProvider {
|
||||
}, true);
|
||||
}
|
||||
|
||||
this.emit(EVENTS.REQUEST_ADDED, id);
|
||||
emit(EVENTS.REQUEST_ADDED, id);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -322,7 +314,7 @@ class FirefoxDataProvider {
|
||||
url,
|
||||
});
|
||||
|
||||
this.emit(EVENTS.NETWORK_EVENT, actor);
|
||||
emit(EVENTS.NETWORK_EVENT, actor);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -349,7 +341,7 @@ class FirefoxDataProvider {
|
||||
statusText: networkInfo.response.statusText,
|
||||
headersSize: networkInfo.response.headersSize
|
||||
});
|
||||
this.emit(EVENTS.STARTED_RECEIVING_RESPONSE, actor);
|
||||
emit(EVENTS.STARTED_RECEIVING_RESPONSE, actor);
|
||||
break;
|
||||
case "responseContent":
|
||||
this.pushRequestToQueue(actor, {
|
||||
@ -375,7 +367,7 @@ class FirefoxDataProvider {
|
||||
|
||||
this.onPayloadDataReceived(actor);
|
||||
|
||||
this.emit(EVENTS.NETWORK_EVENT_UPDATED, actor);
|
||||
emit(EVENTS.NETWORK_EVENT_UPDATED, actor);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -401,7 +393,7 @@ class FirefoxDataProvider {
|
||||
|
||||
// This event is fired only once per request, once all the properties are fetched
|
||||
// from `onNetworkEventUpdate`. There should be no more RDP requests after this.
|
||||
this.emit(EVENTS.PAYLOAD_READY, actor);
|
||||
emit(EVENTS.PAYLOAD_READY, actor);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -471,7 +463,7 @@ class FirefoxDataProvider {
|
||||
let updatingEventName = `UPDATING_${method.replace(/([A-Z])/g, "_$1").toUpperCase()}`;
|
||||
|
||||
// Emit event that tell we just start fetching some data
|
||||
this.emit(EVENTS[updatingEventName], actor);
|
||||
emit(EVENTS[updatingEventName], actor);
|
||||
|
||||
let response = await new Promise((resolve, reject) => {
|
||||
// Do a RDP request to fetch data from the actor.
|
||||
@ -508,7 +500,7 @@ class FirefoxDataProvider {
|
||||
let payload = await this.updateRequest(response.from, {
|
||||
requestHeaders: response
|
||||
});
|
||||
this.emit(EVENTS.RECEIVED_REQUEST_HEADERS, response.from);
|
||||
emit(EVENTS.RECEIVED_REQUEST_HEADERS, response.from);
|
||||
return payload.requestHeaders;
|
||||
}
|
||||
|
||||
@ -521,7 +513,7 @@ class FirefoxDataProvider {
|
||||
let payload = await this.updateRequest(response.from, {
|
||||
responseHeaders: response
|
||||
});
|
||||
this.emit(EVENTS.RECEIVED_RESPONSE_HEADERS, response.from);
|
||||
emit(EVENTS.RECEIVED_RESPONSE_HEADERS, response.from);
|
||||
return payload.responseHeaders;
|
||||
}
|
||||
|
||||
@ -534,7 +526,7 @@ class FirefoxDataProvider {
|
||||
let payload = await this.updateRequest(response.from, {
|
||||
requestCookies: response
|
||||
});
|
||||
this.emit(EVENTS.RECEIVED_REQUEST_COOKIES, response.from);
|
||||
emit(EVENTS.RECEIVED_REQUEST_COOKIES, response.from);
|
||||
return payload.requestCookies;
|
||||
}
|
||||
|
||||
@ -547,7 +539,7 @@ class FirefoxDataProvider {
|
||||
let payload = await this.updateRequest(response.from, {
|
||||
requestPostData: response
|
||||
});
|
||||
this.emit(EVENTS.RECEIVED_REQUEST_POST_DATA, response.from);
|
||||
emit(EVENTS.RECEIVED_REQUEST_POST_DATA, response.from);
|
||||
return payload.requestPostData;
|
||||
}
|
||||
|
||||
@ -560,7 +552,7 @@ class FirefoxDataProvider {
|
||||
let payload = await this.updateRequest(response.from, {
|
||||
securityInfo: response.securityInfo
|
||||
});
|
||||
this.emit(EVENTS.RECEIVED_SECURITY_INFO, response.from);
|
||||
emit(EVENTS.RECEIVED_SECURITY_INFO, response.from);
|
||||
return payload.securityInfo;
|
||||
}
|
||||
|
||||
@ -573,7 +565,7 @@ class FirefoxDataProvider {
|
||||
let payload = await this.updateRequest(response.from, {
|
||||
responseCookies: response
|
||||
});
|
||||
this.emit(EVENTS.RECEIVED_RESPONSE_COOKIES, response.from);
|
||||
emit(EVENTS.RECEIVED_RESPONSE_COOKIES, response.from);
|
||||
return payload.responseCookies;
|
||||
}
|
||||
|
||||
@ -590,7 +582,7 @@ class FirefoxDataProvider {
|
||||
mimeType: response.content.mimeType,
|
||||
responseContent: response,
|
||||
});
|
||||
this.emit(EVENTS.RECEIVED_RESPONSE_CONTENT, response.from);
|
||||
emit(EVENTS.RECEIVED_RESPONSE_CONTENT, response.from);
|
||||
return payload.responseContent;
|
||||
}
|
||||
|
||||
@ -603,7 +595,7 @@ class FirefoxDataProvider {
|
||||
let payload = await this.updateRequest(response.from, {
|
||||
eventTimings: response
|
||||
});
|
||||
this.emit(EVENTS.RECEIVED_EVENT_TIMINGS, response.from);
|
||||
emit(EVENTS.RECEIVED_EVENT_TIMINGS, response.from);
|
||||
return payload.eventTimings;
|
||||
}
|
||||
|
||||
@ -616,17 +608,17 @@ class FirefoxDataProvider {
|
||||
let payload = await this.updateRequest(response.from, {
|
||||
stacktrace: response.stacktrace
|
||||
});
|
||||
this.emit(EVENTS.RECEIVED_EVENT_STACKTRACE, response.from);
|
||||
emit(EVENTS.RECEIVED_EVENT_STACKTRACE, response.from);
|
||||
return payload.stacktrace;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fire events for the owner object.
|
||||
*/
|
||||
emit(type, data) {
|
||||
if (this.owner) {
|
||||
this.owner.emit(type, data);
|
||||
}
|
||||
/**
|
||||
* Guard 'emit' to avoid exception in non-window environment.
|
||||
*/
|
||||
function emit(type, data) {
|
||||
if (typeof window != "undefined") {
|
||||
window.emit(type, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,14 +54,12 @@ class Connector {
|
||||
}
|
||||
|
||||
connectChrome(connection, actions, getState) {
|
||||
let ChromeConnector = require("./chrome-connector");
|
||||
this.connector = new ChromeConnector();
|
||||
this.connector = require("./chrome-connector");
|
||||
return this.connector.connect(connection, actions, getState);
|
||||
}
|
||||
|
||||
connectFirefox(connection, actions, getState) {
|
||||
let FirefoxConnector = require("./firefox-connector");
|
||||
this.connector = new FirefoxConnector();
|
||||
this.connector = require("./firefox-connector");
|
||||
return this.connector.connect(connection, actions, getState);
|
||||
}
|
||||
|
||||
|
@ -126,9 +126,7 @@ const HarExporter = {
|
||||
* Configuration object, see save() for detailed description.
|
||||
*/
|
||||
getHar: function(options) {
|
||||
return this.fetchHarData(options).then(data => {
|
||||
return data ? JSON.parse(data) : null;
|
||||
});
|
||||
return this.fetchHarData(options).then(JSON.parse);
|
||||
},
|
||||
|
||||
// Helpers
|
||||
|
@ -15,8 +15,6 @@ DIRS += [
|
||||
]
|
||||
|
||||
DevToolsModules(
|
||||
'api.js',
|
||||
'app.js',
|
||||
'constants.js',
|
||||
'create-store.js',
|
||||
)
|
||||
|
@ -48,7 +48,7 @@ add_task(async function() {
|
||||
});
|
||||
|
||||
wait = waitForDOM(document, ".CodeMirror-code");
|
||||
let onResponseContent = monitor.panelWin.api.once(EVENTS.RECEIVED_RESPONSE_CONTENT);
|
||||
let onResponseContent = monitor.panelWin.once(EVENTS.RECEIVED_RESPONSE_CONTENT);
|
||||
store.dispatch(Actions.toggleNetworkDetails());
|
||||
EventUtils.sendMouseEvent({ type: "click" },
|
||||
document.querySelector("#response-tab"));
|
||||
|
@ -32,7 +32,7 @@ add_task(async function() {
|
||||
});
|
||||
|
||||
let onNetworkEvents = waitForNetworkEvents(monitor, 1);
|
||||
let onEventTimings = waitFor(monitor.panelWin.api, EVENTS.RECEIVED_EVENT_TIMINGS);
|
||||
let onEventTimings = waitFor(monitor.panelWin, EVENTS.RECEIVED_EVENT_TIMINGS);
|
||||
tab.linkedBrowser.reload();
|
||||
await Promise.all([onNetworkEvents, onEventTimings]);
|
||||
|
||||
|
@ -268,7 +268,7 @@ add_task(async function() {
|
||||
}
|
||||
|
||||
async function selectIndexAndWaitForJSONView(index) {
|
||||
let onResponseContent = monitor.panelWin.api.once(EVENTS.RECEIVED_RESPONSE_CONTENT);
|
||||
let onResponseContent = monitor.panelWin.once(EVENTS.RECEIVED_RESPONSE_CONTENT);
|
||||
let tabpanel = document.querySelector("#response-panel");
|
||||
let waitDOM = waitForDOM(tabpanel, ".treeTable");
|
||||
store.dispatch(Actions.selectRequestByIndex(index));
|
||||
@ -281,7 +281,7 @@ add_task(async function() {
|
||||
}
|
||||
|
||||
async function selectIndexAndWaitForImageView(index) {
|
||||
let onResponseContent = monitor.panelWin.api.once(EVENTS.RECEIVED_RESPONSE_CONTENT);
|
||||
let onResponseContent = monitor.panelWin.once(EVENTS.RECEIVED_RESPONSE_CONTENT);
|
||||
let tabpanel = document.querySelector("#response-panel");
|
||||
let waitDOM = waitForDOM(tabpanel, ".response-image");
|
||||
store.dispatch(Actions.selectRequestByIndex(index));
|
||||
|
@ -28,7 +28,7 @@ add_task(async function() {
|
||||
is(getSelectedRequest(store.getState()), null,
|
||||
"There should be no selected item in the requests menu.");
|
||||
|
||||
let networkEvent = monitor.panelWin.api.once(EVENTS.NETWORK_EVENT);
|
||||
let networkEvent = monitor.panelWin.once(EVENTS.NETWORK_EVENT);
|
||||
tab.linkedBrowser.reload();
|
||||
await networkEvent;
|
||||
|
||||
|
@ -24,11 +24,11 @@ add_task(async function() {
|
||||
assertRequestCount(store, 1);
|
||||
|
||||
let noRequest = true;
|
||||
monitor.panelWin.api.once(EVENTS.NETWORK_EVENT, () => {
|
||||
monitor.panelWin.once(EVENTS.NETWORK_EVENT, () => {
|
||||
noRequest = false;
|
||||
});
|
||||
|
||||
monitor.panelWin.api.once(EVENTS.NETWORK_EVENT_UPDATED, () => {
|
||||
monitor.panelWin.once(EVENTS.NETWORK_EVENT_UPDATED, () => {
|
||||
noRequest = false;
|
||||
});
|
||||
|
||||
|
@ -41,7 +41,7 @@ add_task(async function() {
|
||||
|
||||
for (let testcase of TEST_DATA) {
|
||||
info("Testing Security tab visibility for " + testcase.desc);
|
||||
let onNewItem = monitor.panelWin.api.once(EVENTS.NETWORK_EVENT);
|
||||
let onNewItem = monitor.panelWin.once(EVENTS.NETWORK_EVENT);
|
||||
let onComplete = testcase.isBroken ?
|
||||
waitForSecurityBrokenNetworkEvent() :
|
||||
waitForNetworkEvents(monitor, 1);
|
||||
@ -106,7 +106,7 @@ add_task(async function() {
|
||||
];
|
||||
|
||||
let promises = awaitedEvents.map((event) => {
|
||||
return monitor.panelWin.api.once(EVENTS[event]);
|
||||
return monitor.panelWin.once(EVENTS[event]);
|
||||
});
|
||||
|
||||
return Promise.all(promises);
|
||||
|
@ -34,7 +34,7 @@ function test() {
|
||||
|
||||
function expectEvent(evt, cb) {
|
||||
promiseList.push(new Promise((resolve, reject) => {
|
||||
monitor.panelWin.api.once(evt, _ => {
|
||||
monitor.panelWin.once(evt, _ => {
|
||||
cb().then(resolve, reject);
|
||||
});
|
||||
}));
|
||||
@ -151,7 +151,7 @@ function test() {
|
||||
);
|
||||
});
|
||||
|
||||
monitor.panelWin.api.once(EVENTS.RECEIVED_REQUEST_POST_DATA, () => {
|
||||
monitor.panelWin.once(EVENTS.RECEIVED_REQUEST_POST_DATA, () => {
|
||||
ok(false, "Trap listener: this request doesn't have any post data.");
|
||||
});
|
||||
|
||||
|
@ -161,7 +161,7 @@ add_task(async function() {
|
||||
}
|
||||
|
||||
async function testCookiesTab() {
|
||||
let onEvent = monitor.panelWin.api.once(EVENTS.TAB_UPDATED);
|
||||
let onEvent = monitor.panelWin.once(EVENTS.TAB_UPDATED);
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
document.querySelectorAll("#details-pane tab")[1]);
|
||||
await onEvent;
|
||||
@ -204,7 +204,7 @@ add_task(async function() {
|
||||
}
|
||||
|
||||
async function testResponseTab() {
|
||||
let onEvent = monitor.panelWin.api.once(EVENTS.TAB_UPDATED);
|
||||
let onEvent = monitor.panelWin.once(EVENTS.TAB_UPDATED);
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
document.querySelectorAll("#details-pane tab")[3]);
|
||||
await onEvent;
|
||||
|
@ -155,13 +155,13 @@ function waitForTimelineMarkers(monitor) {
|
||||
info(`Got marker: ${marker.name}`);
|
||||
markers.push(marker);
|
||||
if (markers.length == 2) {
|
||||
monitor.panelWin.api.off(EVENTS.TIMELINE_EVENT, handleTimelineEvent);
|
||||
monitor.panelWin.off(EVENTS.TIMELINE_EVENT, handleTimelineEvent);
|
||||
info("Got two timeline markers, done waiting");
|
||||
resolve(markers);
|
||||
}
|
||||
}
|
||||
|
||||
monitor.panelWin.api.on(EVENTS.TIMELINE_EVENT, handleTimelineEvent);
|
||||
monitor.panelWin.on(EVENTS.TIMELINE_EVENT, handleTimelineEvent);
|
||||
});
|
||||
}
|
||||
|
||||
@ -212,14 +212,14 @@ function waitForAllRequestsFinished(monitor) {
|
||||
}
|
||||
|
||||
// All requests are done - unsubscribe from events and resolve!
|
||||
window.api.off(EVENTS.NETWORK_EVENT, onRequest);
|
||||
window.api.off(EVENTS.PAYLOAD_READY, onTimings);
|
||||
window.off(EVENTS.NETWORK_EVENT, onRequest);
|
||||
window.off(EVENTS.PAYLOAD_READY, onTimings);
|
||||
info("All requests finished");
|
||||
resolve();
|
||||
}
|
||||
|
||||
window.api.on(EVENTS.NETWORK_EVENT, onRequest);
|
||||
window.api.on(EVENTS.PAYLOAD_READY, onTimings);
|
||||
window.on(EVENTS.NETWORK_EVENT, onRequest);
|
||||
window.on(EVENTS.PAYLOAD_READY, onTimings);
|
||||
});
|
||||
}
|
||||
|
||||
@ -248,12 +248,12 @@ let updatedTypes = [
|
||||
// Start collecting all networkEventUpdate event when panel is opened.
|
||||
// removeTab() should be called once all corresponded RECEIVED_* events finished.
|
||||
function startNetworkEventUpdateObserver(panelWin) {
|
||||
updatingTypes.forEach((type) => panelWin.api.on(type, actor => {
|
||||
updatingTypes.forEach((type) => panelWin.on(type, actor => {
|
||||
let key = actor + "-" + updatedTypes[updatingTypes.indexOf(type)];
|
||||
finishedQueue[key] = finishedQueue[key] ? finishedQueue[key] + 1 : 1;
|
||||
}));
|
||||
|
||||
updatedTypes.forEach((type) => panelWin.api.on(type, actor => {
|
||||
updatedTypes.forEach((type) => panelWin.on(type, actor => {
|
||||
let key = actor + "-" + type;
|
||||
finishedQueue[key] = finishedQueue[key] ? finishedQueue[key] - 1 : -1;
|
||||
}));
|
||||
@ -389,14 +389,14 @@ function waitForNetworkEvents(monitor, getRequests) {
|
||||
|
||||
// Wait until networkEvent & payloadReady finish for each request.
|
||||
if (networkEvent >= getRequests && payloadReady >= getRequests) {
|
||||
panel.api.off(EVENTS.NETWORK_EVENT, onNetworkEvent);
|
||||
panel.api.off(EVENTS.PAYLOAD_READY, onPayloadReady);
|
||||
panel.off(EVENTS.NETWORK_EVENT, onNetworkEvent);
|
||||
panel.off(EVENTS.PAYLOAD_READY, onPayloadReady);
|
||||
executeSoon(resolve);
|
||||
}
|
||||
}
|
||||
|
||||
panel.api.on(EVENTS.NETWORK_EVENT, onNetworkEvent);
|
||||
panel.api.on(EVENTS.PAYLOAD_READY, onPayloadReady);
|
||||
panel.on(EVENTS.NETWORK_EVENT, onNetworkEvent);
|
||||
panel.on(EVENTS.PAYLOAD_READY, onPayloadReady);
|
||||
});
|
||||
}
|
||||
|
||||
@ -563,7 +563,7 @@ function verifyRequestItemTarget(document, requestList, requestItem, method,
|
||||
|
||||
/**
|
||||
* Helper function for waiting for an event to fire before resolving a promise.
|
||||
* Example: waitFor(aMonitor.panelWin.api, EVENT_NAME);
|
||||
* Example: waitFor(aMonitor.panelWin, EVENT_NAME);
|
||||
*
|
||||
* @param object subject
|
||||
* The event emitter object that is being listened to.
|
||||
@ -737,7 +737,7 @@ async function showColumn(monitor, column) {
|
||||
*/
|
||||
async function selectIndexAndWaitForSourceEditor(monitor, index) {
|
||||
let document = monitor.panelWin.document;
|
||||
let onResponseContent = monitor.panelWin.api.once(EVENTS.RECEIVED_RESPONSE_CONTENT);
|
||||
let onResponseContent = monitor.panelWin.once(EVENTS.RECEIVED_RESPONSE_CONTENT);
|
||||
// Select the request first, as it may try to fetch whatever is the current request's
|
||||
// responseContent if we select the ResponseTab first.
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" },
|
||||
|
@ -18,7 +18,7 @@ add_task(async function task() {
|
||||
let toolbox = gDevTools.getToolbox(target);
|
||||
|
||||
let monitor = toolbox.getCurrentPanel();
|
||||
let netReady = monitor.panelWin.api.once("NetMonitor:PayloadReady");
|
||||
let netReady = monitor.panelWin.once("NetMonitor:PayloadReady");
|
||||
|
||||
// Fire an XHR POST request.
|
||||
await ContentTask.spawn(gBrowser.selectedBrowser, null, function() {
|
||||
@ -69,7 +69,7 @@ async function testNetworkMessage(messageNode) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait until all lazily fetch requests in netmonitor get finished.
|
||||
* Wait until all lazily fetch requests in netmonitor get finsished.
|
||||
* Otherwise test will be shutdown too early and cause failure.
|
||||
*/
|
||||
async function waitForLazyRequests(toolbox) {
|
||||
|
Loading…
Reference in New Issue
Block a user