--- a/devtools/client/locales/en-US/netmonitor.properties
+++ b/devtools/client/locales/en-US/netmonitor.properties
@@ -490,16 +490,20 @@ netmonitor.toolbar.type=Type
netmonitor.toolbar.cookies=Cookies
# LOCALIZATION NOTE (netmonitor.toolbar.setCookies): This is the label displayed
# in the network table toolbar, above the "set cookies" column.
# Set-Cookie is a HTTP response header. This string is the plural form of it.
# See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie
netmonitor.toolbar.setCookies=Set-Cookies
+# LOCALIZATION NOTE (netmonitor.toolbar.cookies): This is the label displayed
+# in the network table toolbar, above the "scheme" column.
+netmonitor.toolbar.scheme=Scheme
+
# LOCALIZATION NOTE (netmonitor.toolbar.transferred): This is the label displayed
# in the network table toolbar, above the "transferred" column, which is the
# compressed / encoded size.
netmonitor.toolbar.transferred=Transferred
# LOCALIZATION NOTE (netmonitor.toolbar.contentSize): This is the label displayed
# in the network table toolbar, above the "size" column, which is the
# uncompressed / decoded size.
--- a/devtools/client/netmonitor/index.js
+++ b/devtools/client/netmonitor/index.js
@@ -19,17 +19,17 @@ const { configureStore } = require("./sr
require("./src/assets/styles/netmonitor.css");
EventEmitter.decorate(window);
pref("devtools.netmonitor.enabled", true);
pref("devtools.netmonitor.filters", "[\"all\"]");
pref("devtools.netmonitor.hiddenColumns",
- "[\"cookies\",\"protocol\",\"remoteip\",\"setCookies\"]");
+ "[\"cookies\",\"protocol\",\"remoteip\",\"scheme\",\"setCookies\"]");
pref("devtools.netmonitor.panes-network-details-width", 550);
pref("devtools.netmonitor.panes-network-details-height", 450);
pref("devtools.netmonitor.har.defaultLogDir", "");
pref("devtools.netmonitor.har.defaultFileName", "Archive %date");
pref("devtools.netmonitor.har.jsonp", false);
pref("devtools.netmonitor.har.jsonpCallback", "");
pref("devtools.netmonitor.har.includeResponseBodies", true);
pref("devtools.netmonitor.har.compress", false);
--- a/devtools/client/netmonitor/src/assets/styles/netmonitor.css
+++ b/devtools/client/netmonitor/src/assets/styles/netmonitor.css
@@ -442,16 +442,22 @@ body,
}
/* Set Cookies column */
.requests-list-set-cookies {
width: 8%;
}
+/* Scheme column */
+
+.requests-list-scheme {
+ width: 8%;
+}
+
/* Domain column */
.requests-list-domain {
width: 13%;
}
.requests-list-domain.requests-list-column {
text-align: start;
--- a/devtools/client/netmonitor/src/components/moz.build
+++ b/devtools/client/netmonitor/src/components/moz.build
@@ -15,16 +15,17 @@ DevToolsModules(
'request-list-column-cause.js',
'request-list-column-content-size.js',
'request-list-column-cookies.js',
'request-list-column-domain.js',
'request-list-column-file.js',
'request-list-column-method.js',
'request-list-column-protocol.js',
'request-list-column-remote-ip.js',
+ 'request-list-column-scheme.js',
'request-list-column-set-cookies.js',
'request-list-column-status.js',
'request-list-column-transferred-size.js',
'request-list-column-type.js',
'request-list-column-waterfall.js',
'request-list-content.js',
'request-list-empty-notice.js',
'request-list-header.js',
new file mode 100644
--- /dev/null
+++ b/devtools/client/netmonitor/src/components/request-list-column-scheme.js
@@ -0,0 +1,39 @@
+/* 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 {
+ createClass,
+ DOM,
+ PropTypes,
+} = require("devtools/client/shared/vendor/react");
+
+const { div } = DOM;
+
+const RequestListColumnScheme = createClass({
+ displayName: "RequestListColumnScheme",
+
+ propTypes: {
+ item: PropTypes.object.isRequired,
+ },
+
+ shouldComponentUpdate(nextProps) {
+ return this.props.item.urlDetails.scheme !== nextProps.item.urlDetails.scheme;
+ },
+
+ render() {
+ const { urlDetails } = this.props.item;
+ return (
+ div({
+ className: "requests-list-column requests-list-scheme",
+ title: urlDetails.scheme
+ },
+ urlDetails.scheme
+ )
+ );
+ }
+});
+
+module.exports = RequestListColumnScheme;
--- a/devtools/client/netmonitor/src/components/request-list-item.js
+++ b/devtools/client/netmonitor/src/components/request-list-item.js
@@ -17,16 +17,17 @@ const { propertiesEqual } = require("../
const RequestListColumnCause = createFactory(require("./request-list-column-cause"));
const RequestListColumnContentSize = createFactory(require("./request-list-column-content-size"));
const RequestListColumnCookies = createFactory(require("./request-list-column-cookies"));
const RequestListColumnDomain = createFactory(require("./request-list-column-domain"));
const RequestListColumnFile = createFactory(require("./request-list-column-file"));
const RequestListColumnMethod = createFactory(require("./request-list-column-method"));
const RequestListColumnProtocol = createFactory(require("./request-list-column-protocol"));
const RequestListColumnRemoteIP = createFactory(require("./request-list-column-remote-ip"));
+const RequestListColumnScheme = createFactory(require("./request-list-column-scheme"));
const RequestListColumnSetCookies = createFactory(require("./request-list-column-set-cookies"));
const RequestListColumnStatus = createFactory(require("./request-list-column-status"));
const RequestListColumnTransferredSize = createFactory(require("./request-list-column-transferred-size"));
const RequestListColumnType = createFactory(require("./request-list-column-type"));
const RequestListColumnWaterfall = createFactory(require("./request-list-column-waterfall"));
const { div } = DOM;
@@ -130,16 +131,17 @@ const RequestListItem = createClass({
tabIndex: 0,
onContextMenu,
onMouseDown,
},
columns.get("status") && RequestListColumnStatus({ item }),
columns.get("method") && RequestListColumnMethod({ item }),
columns.get("file") && RequestListColumnFile({ item }),
columns.get("protocol") && RequestListColumnProtocol({ item }),
+ columns.get("scheme") && RequestListColumnScheme({ item }),
columns.get("domain") && RequestListColumnDomain({ item, onSecurityIconClick }),
columns.get("remoteip") && RequestListColumnRemoteIP({ item }),
columns.get("cause") && RequestListColumnCause({ item, onCauseBadgeClick }),
columns.get("type") && RequestListColumnType({ item }),
columns.get("cookies") && RequestListColumnCookies({ item }),
columns.get("setCookies") && RequestListColumnSetCookies({ item }),
columns.get("transferred") && RequestListColumnTransferredSize({ item }),
columns.get("contentSize") && RequestListColumnContentSize({ item }),
--- a/devtools/client/netmonitor/src/constants.js
+++ b/devtools/client/netmonitor/src/constants.js
@@ -113,16 +113,20 @@ const HEADERS = [
name: "file",
canFilter: false,
},
{
name: "protocol",
canFilter: true,
},
{
+ name: "scheme",
+ canFilter: true,
+ },
+ {
name: "domain",
canFilter: true,
},
{
name: "remoteip",
canFilter: true,
filterKey: "remote-ip",
},
--- a/devtools/client/netmonitor/src/reducers/ui.js
+++ b/devtools/client/netmonitor/src/reducers/ui.js
@@ -18,16 +18,17 @@ const {
WATERFALL_RESIZE,
} = require("../constants");
const Columns = I.Record({
status: true,
method: true,
file: true,
protocol: false,
+ scheme: false,
domain: true,
remoteip: false,
cause: true,
type: true,
cookies: false,
setCookies: false,
transferred: true,
contentSize: true,
--- a/devtools/client/netmonitor/src/utils/filter-text-utils.js
+++ b/devtools/client/netmonitor/src/utils/filter-text-utils.js
@@ -33,17 +33,16 @@
const { HEADERS } = require("../constants");
const { getFormattedIPAndPort } = require("./format-utils");
const HEADER_FILTERS = HEADERS
.filter(h => h.canFilter)
.map(h => h.filterKey || h.name);
const FILTER_FLAGS = [
...HEADER_FILTERS,
- "scheme",
"set-cookie-domain",
"set-cookie-name",
"set-cookie-value",
"mime-type",
"larger-than",
"is",
"has-response-header",
"regexp",
@@ -177,18 +176,17 @@ function isFlagFilterMatch(item, { type,
if (value === "from-cache" ||
value === "cached") {
match = item.fromCache || item.status === "304";
} else if (value === "running") {
match = !item.status;
}
break;
case "scheme":
- let scheme = new URL(item.url).protocol.replace(":", "").toLowerCase();
- match = scheme === value;
+ match = item.urlDetails.scheme === value;
break;
case "regexp":
try {
let pattern = new RegExp(value);
match = pattern.test(item.url);
} catch (e) {
match = false;
}
--- a/devtools/client/netmonitor/src/utils/request-utils.js
+++ b/devtools/client/netmonitor/src/utils/request-utils.js
@@ -172,23 +172,35 @@ function getUrlHostName(url) {
* @param {string} url - url string
* @return {string} unicode host of a url
*/
function getUrlHost(url) {
return decodeUnicodeUrl((new URL(url)).host);
}
/**
+ * Helpers for getting the shceme portion of a url.
+ * For example helper returns "http" from http://domain.com/path/basename
+ *
+ * @param {string} url - url string
+ * @return {string} string scheme of a url
+ */
+function getUrlScheme(url) {
+ return (new URL(url)).protocol.replace(":", "").toLowerCase();
+}
+
+/**
* Extract several details fields from a URL at once.
*/
function getUrlDetails(url) {
let baseNameWithQuery = getUrlBaseNameWithQuery(url);
let host = getUrlHost(url);
let hostname = getUrlHostName(url);
let unicodeUrl = decodeUnicodeUrl(url);
+ let scheme = getUrlScheme(url);
// Mark local hosts specially, where "local" is as defined in the W3C
// spec for secure contexts.
// http://www.w3.org/TR/powerful-features/
//
// * If the name falls under 'localhost'
// * If the name is an IPv4 address within 127.0.0.0/8
// * If the name is an IPv6 address within ::1/128
@@ -197,16 +209,17 @@ function getUrlDetails(url) {
// been validated before it gets here.
let isLocal = hostname.match(/(.+\.)?localhost$/) ||
hostname.match(/^127\.\d{1,3}\.\d{1,3}\.\d{1,3}/) ||
hostname.match(/\[[0:]+1\]/);
return {
baseNameWithQuery,
host,
+ scheme,
unicodeUrl,
isLocal
};
}
/**
* Parse a url's query string into its components
*
@@ -291,18 +304,19 @@ function propertiesEqual(props, item1, i
module.exports = {
getFormDataSections,
fetchHeaders,
formDataURI,
writeHeaderText,
decodeUnicodeUrl,
getAbbreviatedMimeType,
getUrlBaseName,
- getUrlQuery,
getUrlBaseNameWithQuery,
+ getUrlDetails,
+ getUrlHost,
getUrlHostName,
- getUrlHost,
- getUrlDetails,
+ getUrlQuery,
+ getUrlScheme,
parseQueryString,
parseFormData,
propertiesEqual,
ipToLong,
};
--- a/devtools/client/netmonitor/src/utils/sort-predicates.js
+++ b/devtools/client/netmonitor/src/utils/sort-predicates.js
@@ -51,16 +51,21 @@ function file(first, second) {
return result || waterfall(first, second);
}
function protocol(first, second) {
const result = compareValues(first.httpVersion, second.httpVersion);
return result || waterfall(first, second);
}
+function scheme(first, second) {
+ const result = compareValues(first.urlDetails.scheme, second.urlDetails.scheme);
+ return result || waterfall(first, second);
+}
+
function domain(first, second) {
const firstDomain = first.urlDetails.host.toLowerCase();
const secondDomain = second.urlDetails.host.toLowerCase();
const result = compareValues(firstDomain, secondDomain);
return result || waterfall(first, second);
}
function remoteip(first, second) {
@@ -114,16 +119,17 @@ function contentSize(first, second) {
return result || waterfall(first, second);
}
exports.Sorters = {
status,
method,
file,
protocol,
+ scheme,
cookies,
setCookies,
domain,
remoteip,
cause,
type,
transferred,
contentSize,
--- a/devtools/client/netmonitor/test/head.js
+++ b/devtools/client/netmonitor/test/head.js
@@ -15,18 +15,19 @@ Services.scriptloader.loadSubScript(
const { EVENTS } = require("devtools/client/netmonitor/src/constants");
const {
getFormattedIPAndPort
} = require("devtools/client/netmonitor/src/utils/format-utils");
const {
decodeUnicodeUrl,
getUrlBaseName,
+ getUrlHost,
getUrlQuery,
- getUrlHost,
+ getUrlScheme,
} = require("devtools/client/netmonitor/src/utils/request-utils");
/* eslint-disable no-unused-vars, max-len */
const EXAMPLE_URL = "http://example.com/browser/devtools/client/netmonitor/test/";
const HTTPS_EXAMPLE_URL = "https://example.com/browser/devtools/client/netmonitor/test/";
const API_CALLS_URL = EXAMPLE_URL + "html_api-calls-test-page.html";
const SIMPLE_URL = EXAMPLE_URL + "html_simple-test-page.html";
@@ -375,16 +376,17 @@ function verifyRequestItemTarget(documen
let { fuzzyUrl, status, statusText, cause, type, fullMimeType,
transferred, size, time, displayedStatus } = data;
let target = document.querySelectorAll(".request-list-item")[visibleIndex];
let unicodeUrl = decodeUnicodeUrl(url);
let name = getUrlBaseName(url);
let query = getUrlQuery(url);
let host = getUrlHost(url);
+ let scheme = getUrlScheme(url);
let { httpVersion = "", remoteAddress, remotePort } = requestItem;
let formattedIPPort = getFormattedIPAndPort(remoteAddress, remotePort);
let remoteIP = remoteAddress ? `${formattedIPPort}` : "unknown";
if (fuzzyUrl) {
ok(requestItem.method.startsWith(method), "The attached method is correct.");
ok(requestItem.url.startsWith(url), "The attached url is correct.");
} else {
@@ -422,16 +424,22 @@ function verifyRequestItemTarget(documen
domainTooltip, "The tooltip domain is correct.");
is(target.querySelector(".requests-list-remoteip").textContent,
remoteIP, "The displayed remote IP is correct.");
is(target.querySelector(".requests-list-remoteip").getAttribute("title"),
remoteIP, "The tooltip remote IP is correct.");
+ is(target.querySelector(".requests-list-scheme").textContent,
+ scheme, "The displayed scheme is correct.");
+
+ is(target.querySelector(".requests-list-scheme").getAttribute("title"),
+ scheme, "The tooltip scheme is correct.");
+
if (status !== undefined) {
let value = target.querySelector(".requests-list-status-icon")
.getAttribute("data-code");
let codeValue = target.querySelector(".requests-list-status-code").textContent;
let tooltip = target.querySelector(".requests-list-status").getAttribute("title");
info("Displayed status: " + value);
info("Displayed code: " + codeValue);
info("Tooltip status: " + tooltip);
--- a/devtools/client/preferences/devtools.js
+++ b/devtools/client/preferences/devtools.js
@@ -145,17 +145,18 @@ pref("devtools.serviceWorkers.testing.en
// Enable the Network Monitor
pref("devtools.netmonitor.enabled", true);
// The default Network Monitor UI settings
pref("devtools.netmonitor.panes-network-details-width", 550);
pref("devtools.netmonitor.panes-network-details-height", 450);
pref("devtools.netmonitor.filters", "[\"all\"]");
-pref("devtools.netmonitor.hiddenColumns", "[\"cookies\",\"protocol\",\"remoteip\",\"setCookies\"]");
+pref("devtools.netmonitor.hiddenColumns",
+ "[\"cookies\",\"protocol\",\"remoteip\",\"scheme\",\"setCookies\"]");
// The default Network monitor HAR export setting
pref("devtools.netmonitor.har.defaultLogDir", "");
pref("devtools.netmonitor.har.defaultFileName", "Archive %date");
pref("devtools.netmonitor.har.jsonp", false);
pref("devtools.netmonitor.har.jsonpCallback", "");
pref("devtools.netmonitor.har.includeResponseBodies", true);
pref("devtools.netmonitor.har.compress", false);