diff --git a/devtools/client/framework/components/DebugTargetInfo.js b/devtools/client/framework/components/DebugTargetInfo.js
index e096af04bd7e..d1d0e3ff2f3a 100644
--- a/devtools/client/framework/components/DebugTargetInfo.js
+++ b/devtools/client/framework/components/DebugTargetInfo.js
@@ -6,6 +6,8 @@
const { PureComponent } = require("devtools/client/shared/vendor/react");
const dom = require("devtools/client/shared/vendor/react-dom-factories");
const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
+const { CONNECTION_TYPES } =
+ require("devtools/client/shared/remote-debugging/remote-client-manager");
/**
* This is header that should be displayed on top of the toolbox when using
@@ -15,6 +17,8 @@ class DebugTargetInfo extends PureComponent {
static get propTypes() {
return {
deviceDescription: PropTypes.shape({
+ channel: PropTypes.string.isRequired,
+ connectionType: PropTypes.string,
deviceName: PropTypes.string,
name: PropTypes.string.isRequired,
version: PropTypes.string.isRequired,
@@ -24,37 +28,100 @@ class DebugTargetInfo extends PureComponent {
};
}
- getTargetText() {
- const { L10N, toolbox } = this.props;
- const name = toolbox.target.name;
- const type = L10N.getStr("toolbox.debugTargetInfo.type.tab");
- return L10N.getFormatStr("toolbox.debugTargetInfo.targetLabel", name, type);
- }
-
getRuntimeText() {
const { deviceDescription, L10N } = this.props;
- const { name, deviceName, version } = deviceDescription;
- const localizationType =
- deviceName ? "toolbox.debugTargetInfo.runtimeLabelWithDeviceName"
- : "toolbox.debugTargetInfo.runtimeLabel";
- return L10N.getFormatStr(localizationType, name, version, deviceName);
+ const { name, version, connectionType } = deviceDescription;
+
+ return (connectionType === CONNECTION_TYPES.THIS_FIREFOX)
+ ? L10N.getFormatStr("toolbox.debugTargetInfo.runtimeLabel.thisFirefox", version)
+ : L10N.getFormatStr("toolbox.debugTargetInfo.runtimeLabel", name, version);
+ }
+
+ getAssetsForConnectionType() {
+ const { connectionType } = this.props.deviceDescription;
+
+ const BASE_IMG_URL = "chrome://devtools/skin/images/";
+ switch (connectionType) {
+ case CONNECTION_TYPES.USB:
+ return {
+ image: `${BASE_IMG_URL}aboutdebugging-usb-icon.svg`,
+ l10nId: "toolbox.debugTargetInfo.connection.usb",
+ };
+ case CONNECTION_TYPES.NETWORK:
+ return {
+ image: `${BASE_IMG_URL}aboutdebugging-globe-icon.svg`,
+ l10nId: "toolbox.debugTargetInfo.connection.network",
+ };
+ }
+ }
+
+ shallRenderConnection() {
+ const { connectionType } = this.props.deviceDescription;
+ const renderableTypes = [
+ CONNECTION_TYPES.USB,
+ CONNECTION_TYPES.NETWORK,
+ ];
+
+ return renderableTypes.includes(connectionType);
+ }
+
+ renderConnection() {
+ const { connectionType } = this.props.deviceDescription;
+ const { image, l10nId } = this.getAssetsForConnectionType();
+
+ return dom.span(
+ {
+ className: "iconized-label",
+ },
+ dom.img({ src: image, alt: `${connectionType} icon`}),
+ this.props.L10N.getStr(l10nId),
+ );
+ }
+
+ renderRuntime() {
+ const { channel, deviceName } = this.props.deviceDescription;
+
+ const channelIcon =
+ (channel === "release" || channel === "beta" || channel === "aurora") ?
+ `chrome://devtools/skin/images/aboutdebugging-firefox-${ channel }.svg` :
+ "chrome://devtools/skin/images/aboutdebugging-firefox-nightly.svg";
+
+ return dom.span(
+ {
+ className: "iconized-label",
+ },
+ dom.img({ src: channelIcon, className: "channel-icon" }),
+ dom.b({ className: "ellipsis-text" }, this.getRuntimeText()),
+ dom.span({ className: "ellipsis-text" }, deviceName),
+ );
+ }
+
+ renderTarget() {
+ const title = this.props.toolbox.target.name;
+ const url = this.props.toolbox.target.url;
+ // TODO: https://bugzilla.mozilla.org/show_bug.cgi?id=1520723
+ // Show actual favicon (currently toolbox.target.activeTab.favicon
+ // is unpopulated)
+ const favicon = "chrome://devtools/skin/images/aboutdebugging-globe-icon.svg";
+
+ return dom.span(
+ {
+ className: "iconized-label",
+ },
+ dom.img({ src: favicon, alt: "favicon"}),
+ title ? dom.b({ className: "ellipsis-text"}, title) : null,
+ dom.span({ className: "ellipsis-text" }, url),
+ );
}
render() {
- const { deviceDescription } = this.props;
- const { channel } = deviceDescription;
- const icon =
- (channel === "release" || channel === "beta" || channel === "aurora")
- ? `chrome://devtools/skin/images/aboutdebugging-firefox-${ channel }.svg`
- : "chrome://devtools/skin/images/aboutdebugging-firefox-nightly.svg";
-
return dom.header(
{
className: "debug-target-info",
},
- dom.img({ src: icon }),
- dom.span({}, this.getRuntimeText()),
- dom.span({ className: "target" }, this.getTargetText()),
+ this.shallRenderConnection() ? this.renderConnection() : null,
+ this.renderRuntime(),
+ this.renderTarget(),
);
}
}
diff --git a/devtools/client/framework/toolbox.js b/devtools/client/framework/toolbox.js
index 57106c8f5604..2895c8d36f5b 100644
--- a/devtools/client/framework/toolbox.js
+++ b/devtools/client/framework/toolbox.js
@@ -76,6 +76,10 @@ loader.lazyGetter(this, "reloadAndRecordTab",
loader.lazyGetter(this, "reloadAndStopRecordingTab",
() => require("devtools/client/webreplay/menu.js").reloadAndStopRecordingTab);
+loader.lazyGetter(this, "remoteClientManager", () =>
+ require("devtools/client/shared/remote-debugging/remote-client-manager.js")
+ .remoteClientManager);
+
/**
* A "Toolbox" is the component that holds all the tools for one specific
* target. Visually, it's a document that includes the tools tabs and all
@@ -454,7 +458,10 @@ Toolbox.prototype = {
this._showDebugTargetInfo = true;
const deviceFront = await this.target.client.mainRoot.getFront("device");
// DebugTargetInfo requires the device description to be rendered.
- this._deviceDescription = await deviceFront.getDescription();
+ const description = await deviceFront.getDescription();
+ const remoteId = new this.win.URLSearchParams(this.win.location.href).get("remoteId");
+ const connectionType = remoteClientManager.getConnectionTypeByRemoteId(remoteId);
+ this._deviceDescription = Object.assign({}, description, { connectionType });
}
// Start tracking network activity on toolbox open for targets such as tabs.
diff --git a/devtools/client/jar.mn b/devtools/client/jar.mn
index fbef7b10eeb2..225ed733d79e 100644
--- a/devtools/client/jar.mn
+++ b/devtools/client/jar.mn
@@ -109,6 +109,8 @@ devtools.jar:
skin/images/aboutdebugging-firefox-nightly.svg (themes/images/aboutdebugging-firefox-nightly.svg)
skin/images/aboutdebugging-firefox-release.svg (themes/images/aboutdebugging-firefox-release.svg)
skin/images/aboutdebugging-globe-icon.svg (themes/images/aboutdebugging-globe-icon.svg)
+ skin/images/aboutdebugging-wifi-icon.svg (themes/images/aboutdebugging-wifi-icon.svg)
+ skin/images/aboutdebugging-usb-icon.svg (themes/images/aboutdebugging-usb-icon.svg)
skin/images/fox-smiling.svg (themes/images/fox-smiling.svg)
skin/images/grid.svg (themes/images/grid.svg)
skin/images/angle-swatch.svg (themes/images/angle-swatch.svg)
diff --git a/devtools/client/locales/en-US/toolbox.properties b/devtools/client/locales/en-US/toolbox.properties
index 94a17f473f28..d2e5d024ea60 100644
--- a/devtools/client/locales/en-US/toolbox.properties
+++ b/devtools/client/locales/en-US/toolbox.properties
@@ -200,6 +200,13 @@ toolbox.options.enableNewDebugger.label=Enable new debugger frontend
# The version of runtime: %2$S
toolbox.debugTargetInfo.runtimeLabel=%1$S (%2$S)
+# LOCALIZATION NOTE (toolbox.debugTargetInfo.runtimeLabel.thisFirefox): this is displayed
+# as a toolbox header in about:devtools-toolbox, when inspecting the current Firefox runtime
+# (for instance, when inspecting one of its tabs in about:debugging)
+# e.g. This Firefox (65.0a1)
+# The version of runtime: %S
+toolbox.debugTargetInfo.runtimeLabel.thisFirefox=This Firefox (%S)
+
# LOCALIZATION NOTE (toolbox.debugTargetInfo.runtimeLabelWithDeviceName): This is displayed
# as a toolbox header in about:devtools-toolbox. about:devtools-toolbox is used for
# instance when inspecting tabs in about:debugging.
@@ -223,6 +230,12 @@ toolbox.debugTargetInfo.targetLabel=%1$S (%2$S)
# Currently, we support only this type.
toolbox.debugTargetInfo.type.tab=tab
+# LOCALIZATION NOTE (toolbox.debugTargetInfo.connection.*): This is displayed in the
+# toolbox header in about:devtools-toolbox, to indicate how the connection to the
+# runtime being inspected was made.
+toolbox.debugTargetInfo.connection.usb=USB
+toolbox.debugTargetInfo.connection.network=Network
+
# LOCALIZATION NOTE (browserToolbox.statusMessage): This is the label
# shown next to status details when the Browser Toolbox fails to connect or
# appears to be taking a while to do so.
diff --git a/devtools/client/shared/remote-debugging/remote-client-manager.js b/devtools/client/shared/remote-debugging/remote-client-manager.js
index 0ba4ce35c686..76ccfccb4868 100644
--- a/devtools/client/shared/remote-debugging/remote-client-manager.js
+++ b/devtools/client/shared/remote-debugging/remote-client-manager.js
@@ -4,6 +4,14 @@
"use strict";
+/* connection types for remote clients */
+const CONNECTION_TYPES = {
+ THIS_FIREFOX: "this-firefox",
+ USB: "usb",
+ NETWORK: "network",
+ UNKNOWN: "unknown",
+};
+
/**
* This class is designed to be a singleton shared by all DevTools to get access to
* existing clients created for remote debugging.
@@ -68,10 +76,31 @@ class RemoteClientManager {
return this._clients.get(key);
}
+ /**
+ * Retrieve a managed client for a remote id. The remote id should have been generated
+ * using getRemoteId.
+ */
+ getConnectionTypeByRemoteId(remoteId) {
+ if (!remoteId) {
+ return CONNECTION_TYPES.THIS_FIREFOX;
+ }
+
+ const key = decodeURIComponent(remoteId);
+ const type = this._getType(key);
+ return Object.values(CONNECTION_TYPES).includes(type)
+ ? type
+ : CONNECTION_TYPES.UNKNOWN;
+ }
+
_getKey(id, type) {
return id + "-" + type;
}
+ _getType(key) {
+ const chunks = key.split("-");
+ return chunks[chunks.length - 1];
+ }
+
_removeClientByKey(key) {
const client = this._clients.get(key);
if (client) {
@@ -95,4 +124,7 @@ class RemoteClientManager {
}
// Expose a singleton of RemoteClientManager.
-exports.remoteClientManager = new RemoteClientManager();
+module.exports = {
+ remoteClientManager: new RemoteClientManager(),
+ CONNECTION_TYPES,
+};
diff --git a/devtools/client/themes/images/aboutdebugging-usb-icon.svg b/devtools/client/themes/images/aboutdebugging-usb-icon.svg
new file mode 100644
index 000000000000..a30949a29839
--- /dev/null
+++ b/devtools/client/themes/images/aboutdebugging-usb-icon.svg
@@ -0,0 +1,6 @@
+
+
diff --git a/devtools/client/themes/images/aboutdebugging-wifi-icon.svg b/devtools/client/themes/images/aboutdebugging-wifi-icon.svg
new file mode 100644
index 000000000000..49a45a1af51c
--- /dev/null
+++ b/devtools/client/themes/images/aboutdebugging-wifi-icon.svg
@@ -0,0 +1,9 @@
+
+
diff --git a/devtools/client/themes/toolbox.css b/devtools/client/themes/toolbox.css
index da1ed44d1f61..c6159fff937f 100644
--- a/devtools/client/themes/toolbox.css
+++ b/devtools/client/themes/toolbox.css
@@ -3,29 +3,55 @@
* 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/. */
+/*
+* Utils
+*/
+
+/* text that needs to be cut with … */
+.ellipsis-text {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
/*
* Debug Target Info layout
- * +------+-------------------+------------------+
- * | icon | runtime info text | target info text |
- * | 32px | auto | 1fr |
- * +------+-------------------+------------------+
+ * +------------+--------------+------------------------+
+ * | connection | runtime info | target info icon + text |
+ * +------------+--------------+------------------------+
*/
.debug-target-info {
- display: grid;
- grid-template-columns: 32px auto 1fr;
- grid-column-gap: 8px;
- align-items: center;
+ display: flex;
background: var(--theme-tab-toolbar-background);
border-bottom: 1px solid var(--theme-splitter-color);
- padding-bottom: 4px;
- padding-left: 12px;
- padding-top: 4px;
- font-size: 1.46em;
+ padding: 4px 0;
+ font-size: 1.2em;
color: var(--theme-toolbar-color);
}
-.debug-target-info .target {
- font-weight: lighter;
+/*
+ * Debug Target labels with icon layout
+ * +------+------------------------+---------------+
+ * | icon | label text (bold) | optional text |
+ * | 20px | max-content | max-content |
+ * +------+------------------------+---------------+
+ */
+.debug-target-info .iconized-label {
+ display: grid;
+ grid-template-columns: 20px auto auto;
+ grid-column-gap: 8px;
+ align-items: center;
+ padding: 0 24px;
+ white-space: nowrap;
+}
+
+.debug-target-info .iconized-label:not(:last-child) {
+ border-right: 1px solid var(--theme-splitter-color);
+}
+
+.debug-target-info img {
+ -moz-context-properties: fill, stroke;
+ fill: var(--theme-toolbar-icon-color);
}
/* Toolbox tabbar */
@@ -615,5 +641,5 @@
}
.webreplay-player #overlay .tick:hover ~ .tick {
- opacity: 0.5;
-}
\ No newline at end of file
+ opacity: 0.5;
+}