--- a/devtools/client/netmonitor/actions/filters.js
+++ b/devtools/client/netmonitor/actions/filters.js
@@ -1,17 +1,17 @@
/* 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 {
+ ENABLE_REQUEST_FILTER_TYPE_ONLY,
TOGGLE_REQUEST_FILTER_TYPE,
- ENABLE_REQUEST_FILTER_TYPE_ONLY,
SET_REQUEST_FILTER_TEXT,
} = require("../constants");
/**
* Toggle an existing filter type state.
* If type 'all' is specified, all the other filter types are set to false.
* Available filter types are defined in filters reducer.
*
@@ -35,24 +35,24 @@ function toggleRequestFilterType(filter)
function enableRequestFilterTypeOnly(filter) {
return {
type: ENABLE_REQUEST_FILTER_TYPE_ONLY,
filter,
};
}
/**
- * Set filter text.
+ * Set filter text in toolbar.
*
* @param {string} text - A filter text is going to be set
*/
function setRequestFilterText(text) {
return {
type: SET_REQUEST_FILTER_TEXT,
text,
};
}
module.exports = {
+ enableRequestFilterTypeOnly,
toggleRequestFilterType,
- enableRequestFilterTypeOnly,
setRequestFilterText,
};
--- a/devtools/client/netmonitor/components/search-box.js
+++ b/devtools/client/netmonitor/components/search-box.js
@@ -3,23 +3,21 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { connect } = require("devtools/client/shared/vendor/react-redux");
const SearchBox = require("devtools/client/shared/components/search-box");
const { L10N } = require("../l10n");
const Actions = require("../actions/index");
-const { FREETEXT_FILTER_SEARCH_DELAY } = require("../constants");
+const { FILTER_SEARCH_DELAY } = require("../constants");
module.exports = connect(
(state) => ({
- delay: FREETEXT_FILTER_SEARCH_DELAY,
+ delay: FILTER_SEARCH_DELAY,
keyShortcut: L10N.getStr("netmonitor.toolbar.filterFreetext.key"),
placeholder: L10N.getStr("netmonitor.toolbar.filterFreetext.label"),
type: "filter",
}),
(dispatch) => ({
- onChange: (url) => {
- dispatch(Actions.setRequestFilterText(url));
- },
+ onChange: (text) => dispatch(Actions.setRequestFilterText(text)),
})
)(SearchBox);
--- a/devtools/client/netmonitor/components/toolbar.js
+++ b/devtools/client/netmonitor/components/toolbar.js
@@ -5,17 +5,17 @@
"use strict";
const {
createFactory,
DOM,
} = require("devtools/client/shared/vendor/react");
const ClearButton = createFactory(require("./clear-button"));
const FilterButtons = createFactory(require("./filter-buttons"));
-const SearchBox = createFactory(require("./search-box"));
+const ToolbarSearchBox = createFactory(require("./search-box"));
const SummaryButton = createFactory(require("./summary-button"));
const ToggleButton = createFactory(require("./toggle-button"));
const { span } = DOM;
/*
* Network monitor toolbar component
* Toolbar contains a set of useful tools to control network requests
@@ -23,15 +23,15 @@ const { span } = DOM;
function Toolbar() {
return span({ className: "devtools-toolbar devtools-toolbar-container" },
span({ className: "devtools-toolbar-group" },
ClearButton(),
FilterButtons()
),
span({ className: "devtools-toolbar-group" },
SummaryButton(),
- SearchBox(),
+ ToolbarSearchBox(),
ToggleButton()
)
);
}
module.exports = Toolbar;
--- a/devtools/client/netmonitor/details-view.js
+++ b/devtools/client/netmonitor/details-view.js
@@ -1,48 +1,34 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* eslint-disable mozilla/reject-some-requires */
-/* globals window, dumpn, $, gNetwork */
+/* globals window, dumpn, $ */
"use strict";
const promise = require("promise");
const EventEmitter = require("devtools/shared/event-emitter");
-const { Heritage } = require("devtools/client/shared/widgets/view-helpers");
const { Task } = require("devtools/shared/task");
const { ToolSidebar } = require("devtools/client/framework/sidebar");
-const { VariablesView } = require("resource://devtools/client/shared/widgets/VariablesView.jsm");
const { EVENTS } = require("./events");
-const { L10N } = require("./l10n");
const { Filters } = require("./filter-predicates");
const { createFactory } = require("devtools/client/shared/vendor/react");
const ReactDOM = require("devtools/client/shared/vendor/react-dom");
const Provider = createFactory(require("devtools/client/shared/vendor/react-redux").Provider);
+const CookiesPanel = createFactory(require("./shared/components/cookies-panel"));
const HeadersPanel = createFactory(require("./shared/components/headers-panel"));
const ParamsPanel = createFactory(require("./shared/components/params-panel"));
const PreviewPanel = createFactory(require("./shared/components/preview-panel"));
const ResponsePanel = createFactory(require("./shared/components/response-panel"));
const SecurityPanel = createFactory(require("./shared/components/security-panel"));
const TimingsPanel = createFactory(require("./shared/components/timings-panel"));
-const GENERIC_VARIABLES_VIEW_SETTINGS = {
- lazyEmpty: true,
- // ms
- lazyEmptyDelay: 10,
- searchEnabled: true,
- editableValueTooltip: "",
- editableNameTooltip: "",
- preventDisableOnChange: true,
- preventDescriptorModifiers: true,
- eval: () => {}
-};
-
/**
* Functions handling the requests details view.
*/
function DetailsView() {
dumpn("DetailsView was instantiated");
// The ToolSidebar requires the panel object to be able to emit events.
EventEmitter.decorate(this);
@@ -65,16 +51,23 @@ DetailsView.prototype = {
},
/**
* Initialization function, called when the network monitor is started.
*/
initialize: function (store) {
dumpn("Initializing the DetailsView");
+ this._cookiesPanelNode = $("#react-cookies-tabpanel-hook");
+
+ ReactDOM.render(Provider(
+ { store },
+ CookiesPanel()
+ ), this._cookiesPanelNode);
+
this._headersPanelNode = $("#react-headers-tabpanel-hook");
ReactDOM.render(Provider(
{ store },
HeadersPanel()
), this._headersPanelNode);
this._paramsPanelNode = $("#react-params-tabpanel-hook");
@@ -112,36 +105,27 @@ DetailsView.prototype = {
TimingsPanel()
), this._timingsPanelNode);
this.widget = $("#event-details-pane");
this.sidebar = new ToolSidebar(this.widget, this, "netmonitor", {
disableTelemetry: true,
showAllTabsMenu: true
});
-
- this._cookies = new VariablesView($("#all-cookies"),
- Heritage.extend(GENERIC_VARIABLES_VIEW_SETTINGS, {
- emptyText: L10N.getStr("cookiesEmptyText"),
- searchPlaceholder: L10N.getStr("cookiesFilterText")
- }));
-
- this._requestCookies = L10N.getStr("requestCookies");
- this._responseCookies = L10N.getStr("responseCookies");
-
$("tabpanels", this.widget).addEventListener("select", this._onTabSelect);
},
/**
* Destruction function, called when the network monitor is closed.
*/
destroy: function () {
dumpn("Destroying the DetailsView");
+ ReactDOM.unmountComponentAtNode(this._cookiesPanelNode);
+ ReactDOM.unmountComponentAtNode(this._headersPanelNode);
ReactDOM.unmountComponentAtNode(this._paramsPanelNode);
- ReactDOM.unmountComponentAtNode(this._headersPanelNode);
ReactDOM.unmountComponentAtNode(this._previewPanelNode);
ReactDOM.unmountComponentAtNode(this._responsePanelNode);
ReactDOM.unmountComponentAtNode(this._securityPanelNode);
ReactDOM.unmountComponentAtNode(this._timingsPanelNode);
this.sidebar.destroy();
$("tabpanels", this.widget).removeEventListener("select",
this._onTabSelect);
},
@@ -172,18 +156,16 @@ DetailsView.prototype = {
// request has no security information.
if (!isHtml && this.widget.selectedPanel === $("#preview-tabpanel") ||
!hasSecurityInfo && this.widget.selectedPanel ===
$("#security-tabpanel")) {
this.widget.selectedIndex = 0;
}
- this._cookies.empty();
-
this._dataSrc = { src: data, populated: [] };
this._onTabSelect();
window.emit(EVENTS.NETWORKDETAILSVIEW_POPULATED);
return promise.resolve();
},
/**
@@ -206,24 +188,16 @@ DetailsView.prototype = {
// 997065 and 984687. As there's no way to stop the current task mark the
// tab dirty and refresh the panel once the current task finishes.
viewState.dirty[tab] = true;
viewState.latestData = src;
return;
}
Task.spawn(function* () {
- viewState.updating[tab] = true;
- switch (tab) {
- // "Cookies"
- case 1:
- yield view._setResponseCookies(src.responseCookies);
- yield view._setRequestCookies(src.requestCookies);
- break;
- }
viewState.updating[tab] = false;
}).then(() => {
if (tab == this.widget.selectedIndex) {
if (viewState.dirty[tab]) {
// The request information was updated while the task was running.
viewState.dirty[tab] = false;
view.populate(viewState.latestData);
} else {
@@ -234,83 +208,12 @@ DetailsView.prototype = {
} else if (viewState.dirty[tab]) {
// Tab is dirty but no longer selected. Don't refresh it now, it'll be
// done if the tab is shown again.
viewState.dirty[tab] = false;
}
}, e => console.error(e));
},
- /**
- * Sets the network request cookies shown in this view.
- *
- * @param object response
- * The message received from the server.
- * @return object
- * A promise that is resolved when the request cookies are set.
- */
- _setRequestCookies: Task.async(function* (response) {
- if (response && response.cookies.length) {
- response.cookies.sort((a, b) => a.name > b.name);
- yield this._addCookies(this._requestCookies, response);
- }
- }),
-
- /**
- * Sets the network response cookies shown in this view.
- *
- * @param object response
- * The message received from the server.
- * @return object
- * A promise that is resolved when the response cookies are set.
- */
- _setResponseCookies: Task.async(function* (response) {
- if (response && response.cookies.length) {
- yield this._addCookies(this._responseCookies, response);
- }
- }),
-
- /**
- * Populates the cookies container in this view with the specified data.
- *
- * @param string name
- * The type of cookies to populate (request or response).
- * @param object response
- * The message received from the server.
- * @return object
- * Returns a promise that resolves upon the adding of cookies.
- */
- _addCookies: Task.async(function* (name, response) {
- let cookiesScope = this._cookies.addScope(name);
- cookiesScope.expanded = true;
-
- for (let cookie of response.cookies) {
- let cookieVar = cookiesScope.addItem(cookie.name, {}, {relaxed: true});
- let cookieValue = yield gNetwork.getString(cookie.value);
- cookieVar.setGrip(cookieValue);
-
- // By default the cookie name and value are shown. If this is the only
- // information available, then nothing else is to be displayed.
- let cookieProps = Object.keys(cookie);
- if (cookieProps.length == 2) {
- continue;
- }
-
- // Display any other information other than the cookie name and value
- // which may be available.
- let rawObject = Object.create(null);
- let otherProps = cookieProps.filter(e => e != "name" && e != "value");
- for (let prop of otherProps) {
- rawObject[prop] = cookie[prop];
- }
- cookieVar.populate(rawObject);
- cookieVar.twisty = true;
- cookieVar.expanded = true;
- }
- }),
-
_dataSrc: null,
- _cookies: null,
- _requestCookies: "",
- _responseCookies: ""
};
exports.DetailsView = DetailsView;
--- a/devtools/client/netmonitor/netmonitor.xul
+++ b/devtools/client/netmonitor/netmonitor.xul
@@ -124,17 +124,18 @@
<tabpanel id="headers-tabpanel"
class="tabpanel-content">
<html:div xmlns="http://www.w3.org/1999/xhtml"
id="react-headers-tabpanel-hook"/>
</tabpanel>
<tabpanel id="cookies-tabpanel"
class="tabpanel-content">
<vbox flex="1">
- <vbox id="all-cookies" flex="1"/>
+ <html:div xmlns="http://www.w3.org/1999/xhtml"
+ id="react-cookies-tabpanel-hook"/>
</vbox>
</tabpanel>
<tabpanel id="params-tabpanel"
class="tabpanel-content">
<html:div xmlns="http://www.w3.org/1999/xhtml"
id="react-params-tabpanel-hook"/>
</tabpanel>
<tabpanel id="response-tabpanel"
--- a/devtools/client/netmonitor/reducers/filters.js
+++ b/devtools/client/netmonitor/reducers/filters.js
@@ -1,18 +1,18 @@
/* 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 I = require("devtools/client/shared/vendor/immutable");
const {
+ ENABLE_REQUEST_FILTER_TYPE_ONLY,
TOGGLE_REQUEST_FILTER_TYPE,
- ENABLE_REQUEST_FILTER_TYPE_ONLY,
SET_REQUEST_FILTER_TEXT,
} = require("../constants");
const FilterTypes = I.Record({
all: false,
html: false,
css: false,
js: false,
@@ -62,22 +62,22 @@ function enableRequestFilterTypeOnly(sta
return state;
}
return new FilterTypes({ [filter]: true });
}
function filters(state = new Filters(), action) {
switch (action.type) {
+ case ENABLE_REQUEST_FILTER_TYPE_ONLY:
+ return state.set("requestFilterTypes",
+ enableRequestFilterTypeOnly(state.requestFilterTypes, action));
case TOGGLE_REQUEST_FILTER_TYPE:
return state.set("requestFilterTypes",
toggleRequestFilterType(state.requestFilterTypes, action));
- case ENABLE_REQUEST_FILTER_TYPE_ONLY:
- return state.set("requestFilterTypes",
- enableRequestFilterTypeOnly(state.requestFilterTypes, action));
case SET_REQUEST_FILTER_TEXT:
return state.set("requestFilterText", action.text);
default:
return state;
}
}
module.exports = filters;
--- a/devtools/client/netmonitor/requests-menu-view.js
+++ b/devtools/client/netmonitor/requests-menu-view.js
@@ -23,20 +23,20 @@ const { Prefs } = require("./prefs");
const {
fetchHeaders,
formDataURI,
getFormDataSections,
} = require("./request-utils");
const {
getActiveFilters,
- getSortedRequests,
getDisplayedRequests,
getRequestById,
getSelectedRequest,
+ getSortedRequests,
} = require("./selectors/index");
// ms
const RESIZE_REFRESH_RATE = 50;
// A smart store watcher to notify store changes as necessary
function storeWatcher(initialValue, reduceValue, onChange) {
let currentValue = initialValue;
@@ -219,34 +219,36 @@ RequestsMenuView.prototype = {
id,
{
startedMillis,
method,
url,
isXHR,
cause,
fromCache,
- fromServiceWorker
+ fromServiceWorker,
},
true
);
this.store.dispatch(action).then(() => window.emit(EVENTS.REQUEST_ADDED, action.id));
},
updateRequest: Task.async(function* (id, data) {
const action = Actions.updateRequest(id, data, true);
yield this.store.dispatch(action);
-
let {
+ responseContent,
+ responseCookies,
+ responseHeaders,
+ requestCookies,
requestHeaders,
requestPostData,
- responseContent,
- responseHeaders,
} = action.data;
+ let request = getRequestById(this.store.getState(), action.id);
if (requestHeaders && requestHeaders.headers && requestHeaders.headers.length) {
let headers = yield fetchHeaders(
requestHeaders, gNetwork.getString.bind(gNetwork));
if (headers) {
yield this.store.dispatch(Actions.updateRequest(
action.id,
{ requestHeaders: headers },
@@ -262,36 +264,33 @@ RequestsMenuView.prototype = {
yield this.store.dispatch(Actions.updateRequest(
action.id,
{ responseHeaders: headers },
true,
));
}
}
- if (responseContent && responseContent.content) {
- let request = getRequestById(this.store.getState(), action.id);
- if (request) {
- let { mimeType } = request;
- let { text, encoding } = responseContent.content;
- let response = yield gNetwork.getString(text);
- let payload = {};
+ if (request && responseContent && responseContent.content) {
+ let { mimeType } = request;
+ let { text, encoding } = responseContent.content;
+ let response = yield gNetwork.getString(text);
+ let payload = {};
- if (mimeType.includes("image/")) {
- payload.responseContentDataUri = formDataURI(mimeType, encoding, response);
- }
+ if (mimeType.includes("image/")) {
+ payload.responseContentDataUri = formDataURI(mimeType, encoding, response);
+ }
- responseContent.content.text = response;
- payload.responseContent = responseContent;
+ responseContent.content.text = response;
+ payload.responseContent = responseContent;
- yield this.store.dispatch(Actions.updateRequest(action.id, payload, true));
+ yield this.store.dispatch(Actions.updateRequest(action.id, payload, true));
- if (mimeType.includes("image/")) {
- window.emit(EVENTS.RESPONSE_IMAGE_THUMBNAIL_DISPLAYED);
- }
+ if (mimeType.includes("image/")) {
+ window.emit(EVENTS.RESPONSE_IMAGE_THUMBNAIL_DISPLAYED);
}
}
// Search the POST data upload stream for request headers and add
// them as a separate property, different from the classic headers.
if (requestPostData && requestPostData.postData) {
let { text } = requestPostData.postData;
let postData = yield gNetwork.getString(text);
@@ -301,16 +300,61 @@ RequestsMenuView.prototype = {
}, 0);
let payload = {};
requestPostData.postData.text = postData;
payload.requestPostData = Object.assign({}, requestPostData);
payload.requestHeadersFromUploadStream = { headers, headersSize };
yield this.store.dispatch(Actions.updateRequest(action.id, payload, true));
}
+
+ // Fetch request and response cookies long value.
+ // Actor does not provide full sized cookie value when the value is too long
+ // To display values correctly, we need fetch them in each request.
+ if (requestCookies) {
+ let reqCookies = [];
+ // request store cookies in requestCookies or requestCookies.cookies
+ let cookies = requestCookies.cookies ?
+ requestCookies.cookies : requestCookies;
+ // make sure cookies is iterable
+ if (typeof cookies[Symbol.iterator] === "function") {
+ for (let cookie of cookies) {
+ reqCookies.push(Object.assign({}, cookie, {
+ value: yield gNetwork.getString(cookie.value),
+ }));
+ }
+ if (reqCookies.length) {
+ yield this.store.dispatch(Actions.updateRequest(
+ action.id,
+ { requestCookies: reqCookies },
+ true));
+ }
+ }
+ }
+
+ if (responseCookies) {
+ let resCookies = [];
+ // response store cookies in responseCookies or responseCookies.cookies
+ let cookies = responseCookies.cookies ?
+ responseCookies.cookies : responseCookies;
+ // make sure cookies is iterable
+ if (typeof cookies[Symbol.iterator] === "function") {
+ for (let cookie of cookies) {
+ resCookies.push(Object.assign({}, cookie, {
+ value: yield gNetwork.getString(cookie.value),
+ }));
+ }
+ if (resCookies.length) {
+ yield this.store.dispatch(Actions.updateRequest(
+ action.id,
+ { responseCookies: resCookies },
+ true));
+ }
+ }
+ }
}),
/**
* Disable batched updates. Used by tests.
*/
set lazyUpdate(value) {
this.store.dispatch(Actions.batchEnable(value));
},
--- a/devtools/client/netmonitor/selectors/requests.js
+++ b/devtools/client/netmonitor/selectors/requests.js
@@ -92,24 +92,52 @@ const getDisplayedRequestsSummary = crea
}
);
const getSelectedRequest = createSelector(
state => state.requests,
({ selectedId, requests }) => selectedId ? requests.get(selectedId) : null
);
+const getSelectedRequestCookies = createSelector(
+ getSelectedRequest,
+ selectedRequest => {
+ // request store cookies in requestCookies or requestCookies.cookies
+ if (selectedRequest && selectedRequest.requestCookies) {
+ return selectedRequest.requestCookies.cookies ?
+ selectedRequest.requestCookies.cookies : selectedRequest.requestCookies;
+ }
+
+ return [];
+ }
+);
+
+const getSelectedResponseCookies = createSelector(
+ getSelectedRequest,
+ selectedRequest => {
+ // response store cookies in responseCookies or responseCookies.cookies
+ if (selectedRequest && selectedRequest.responseCookies) {
+ return selectedRequest.responseCookies.cookies ?
+ selectedRequest.responseCookies.cookies : selectedRequest.responseCookies;
+ }
+
+ return [];
+ }
+);
+
function getRequestById(state, id) {
return state.requests.requests.get(id);
}
function getDisplayedRequestById(state, id) {
return getDisplayedRequests(state).find(r => r.id === id);
}
module.exports = {
getDisplayedRequestById,
getDisplayedRequests,
getDisplayedRequestsSummary,
getRequestById,
getSelectedRequest,
+ getSelectedRequestCookies,
+ getSelectedResponseCookies,
getSortedRequests,
};
new file mode 100644
--- /dev/null
+++ b/devtools/client/netmonitor/shared/components/cookies-panel.js
@@ -0,0 +1,99 @@
+/* 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,
+ DOM,
+ PropTypes,
+} = require("devtools/client/shared/vendor/react");
+const { connect } = require("devtools/client/shared/vendor/react-redux");
+const { L10N } = require("../../l10n");
+const {
+ getSelectedRequestCookies,
+ getSelectedResponseCookies,
+} = require("../../selectors/index");
+
+// Component
+const PropertiesView = createFactory(require("./properties-view"));
+
+const { div } = DOM;
+
+const COOKIES_EMPTY_TEXT = L10N.getStr("cookiesEmptyText");
+const COOKIES_FILTER_TEXT = L10N.getStr("cookiesFilterText");
+const REQUEST_COOKIES = L10N.getStr("requestCookies");
+const RESPONSE_COOKIES = L10N.getStr("responseCookies");
+const SECTION_NAMES = [
+ RESPONSE_COOKIES,
+ REQUEST_COOKIES,
+];
+
+/*
+ * Cookies panel component
+ * This tab lists full details of any cookies sent with the request or response
+ */
+function CookiesPanel({
+ request,
+ response,
+}) {
+ if (!response.length && !request.length) {
+ return div({ className: "empty-notice" },
+ COOKIES_EMPTY_TEXT
+ );
+ }
+
+ let object = {};
+ if (response.length) {
+ object[RESPONSE_COOKIES] = getProperties(response);
+ }
+ if (request.length) {
+ object[REQUEST_COOKIES] = getProperties(request);
+ }
+
+ return (
+ PropertiesView({
+ object,
+ filterPlaceHolder: COOKIES_FILTER_TEXT,
+ sectionNames: SECTION_NAMES,
+ })
+ );
+}
+
+CookiesPanel.displayName = "CookiesPanel";
+
+CookiesPanel.propTypes = {
+ request: PropTypes.array.isRequired,
+ response: PropTypes.array.isRequired,
+};
+
+/**
+ * Mapping array to dict for TreeView usage.
+ * Since TreeView only support Object(dict) format.
+ *
+ * @param {Object[]} arr - key-value pair array like cookies or params
+ * @returns {Object}
+ */
+function getProperties(arr) {
+ return arr.reduce((map, obj) => {
+ // Generally cookies object contains only name and value properties and can
+ // be rendered as name: value pair.
+ // When there are more properties in cookies object such as extra or path,
+ // We will pass the object to display these extra information
+ if (Object.keys(obj).length > 2) {
+ map[obj.name] = Object.assign({}, obj);
+ delete map[obj.name].name;
+ } else {
+ map[obj.name] = obj.value;
+ }
+ return map;
+ }, {});
+}
+
+module.exports = connect(
+ state => ({
+ request: getSelectedRequestCookies(state),
+ response: getSelectedResponseCookies(state),
+ })
+)(CookiesPanel);
--- a/devtools/client/netmonitor/shared/components/moz.build
+++ b/devtools/client/netmonitor/shared/components/moz.build
@@ -1,13 +1,14 @@
# 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/.
DevToolsModules(
+ 'cookies-panel.js',
'editor.js',
'headers-panel.js',
'params-panel.js',
'preview-panel.js',
'properties-view.js',
'response-panel.js',
'security-panel.js',
'timings-panel.js',
--- a/devtools/client/themes/netmonitor.css
+++ b/devtools/client/themes/netmonitor.css
@@ -1267,30 +1267,32 @@
width: 100%;
height: 100%;
}
/*
* FIXME: normal html block element cannot fill outer XUL element
* This workaround should be removed after netmonitor is migrated to react
*/
+#react-cookies-tabpanel-hook,
#react-headers-tabpanel-hook,
#react-params-tabpanel-hook,
#react-preview-tabpanel-hook,
#react-response-tabpanel-hook,
#react-security-tabpanel-hook,
#react-timings-tabpanel-hook,
#network-statistics-charts,
#primed-cache-chart,
#empty-cache-chart {
display: -moz-box;
-moz-box-flex: 1;
}
/* For vbox */
+#react-cookies-tabpanel-hook,
#react-headers-tabpanel-hook,
#react-params-tabpanel-hook,
#react-preview-tabpanel-hook,
#react-response-tabpanel-hook,
#react-security-tabpanel-hook,
#react-timings-tabpanel-hook,
#primed-cache-chart,
#empty-cache-chart {