зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1005755 - Stop using Connector as a singleton; r=rickychien
MozReview-Commit-ID: tQKFiKDozA --HG-- extra : rebase_source : f1392a9c909464d812e868dc3760e2f0d69fc8ae
This commit is contained in:
Родитель
2b9694966e
Коммит
b27a14a02a
|
@ -14,7 +14,8 @@
|
|||
<script>
|
||||
"use strict";
|
||||
|
||||
const { BrowserLoader } = Components.utils.import("resource://devtools/client/shared/browser-loader.js", {});
|
||||
const { BrowserLoader } = Components.utils.import(
|
||||
"resource://devtools/client/shared/browser-loader.js", {});
|
||||
const require = window.windowRequire = BrowserLoader({
|
||||
baseURI: "resource://devtools/client/netmonitor/",
|
||||
window,
|
||||
|
@ -25,15 +26,23 @@
|
|||
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/utils/create-store");
|
||||
const store = configureStore();
|
||||
const actions = bindActionCreators(require("./src/actions/index"), store.dispatch);
|
||||
const { onFirefoxConnect, onDisconnect } = require("./src/connector/index");
|
||||
const App = createFactory(require("./src/components/app"));
|
||||
const { getDisplayedRequestById } = require("./src/selectors/index");
|
||||
const { EVENTS } = require("./src/constants");
|
||||
|
||||
// Inject EventEmitter into global window.
|
||||
EventEmitter.decorate(window);
|
||||
|
||||
// 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.store = store;
|
||||
window.connector = connector;
|
||||
|
||||
window.Netmonitor = {
|
||||
bootstrap({ toolbox }) {
|
||||
|
@ -53,17 +62,57 @@
|
|||
top.openUILinkIn(link, "tab");
|
||||
};
|
||||
|
||||
const App = createFactory(require("./src/components/app"));
|
||||
// Render the root Application component.
|
||||
const sourceMapService = toolbox.sourceMapURLService;
|
||||
const app = App({ sourceMapService, openLink });
|
||||
const app = App({ connector, openLink, sourceMapService });
|
||||
render(Provider({ store }, app), this.mount);
|
||||
return onFirefoxConnect(connection, actions, store.getState);
|
||||
|
||||
// Connect to the Firefox backend by default.
|
||||
return connector.connectFirefox(connection, actions, store.getState);
|
||||
},
|
||||
|
||||
destroy() {
|
||||
unmountComponentAtNode(this.mount);
|
||||
return onDisconnect();
|
||||
return connector.disconnect();
|
||||
},
|
||||
|
||||
/**
|
||||
* 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:
|
||||
|
|
|
@ -13,7 +13,6 @@ const React = require("react");
|
|||
const ReactDOM = require("react-dom");
|
||||
const { bindActionCreators } = require("redux");
|
||||
const { bootstrap, renderRoot } = require("devtools-launchpad");
|
||||
const EventEmitter = require("devtools-modules/src/utils/event-emitter");
|
||||
const { Services: { appinfo, pref }} = require("devtools-modules");
|
||||
|
||||
// Initialize preferences as early as possible
|
||||
|
@ -39,15 +38,17 @@ pref("devtools.netmonitor.har.enableAutoExportToFile", false);
|
|||
pref("devtools.netmonitor.persistlog", false);
|
||||
pref("devtools.styleeditor.enabled", true);
|
||||
|
||||
const { configureStore } = require("./src/utils/create-store");
|
||||
|
||||
require("./src/assets/styles/netmonitor.css");
|
||||
|
||||
const EventEmitter = require("devtools-modules/src/utils/event-emitter");
|
||||
EventEmitter.decorate(window);
|
||||
|
||||
const { configureStore } = require("./src/utils/create-store");
|
||||
const App = require("./src/components/app");
|
||||
const store = configureStore();
|
||||
const { Connector } = require("./src/connector/index");
|
||||
const connector = new Connector();
|
||||
const store = configureStore(connector);
|
||||
const actions = bindActionCreators(require("./src/actions"), store.dispatch);
|
||||
const { onConnect } = require("./src/connector");
|
||||
|
||||
// Inject to global window for testing
|
||||
window.store = store;
|
||||
|
@ -80,6 +81,7 @@ bootstrap(React, ReactDOM).then((connection) => {
|
|||
if (!connection) {
|
||||
return;
|
||||
}
|
||||
renderRoot(React, ReactDOM, App, store);
|
||||
onConnect(connection, actions, store.getState);
|
||||
|
||||
renderRoot(React, ReactDOM, App, store, {connector});
|
||||
connector.connect(connection, actions, store.getState);
|
||||
});
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { sendHTTPRequest } = require("../connector/index");
|
||||
const {
|
||||
ADD_REQUEST,
|
||||
CLEAR_REQUESTS,
|
||||
|
@ -47,7 +46,7 @@ function cloneSelectedRequest() {
|
|||
/**
|
||||
* Send a new HTTP request using the data in the custom request form.
|
||||
*/
|
||||
function sendCustomRequest() {
|
||||
function sendCustomRequest(connector) {
|
||||
return (dispatch, getState) => {
|
||||
const selected = getSelectedRequest(getState());
|
||||
|
||||
|
@ -68,7 +67,7 @@ function sendCustomRequest() {
|
|||
data.body = selected.requestPostData.postData.text;
|
||||
}
|
||||
|
||||
sendHTTPRequest(data, (response) => {
|
||||
connector.sendHTTPRequest(data, (response) => {
|
||||
return dispatch({
|
||||
type: SEND_CUSTOM_REQUEST,
|
||||
id: response.eventActor.actor,
|
||||
|
|
|
@ -15,7 +15,6 @@ const {
|
|||
TOGGLE_COLUMN,
|
||||
WATERFALL_RESIZE,
|
||||
} = require("../constants");
|
||||
const { triggerActivity } = require("../connector/index");
|
||||
|
||||
/**
|
||||
* Change network details panel.
|
||||
|
@ -56,11 +55,12 @@ function disableBrowserCache(disabled) {
|
|||
/**
|
||||
* Change performance statistics panel open state.
|
||||
*
|
||||
* @param {Object} connector - connector object to the backend
|
||||
* @param {boolean} visible - expected performance statistics panel open state
|
||||
*/
|
||||
function openStatistics(open) {
|
||||
function openStatistics(connector, open) {
|
||||
if (open) {
|
||||
triggerActivity(ACTIVITY_TYPE.RELOAD.WITH_CACHE_ENABLED);
|
||||
connector.triggerActivity(ACTIVITY_TYPE.RELOAD.WITH_CACHE_ENABLED);
|
||||
}
|
||||
return {
|
||||
type: OPEN_STATISTICS,
|
||||
|
@ -139,9 +139,9 @@ function toggleBrowserCache() {
|
|||
/**
|
||||
* Toggle performance statistics panel.
|
||||
*/
|
||||
function toggleStatistics() {
|
||||
function toggleStatistics(connector) {
|
||||
return (dispatch, getState) =>
|
||||
dispatch(openStatistics(!getState().ui.statisticsOpen));
|
||||
dispatch(openStatistics(connector, !getState().ui.statisticsOpen));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
|
|
@ -17,18 +17,25 @@ const StatisticsPanel = createFactory(require("./statistics-panel"));
|
|||
|
||||
const { div } = DOM;
|
||||
|
||||
/*
|
||||
/**
|
||||
* App component
|
||||
* The top level component for representing main panel
|
||||
*/
|
||||
function App({
|
||||
connector,
|
||||
openLink,
|
||||
sourceMapService,
|
||||
statisticsOpen,
|
||||
}) {
|
||||
return (
|
||||
div({ className: "network-monitor" },
|
||||
!statisticsOpen ? MonitorPanel({ openLink, sourceMapService }) : StatisticsPanel()
|
||||
!statisticsOpen ? MonitorPanel({
|
||||
connector,
|
||||
sourceMapService,
|
||||
openLink,
|
||||
}) : StatisticsPanel({
|
||||
connector
|
||||
})
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -36,9 +43,13 @@ function App({
|
|||
App.displayName = "App";
|
||||
|
||||
App.propTypes = {
|
||||
// The backend connector object.
|
||||
connector: PropTypes.object.isRequired,
|
||||
// Callback for opening links in the UI
|
||||
openLink: PropTypes.func,
|
||||
// Service to enable the source map feature.
|
||||
sourceMapService: PropTypes.object,
|
||||
// True if the stats panel is opened.
|
||||
statisticsOpen: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
|
|
|
@ -148,6 +148,7 @@ function CustomRequestPanel({
|
|||
CustomRequestPanel.displayName = "CustomRequestPanel";
|
||||
|
||||
CustomRequestPanel.propTypes = {
|
||||
connector: PropTypes.object.isRequired,
|
||||
removeSelectedCustomRequest: PropTypes.func.isRequired,
|
||||
request: PropTypes.object,
|
||||
sendCustomRequest: PropTypes.func.isRequired,
|
||||
|
@ -249,9 +250,9 @@ function updateCustomRequestFields(evt, request, updateRequest) {
|
|||
|
||||
module.exports = connect(
|
||||
(state) => ({ request: getSelectedRequest(state) }),
|
||||
(dispatch) => ({
|
||||
(dispatch, props) => ({
|
||||
removeSelectedCustomRequest: () => dispatch(Actions.removeSelectedCustomRequest()),
|
||||
sendCustomRequest: () => dispatch(Actions.sendCustomRequest()),
|
||||
sendCustomRequest: () => dispatch(Actions.sendCustomRequest(props.connector)),
|
||||
updateRequest: (id, data, batch) => dispatch(Actions.updateRequest(id, data, batch)),
|
||||
})
|
||||
)(CustomRequestPanel);
|
||||
|
|
|
@ -14,7 +14,6 @@ const {
|
|||
const { connect } = require("devtools/client/shared/vendor/react-redux");
|
||||
const { findDOMNode } = require("devtools/client/shared/vendor/react-dom");
|
||||
const Actions = require("../actions/index");
|
||||
const { getLongString } = require("../connector/index");
|
||||
const { getFormDataSections } = require("../utils/request-utils");
|
||||
const { getSelectedRequest } = require("../selectors/index");
|
||||
|
||||
|
@ -26,7 +25,7 @@ const Toolbar = createFactory(require("./toolbar"));
|
|||
const { div } = DOM;
|
||||
const MediaQueryList = window.matchMedia("(min-width: 700px)");
|
||||
|
||||
/*
|
||||
/**
|
||||
* Monitor panel component
|
||||
* The main panel for displaying various network request information
|
||||
*/
|
||||
|
@ -34,11 +33,11 @@ const MonitorPanel = createClass({
|
|||
displayName: "MonitorPanel",
|
||||
|
||||
propTypes: {
|
||||
connector: PropTypes.object.isRequired,
|
||||
isEmpty: PropTypes.bool.isRequired,
|
||||
networkDetailsOpen: PropTypes.bool.isRequired,
|
||||
openNetworkDetails: PropTypes.func.isRequired,
|
||||
request: PropTypes.object,
|
||||
// Service to enable the source map feature.
|
||||
sourceMapService: PropTypes.object,
|
||||
openLink: PropTypes.func,
|
||||
updateRequest: PropTypes.func.isRequired,
|
||||
|
@ -72,7 +71,7 @@ const MonitorPanel = createClass({
|
|||
requestHeaders,
|
||||
requestHeadersFromUploadStream,
|
||||
requestPostData,
|
||||
getLongString,
|
||||
this.props.connector.getLongString,
|
||||
).then((newFormDataSections) => {
|
||||
updateRequest(
|
||||
request.id,
|
||||
|
@ -106,6 +105,7 @@ const MonitorPanel = createClass({
|
|||
|
||||
render() {
|
||||
let {
|
||||
connector,
|
||||
isEmpty,
|
||||
networkDetailsOpen,
|
||||
sourceMapService,
|
||||
|
@ -126,9 +126,10 @@ const MonitorPanel = createClass({
|
|||
minSize: "50px",
|
||||
maxSize: "80%",
|
||||
splitterSize: "1px",
|
||||
startPanel: RequestList({ isEmpty }),
|
||||
startPanel: RequestList({ isEmpty, connector }),
|
||||
endPanel: networkDetailsOpen && NetworkDetailsPanel({
|
||||
ref: "endPanel",
|
||||
connector,
|
||||
sourceMapService,
|
||||
openLink,
|
||||
}),
|
||||
|
|
|
@ -19,10 +19,11 @@ const TabboxPanel = createFactory(require("./tabbox-panel"));
|
|||
|
||||
const { div } = DOM;
|
||||
|
||||
/*
|
||||
/**
|
||||
* Network details panel component
|
||||
*/
|
||||
function NetworkDetailsPanel({
|
||||
connector,
|
||||
activeTabId,
|
||||
cloneSelectedRequest,
|
||||
request,
|
||||
|
@ -40,12 +41,14 @@ function NetworkDetailsPanel({
|
|||
TabboxPanel({
|
||||
activeTabId,
|
||||
cloneSelectedRequest,
|
||||
connector,
|
||||
openLink,
|
||||
request,
|
||||
selectTab,
|
||||
sourceMapService,
|
||||
openLink,
|
||||
}) :
|
||||
CustomRequestPanel({
|
||||
connector,
|
||||
request,
|
||||
})
|
||||
)
|
||||
|
@ -55,12 +58,12 @@ function NetworkDetailsPanel({
|
|||
NetworkDetailsPanel.displayName = "NetworkDetailsPanel";
|
||||
|
||||
NetworkDetailsPanel.propTypes = {
|
||||
connector: PropTypes.object.isRequired,
|
||||
activeTabId: PropTypes.string,
|
||||
cloneSelectedRequest: PropTypes.func.isRequired,
|
||||
open: PropTypes.bool,
|
||||
request: PropTypes.object,
|
||||
selectTab: PropTypes.func.isRequired,
|
||||
// Service to enable the source map feature.
|
||||
sourceMapService: PropTypes.object,
|
||||
openLink: PropTypes.func,
|
||||
};
|
||||
|
|
|
@ -35,6 +35,7 @@ const RequestListContent = createClass({
|
|||
displayName: "RequestListContent",
|
||||
|
||||
propTypes: {
|
||||
connector: PropTypes.object.isRequired,
|
||||
columns: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
displayedRequests: PropTypes.object.isRequired,
|
||||
|
@ -51,10 +52,12 @@ const RequestListContent = createClass({
|
|||
},
|
||||
|
||||
componentWillMount() {
|
||||
const { dispatch } = this.props;
|
||||
const { dispatch, connector } = this.props;
|
||||
this.contextMenu = new RequestListContextMenu({
|
||||
cloneSelectedRequest: () => dispatch(Actions.cloneSelectedRequest()),
|
||||
openStatistics: (open) => dispatch(Actions.openStatistics(open)),
|
||||
getTabTarget: connector.getTabTarget,
|
||||
getLongString: connector.getLongString,
|
||||
openStatistics: (open) => dispatch(Actions.openStatistics(connector, open)),
|
||||
});
|
||||
this.tooltip = new HTMLTooltip(window.parent.document, { type: "arrow" });
|
||||
},
|
||||
|
@ -156,8 +159,9 @@ const RequestListContent = createClass({
|
|||
return false;
|
||||
}
|
||||
|
||||
let { connector } = this.props;
|
||||
if (requestItem.responseContent && target.closest(".requests-list-icon")) {
|
||||
return setTooltipImageContent(tooltip, itemEl, requestItem);
|
||||
return setTooltipImageContent(connector, tooltip, itemEl, requestItem);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -12,7 +12,6 @@ const {
|
|||
} = require("devtools/client/shared/vendor/react");
|
||||
const { connect } = require("devtools/client/shared/vendor/react-redux");
|
||||
const Actions = require("../actions/index");
|
||||
const { triggerActivity } = require("../connector/index");
|
||||
const { ACTIVITY_TYPE } = require("../constants");
|
||||
const { L10N } = require("../utils/l10n");
|
||||
const { getPerformanceAnalysisURL } = require("../utils/mdn-utils");
|
||||
|
@ -37,6 +36,7 @@ const RequestListEmptyNotice = createClass({
|
|||
displayName: "RequestListEmptyNotice",
|
||||
|
||||
propTypes: {
|
||||
connector: PropTypes.object.isRequired,
|
||||
onReloadClick: PropTypes.func.isRequired,
|
||||
onPerfClick: PropTypes.func.isRequired,
|
||||
},
|
||||
|
@ -75,8 +75,9 @@ const RequestListEmptyNotice = createClass({
|
|||
|
||||
module.exports = connect(
|
||||
undefined,
|
||||
dispatch => ({
|
||||
onPerfClick: () => dispatch(Actions.openStatistics(true)),
|
||||
onReloadClick: () => triggerActivity(ACTIVITY_TYPE.RELOAD.WITH_CACHE_DEFAULT),
|
||||
(dispatch, props) => ({
|
||||
onPerfClick: () => dispatch(Actions.openStatistics(props.connector, true)),
|
||||
onReloadClick: () => props.connector.triggerActivity(
|
||||
ACTIVITY_TYPE.RELOAD.WITH_CACHE_DEFAULT),
|
||||
})
|
||||
)(RequestListEmptyNotice);
|
||||
|
|
|
@ -21,12 +21,15 @@ const { div } = DOM;
|
|||
/**
|
||||
* Request panel component
|
||||
*/
|
||||
function RequestList({ isEmpty }) {
|
||||
function RequestList({
|
||||
connector,
|
||||
isEmpty,
|
||||
}) {
|
||||
return (
|
||||
div({ className: "request-list-container" },
|
||||
RequestListHeader(),
|
||||
isEmpty ? RequestListEmptyNotice() : RequestListContent(),
|
||||
StatusBar(),
|
||||
isEmpty ? RequestListEmptyNotice({connector}) : RequestListContent({connector}),
|
||||
StatusBar({connector}),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -34,6 +37,7 @@ function RequestList({ isEmpty }) {
|
|||
RequestList.displayName = "RequestList";
|
||||
|
||||
RequestList.propTypes = {
|
||||
connector: PropTypes.object.isRequired,
|
||||
isEmpty: PropTypes.bool.isRequired,
|
||||
};
|
||||
|
||||
|
|
|
@ -9,14 +9,18 @@ const {
|
|||
DOM,
|
||||
PropTypes,
|
||||
} = require("devtools/client/shared/vendor/react");
|
||||
const { viewSourceInDebugger } = require("../connector/index");
|
||||
|
||||
const { div } = DOM;
|
||||
|
||||
// Components
|
||||
const StackTrace = createFactory(require("devtools/client/shared/components/StackTrace"));
|
||||
|
||||
/**
|
||||
* This component represents a side panel responsible for
|
||||
* rendering stack-trace info for selected request.
|
||||
*/
|
||||
function StackTracePanel({
|
||||
connector,
|
||||
openLink,
|
||||
request,
|
||||
sourceMapService,
|
||||
|
@ -27,7 +31,9 @@ function StackTracePanel({
|
|||
div({ className: "panel-container" },
|
||||
StackTrace({
|
||||
stacktrace,
|
||||
onViewSourceInDebugger: ({ url, line }) => viewSourceInDebugger(url, line),
|
||||
onViewSourceInDebugger: ({ url, line }) => {
|
||||
return connector.viewSourceInDebugger(url, line);
|
||||
},
|
||||
sourceMapService,
|
||||
openLink,
|
||||
}),
|
||||
|
@ -38,8 +44,8 @@ function StackTracePanel({
|
|||
StackTracePanel.displayName = "StackTracePanel";
|
||||
|
||||
StackTracePanel.propTypes = {
|
||||
connector: PropTypes.object.isRequired,
|
||||
request: PropTypes.object.isRequired,
|
||||
// Service to enable the source map feature.
|
||||
sourceMapService: PropTypes.object,
|
||||
openLink: PropTypes.func,
|
||||
};
|
||||
|
|
|
@ -44,6 +44,7 @@ const StatisticsPanel = createClass({
|
|||
displayName: "StatisticsPanel",
|
||||
|
||||
propTypes: {
|
||||
connector: PropTypes.object.isRequired,
|
||||
closeStatistics: PropTypes.func.isRequired,
|
||||
enableRequestFilterTypeOnly: PropTypes.func.isRequired,
|
||||
requests: PropTypes.object,
|
||||
|
@ -302,8 +303,8 @@ module.exports = connect(
|
|||
(state) => ({
|
||||
requests: state.requests.requests.valueSeq(),
|
||||
}),
|
||||
(dispatch) => ({
|
||||
closeStatistics: () => dispatch(Actions.openStatistics(false)),
|
||||
(dispatch, props) => ({
|
||||
closeStatistics: () => dispatch(Actions.openStatistics(props.connector, false)),
|
||||
enableRequestFilterTypeOnly: (label) =>
|
||||
dispatch(Actions.enableRequestFilterTypeOnly(label)),
|
||||
})
|
||||
|
|
|
@ -88,6 +88,7 @@ function StatusBar({ summary, openStatistics, timingMarkers }) {
|
|||
StatusBar.displayName = "StatusBar";
|
||||
|
||||
StatusBar.propTypes = {
|
||||
connector: PropTypes.object.isRequired,
|
||||
openStatistics: PropTypes.func.isRequired,
|
||||
summary: PropTypes.object.isRequired,
|
||||
timingMarkers: PropTypes.object.isRequired,
|
||||
|
@ -102,7 +103,7 @@ module.exports = connect(
|
|||
load: getDisplayedTimingMarker(state, "firstDocumentLoadTimestamp"),
|
||||
},
|
||||
}),
|
||||
(dispatch) => ({
|
||||
openStatistics: () => dispatch(Actions.openStatistics(true)),
|
||||
(dispatch, props) => ({
|
||||
openStatistics: () => dispatch(Actions.openStatistics(props.connector, true)),
|
||||
}),
|
||||
)(StatusBar);
|
||||
|
|
|
@ -31,17 +31,18 @@ const SECURITY_TITLE = L10N.getStr("netmonitor.tab.security");
|
|||
const STACK_TRACE_TITLE = L10N.getStr("netmonitor.tab.stackTrace");
|
||||
const TIMINGS_TITLE = L10N.getStr("netmonitor.tab.timings");
|
||||
|
||||
/*
|
||||
/**
|
||||
* Tabbox panel component
|
||||
* Display the network request details
|
||||
*/
|
||||
function TabboxPanel({
|
||||
activeTabId,
|
||||
cloneSelectedRequest = ()=>{},
|
||||
cloneSelectedRequest = () => {},
|
||||
connector,
|
||||
openLink,
|
||||
request,
|
||||
selectTab,
|
||||
sourceMapService,
|
||||
openLink,
|
||||
}) {
|
||||
if (!request) {
|
||||
return null;
|
||||
|
@ -90,7 +91,7 @@ function TabboxPanel({
|
|||
id: PANELS.STACK_TRACE,
|
||||
title: STACK_TRACE_TITLE,
|
||||
},
|
||||
StackTracePanel({ request, sourceMapService, openLink }),
|
||||
StackTracePanel({ request, sourceMapService, openLink, connector }),
|
||||
),
|
||||
request.securityState && request.securityState !== "insecure" &&
|
||||
TabPanel({
|
||||
|
@ -108,11 +109,11 @@ TabboxPanel.displayName = "TabboxPanel";
|
|||
TabboxPanel.propTypes = {
|
||||
activeTabId: PropTypes.string,
|
||||
cloneSelectedRequest: PropTypes.func,
|
||||
connector: PropTypes.object.isRequired,
|
||||
openLink: PropTypes.func,
|
||||
request: PropTypes.object,
|
||||
selectTab: PropTypes.func.isRequired,
|
||||
// Service to enable the source map feature.
|
||||
sourceMapService: PropTypes.object,
|
||||
openLink: PropTypes.func,
|
||||
};
|
||||
|
||||
module.exports = connect()(TabboxPanel);
|
||||
|
|
|
@ -35,6 +35,14 @@ class ChromeConnector {
|
|||
this.connector.disconnect();
|
||||
}
|
||||
|
||||
pause() {
|
||||
this.disconnect();
|
||||
}
|
||||
|
||||
resume() {
|
||||
this.setup();
|
||||
}
|
||||
|
||||
/**
|
||||
* currently all events are about "navigation" is not support on CDP
|
||||
*/
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
const Services = require("Services");
|
||||
const { TimelineFront } = require("devtools/shared/fronts/timeline");
|
||||
const { ACTIVITY_TYPE, EVENTS } = require("../constants");
|
||||
const { getDisplayedRequestById } = require("../selectors/index");
|
||||
const FirefoxDataProvider = require("./firefox-data-provider");
|
||||
|
||||
class FirefoxConnector {
|
||||
|
@ -21,7 +20,6 @@ class FirefoxConnector {
|
|||
this.sendHTTPRequest = this.sendHTTPRequest.bind(this);
|
||||
this.setPreferences = this.setPreferences.bind(this);
|
||||
this.triggerActivity = this.triggerActivity.bind(this);
|
||||
this.inspectRequest = this.inspectRequest.bind(this);
|
||||
this.getTabTarget = this.getTabTarget.bind(this);
|
||||
this.viewSourceInDebugger = this.viewSourceInDebugger.bind(this);
|
||||
|
||||
|
@ -43,12 +41,7 @@ class FirefoxConnector {
|
|||
actions: this.actions,
|
||||
});
|
||||
|
||||
this.tabTarget.on("will-navigate", this.willNavigate);
|
||||
this.tabTarget.on("close", this.disconnect);
|
||||
this.webConsoleClient.on("networkEvent",
|
||||
this.dataProvider.onNetworkEvent);
|
||||
this.webConsoleClient.on("networkEventUpdate",
|
||||
this.dataProvider.onNetworkEventUpdate);
|
||||
this.addListeners();
|
||||
|
||||
// Don't start up waiting for timeline markers if the server isn't
|
||||
// recent enough to emit the markers we're interested in.
|
||||
|
@ -71,16 +64,38 @@ class FirefoxConnector {
|
|||
await this.timelineFront.destroy();
|
||||
}
|
||||
|
||||
this.tabTarget.off("will-navigate");
|
||||
this.tabTarget.off("close");
|
||||
this.removeListeners();
|
||||
|
||||
this.tabTarget = null;
|
||||
this.webConsoleClient.off("networkEvent");
|
||||
this.webConsoleClient.off("networkEventUpdate");
|
||||
this.webConsoleClient = null;
|
||||
this.timelineFront = null;
|
||||
this.dataProvider = null;
|
||||
}
|
||||
|
||||
pause() {
|
||||
this.removeListeners();
|
||||
}
|
||||
|
||||
resume() {
|
||||
this.addListeners();
|
||||
}
|
||||
|
||||
addListeners() {
|
||||
this.tabTarget.on("will-navigate", this.willNavigate);
|
||||
this.tabTarget.on("close", this.disconnect);
|
||||
this.webConsoleClient.on("networkEvent",
|
||||
this.dataProvider.onNetworkEvent);
|
||||
this.webConsoleClient.on("networkEventUpdate",
|
||||
this.dataProvider.onNetworkEventUpdate);
|
||||
}
|
||||
|
||||
removeListeners() {
|
||||
this.tabTarget.off("will-navigate");
|
||||
this.tabTarget.off("close");
|
||||
this.webConsoleClient.off("networkEvent");
|
||||
this.webConsoleClient.off("networkEventUpdate");
|
||||
}
|
||||
|
||||
willNavigate() {
|
||||
if (!Services.prefs.getBoolPref("devtools.netmonitor.persistlog")) {
|
||||
this.actions.batchReset();
|
||||
|
@ -214,42 +229,6 @@ class FirefoxConnector {
|
|||
return Promise.reject(new Error("Invalid activity type"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the specified request in the waterfall and opens the details view.
|
||||
*
|
||||
* @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(this.getState(), requestId);
|
||||
if (!request) {
|
||||
// Reset filters so that the request is visible.
|
||||
this.actions.toggleRequestFilterType("all");
|
||||
request = getDisplayedRequestById(this.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);
|
||||
this.actions.selectRequest(request.id);
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
|
||||
inspector();
|
||||
|
||||
if (!request) {
|
||||
window.on(EVENTS.REQUEST_ADDED, inspector);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the network information packet from actor server
|
||||
*
|
||||
|
|
|
@ -3,83 +3,101 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
let connector = {};
|
||||
|
||||
function onConnect(connection, actions, getState) {
|
||||
if (!connection || !connection.tab) {
|
||||
return;
|
||||
/**
|
||||
* Generic connector wrapper object that is responsible for
|
||||
* instantiating specific connector implementation according
|
||||
* to the client type.
|
||||
*/
|
||||
class Connector {
|
||||
constructor() {
|
||||
this.connector = null;
|
||||
|
||||
// Bind public API
|
||||
this.connect = this.connect.bind(this);
|
||||
this.disconnect = this.disconnect.bind(this);
|
||||
this.connectChrome = this.connectChrome.bind(this);
|
||||
this.connectFirefox = this.connectFirefox.bind(this);
|
||||
this.getLongString = this.getLongString.bind(this);
|
||||
this.getNetworkRequest = this.getNetworkRequest.bind(this);
|
||||
this.getTabTarget = this.getTabTarget.bind(this);
|
||||
this.sendHTTPRequest = this.sendHTTPRequest.bind(this);
|
||||
this.setPreferences = this.setPreferences.bind(this);
|
||||
this.triggerActivity = this.triggerActivity.bind(this);
|
||||
this.viewSourceInDebugger = this.viewSourceInDebugger.bind(this);
|
||||
}
|
||||
|
||||
let { clientType } = connection.tab;
|
||||
switch (clientType) {
|
||||
case "chrome":
|
||||
onChromeConnect(connection, actions, getState);
|
||||
break;
|
||||
case "firefox":
|
||||
onFirefoxConnect(connection, actions, getState);
|
||||
break;
|
||||
default:
|
||||
throw Error(`Unknown client type - ${clientType}`);
|
||||
// Connect/Disconnect API
|
||||
|
||||
connect(connection, actions, getState) {
|
||||
if (!connection || !connection.tab) {
|
||||
return;
|
||||
}
|
||||
|
||||
let { clientType } = connection.tab;
|
||||
switch (clientType) {
|
||||
case "chrome":
|
||||
this.connectChrome(connection, actions, getState);
|
||||
break;
|
||||
case "firefox":
|
||||
this.connectFirefox(connection, actions, getState);
|
||||
break;
|
||||
default:
|
||||
throw Error(`Unknown client type - ${clientType}`);
|
||||
}
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
this.connector && this.connector.disconnect();
|
||||
}
|
||||
|
||||
connectChrome(connection, actions, getState) {
|
||||
this.connector = require("./chrome-connector");
|
||||
this.connector.connect(connection, actions, getState);
|
||||
}
|
||||
|
||||
connectFirefox(connection, actions, getState) {
|
||||
this.connector = require("./firefox-connector");
|
||||
this.connector.connect(connection, actions, getState);
|
||||
}
|
||||
|
||||
pause() {
|
||||
this.connector.pause();
|
||||
}
|
||||
|
||||
resume() {
|
||||
this.connector.resume();
|
||||
}
|
||||
|
||||
// Public API
|
||||
|
||||
getLongString() {
|
||||
return this.connector.getLongString(...arguments);
|
||||
}
|
||||
|
||||
getNetworkRequest() {
|
||||
return this.connector.getNetworkRequest(...arguments);
|
||||
}
|
||||
|
||||
getTabTarget() {
|
||||
return this.connector.getTabTarget();
|
||||
}
|
||||
|
||||
sendHTTPRequest() {
|
||||
return this.connector.sendHTTPRequest(...arguments);
|
||||
}
|
||||
|
||||
setPreferences() {
|
||||
return this.connector.setPreferences(...arguments);
|
||||
}
|
||||
|
||||
triggerActivity() {
|
||||
return this.connector.triggerActivity(...arguments);
|
||||
}
|
||||
|
||||
viewSourceInDebugger() {
|
||||
return this.connector.viewSourceInDebugger(...arguments);
|
||||
}
|
||||
}
|
||||
|
||||
function onDisconnect() {
|
||||
connector && connector.disconnect();
|
||||
}
|
||||
|
||||
function onChromeConnect(connection, actions, getState) {
|
||||
connector = require("./chrome-connector");
|
||||
connector.connect(connection, actions, getState);
|
||||
}
|
||||
|
||||
function onFirefoxConnect(connection, actions, getState) {
|
||||
connector = require("./firefox-connector");
|
||||
connector.connect(connection, actions, getState);
|
||||
}
|
||||
|
||||
function inspectRequest() {
|
||||
return connector.inspectRequest(...arguments);
|
||||
}
|
||||
|
||||
function getLongString() {
|
||||
return connector.getLongString(...arguments);
|
||||
}
|
||||
|
||||
function getNetworkRequest() {
|
||||
return connector.getNetworkRequest(...arguments);
|
||||
}
|
||||
|
||||
function getTabTarget() {
|
||||
return connector.getTabTarget();
|
||||
}
|
||||
|
||||
function sendHTTPRequest() {
|
||||
return connector.sendHTTPRequest(...arguments);
|
||||
}
|
||||
|
||||
function setPreferences() {
|
||||
return connector.setPreferences(...arguments);
|
||||
}
|
||||
|
||||
function triggerActivity() {
|
||||
return connector.triggerActivity(...arguments);
|
||||
}
|
||||
|
||||
function viewSourceInDebugger() {
|
||||
return connector.viewSourceInDebugger(...arguments);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
onConnect,
|
||||
onChromeConnect,
|
||||
onFirefoxConnect,
|
||||
onDisconnect,
|
||||
getLongString,
|
||||
getNetworkRequest,
|
||||
getTabTarget,
|
||||
inspectRequest,
|
||||
sendHTTPRequest,
|
||||
setPreferences,
|
||||
triggerActivity,
|
||||
viewSourceInDebugger,
|
||||
};
|
||||
module.exports.Connector = Connector;
|
||||
|
|
|
@ -16,10 +16,9 @@ function* throttleUploadTest(actuallyThrottle) {
|
|||
|
||||
info("Starting test... (actuallyThrottle = " + actuallyThrottle + ")");
|
||||
|
||||
let { store, windowRequire } = monitor.panelWin;
|
||||
let { connector, store, windowRequire } = monitor.panelWin;
|
||||
let Actions = windowRequire("devtools/client/netmonitor/src/actions/index");
|
||||
let { setPreferences } =
|
||||
windowRequire("devtools/client/netmonitor/src/connector/index");
|
||||
let setPreferences = () => connector.setPreferences;
|
||||
let RequestListContextMenu = windowRequire(
|
||||
"devtools/client/netmonitor/src/request-list-context-menu");
|
||||
|
||||
|
|
|
@ -8,15 +8,32 @@ const {
|
|||
TOGGLE_RECORDING,
|
||||
} = require("../constants");
|
||||
|
||||
const {
|
||||
getRecordingState,
|
||||
} = require("../selectors/index");
|
||||
|
||||
/**
|
||||
* Start/stop HTTP traffic recording.
|
||||
*
|
||||
* The UI state of the toolbar toggle button is stored in UI
|
||||
* reducer and the backend connection is managed here in the
|
||||
* middleware.
|
||||
*/
|
||||
function recordingMiddleware(store) {
|
||||
return next => action => {
|
||||
function recordingMiddleware(connector) {
|
||||
return store => next => action => {
|
||||
const res = next(action);
|
||||
|
||||
// Pause/resume HTTP monitoring according to
|
||||
// the user action.
|
||||
if (action.type === TOGGLE_RECORDING) {
|
||||
// TODO connect/disconnect the backend.
|
||||
let recording = getRecordingState(store.getState());
|
||||
if (recording) {
|
||||
connector.resume();
|
||||
} else {
|
||||
connector.pause();
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -10,10 +10,6 @@ const { gDevTools } = require("devtools/client/framework/devtools");
|
|||
const { saveAs } = require("devtools/client/shared/file-saver");
|
||||
const { copyString } = require("devtools/shared/platform/clipboard");
|
||||
const { HarExporter } = require("./har/har-exporter");
|
||||
const {
|
||||
getLongString,
|
||||
getTabTarget,
|
||||
} = require("./connector/index");
|
||||
const {
|
||||
getSelectedRequest,
|
||||
getSortedRequests,
|
||||
|
@ -28,9 +24,13 @@ const {
|
|||
|
||||
function RequestListContextMenu({
|
||||
cloneSelectedRequest,
|
||||
getLongString,
|
||||
getTabTarget,
|
||||
openStatistics,
|
||||
}) {
|
||||
this.cloneSelectedRequest = cloneSelectedRequest;
|
||||
this.getLongString = getLongString;
|
||||
this.getTabTarget = getTabTarget;
|
||||
this.openStatistics = openStatistics;
|
||||
}
|
||||
|
||||
|
@ -239,7 +239,7 @@ RequestListContextMenu.prototype = {
|
|||
* Opens selected item in the debugger
|
||||
*/
|
||||
openInDebugger() {
|
||||
let toolbox = gDevTools.getToolbox(getTabTarget());
|
||||
let toolbox = gDevTools.getToolbox(this.getTabTarget());
|
||||
toolbox.viewSourceInDebugger(this.selectedRequest.url, 0);
|
||||
},
|
||||
|
||||
|
@ -247,7 +247,7 @@ RequestListContextMenu.prototype = {
|
|||
* Opens selected item in the style editor
|
||||
*/
|
||||
openInStyleEditor() {
|
||||
let toolbox = gDevTools.getToolbox(getTabTarget());
|
||||
let toolbox = gDevTools.getToolbox(this.getTabTarget());
|
||||
toolbox.viewSourceInStyleEditor(this.selectedRequest.url, 0);
|
||||
},
|
||||
|
||||
|
@ -387,11 +387,11 @@ RequestListContextMenu.prototype = {
|
|||
},
|
||||
|
||||
getDefaultHarOptions() {
|
||||
let form = getTabTarget().form;
|
||||
let form = this.getTabTarget().form;
|
||||
let title = form.title || form.url;
|
||||
|
||||
return {
|
||||
getString: getLongString,
|
||||
getString: this.getLongString,
|
||||
items: this.sortedRequests,
|
||||
title: title
|
||||
};
|
||||
|
|
|
@ -8,19 +8,18 @@ const {
|
|||
setImageTooltip,
|
||||
getImageDimensions,
|
||||
} = require("devtools/client/shared/widgets/tooltip/ImageTooltipHelper");
|
||||
const { getLongString } = require("./connector/index");
|
||||
const { formDataURI } = require("./utils/request-utils");
|
||||
|
||||
const REQUESTS_TOOLTIP_IMAGE_MAX_DIM = 400; // px
|
||||
|
||||
async function setTooltipImageContent(tooltip, itemEl, requestItem) {
|
||||
async function setTooltipImageContent(connector, tooltip, itemEl, requestItem) {
|
||||
let { mimeType, text, encoding } = requestItem.responseContent.content;
|
||||
|
||||
if (!mimeType || !mimeType.includes("image/")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let string = await getLongString(text);
|
||||
let string = await connector.getLongString(text);
|
||||
let src = formDataURI(mimeType, encoding, string);
|
||||
let maxDim = REQUESTS_TOOLTIP_IMAGE_MAX_DIM;
|
||||
let { naturalWidth, naturalHeight } = await getImageDimensions(tooltip.doc, src);
|
||||
|
|
|
@ -6,9 +6,14 @@
|
|||
|
||||
const Services = require("Services");
|
||||
const { applyMiddleware, createStore } = require("devtools/client/shared/vendor/redux");
|
||||
|
||||
// Middleware
|
||||
const batching = require("../middleware/batching");
|
||||
const prefs = require("../middleware/prefs");
|
||||
const thunk = require("../middleware/thunk");
|
||||
const recording = require("../middleware/recording");
|
||||
|
||||
// Reducers
|
||||
const rootReducer = require("../reducers/index");
|
||||
const { FilterTypes, Filters } = require("../reducers/filters");
|
||||
const { Requests } = require("../reducers/requests");
|
||||
|
@ -16,21 +21,40 @@ const { Sort } = require("../reducers/sort");
|
|||
const { TimingMarkers } = require("../reducers/timing-markers");
|
||||
const { UI, Columns } = require("../reducers/ui");
|
||||
|
||||
function configureStore() {
|
||||
const getPref = (pref) => {
|
||||
try {
|
||||
return JSON.parse(Services.prefs.getCharPref(pref));
|
||||
} catch (_) {
|
||||
return [];
|
||||
}
|
||||
/**
|
||||
* Configure state and middleware for the Network monitor tool.
|
||||
*/
|
||||
function configureStore(connector) {
|
||||
// Prepare initial state.
|
||||
const initialState = {
|
||||
filters: new Filters({
|
||||
requestFilterTypes: getFilterState()
|
||||
}),
|
||||
requests: new Requests(),
|
||||
sort: new Sort(),
|
||||
timingMarkers: new TimingMarkers(),
|
||||
ui: new UI({
|
||||
columns: getColumnState()
|
||||
}),
|
||||
};
|
||||
|
||||
let activeFilters = {};
|
||||
let filters = getPref("devtools.netmonitor.filters");
|
||||
filters.forEach((filter) => {
|
||||
activeFilters[filter] = true;
|
||||
});
|
||||
// Prepare middleware.
|
||||
let middleware = applyMiddleware(
|
||||
thunk,
|
||||
prefs,
|
||||
batching,
|
||||
recording(connector)
|
||||
);
|
||||
|
||||
return createStore(rootReducer, initialState, middleware);
|
||||
}
|
||||
|
||||
// Helpers
|
||||
|
||||
/**
|
||||
* Get column state from preferences.
|
||||
*/
|
||||
function getColumnState() {
|
||||
let columns = new Columns();
|
||||
let visibleColumns = getPref("devtools.netmonitor.visibleColumns");
|
||||
|
||||
|
@ -40,19 +64,27 @@ function configureStore() {
|
|||
});
|
||||
}
|
||||
|
||||
const initialState = {
|
||||
filters: new Filters({
|
||||
requestFilterTypes: new FilterTypes(activeFilters)
|
||||
}),
|
||||
requests: new Requests(),
|
||||
sort: new Sort(),
|
||||
timingMarkers: new TimingMarkers(),
|
||||
ui: new UI({
|
||||
columns,
|
||||
}),
|
||||
};
|
||||
return columns;
|
||||
}
|
||||
|
||||
return createStore(rootReducer, initialState, applyMiddleware(thunk, prefs, batching));
|
||||
/**
|
||||
* Get filter state from preferences.
|
||||
*/
|
||||
function getFilterState() {
|
||||
let activeFilters = {};
|
||||
let filters = getPref("devtools.netmonitor.filters");
|
||||
filters.forEach((filter) => {
|
||||
activeFilters[filter] = true;
|
||||
});
|
||||
return new FilterTypes(activeFilters);
|
||||
}
|
||||
|
||||
function getPref(pref) {
|
||||
try {
|
||||
return JSON.parse(Services.prefs.getCharPref(pref));
|
||||
} catch (_) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
exports.configureStore = configureStore;
|
||||
|
|
|
@ -139,9 +139,7 @@ NewConsoleOutputWrapper.prototype = {
|
|||
),
|
||||
openNetworkPanel: (requestId) => {
|
||||
return this.toolbox.selectTool("netmonitor").then((panel) => {
|
||||
let { inspectRequest } = panel.panelWin.windowRequire(
|
||||
"devtools/client/netmonitor/src/connector/index");
|
||||
return inspectRequest(requestId);
|
||||
return panel.panelWin.Netmonitor.inspectRequest(requestId);
|
||||
});
|
||||
},
|
||||
sourceMapService: this.toolbox ? this.toolbox.sourceMapURLService : null,
|
||||
|
|
|
@ -1849,14 +1849,11 @@ WebConsoleFrame.prototype = {
|
|||
openNetworkPanel: function (requestId) {
|
||||
let toolbox = gDevTools.getToolbox(this.owner.target);
|
||||
// The browser console doesn't have a toolbox.
|
||||
if (!toolbox) {
|
||||
return;
|
||||
if (toolbox) {
|
||||
return toolbox.selectTool("netmonitor").then(panel => {
|
||||
return panel.panelWin.Netmonitor.inspectRequest(requestId);
|
||||
});
|
||||
}
|
||||
return toolbox.selectTool("netmonitor").then(panel => {
|
||||
let { inspectRequest } = panel.panelWin.windowRequire(
|
||||
"devtools/client/netmonitor/src/connector/index");
|
||||
return inspectRequest(requestId);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
Загрузка…
Ссылка в новой задаче