Bug 1539344 - Part 2: display target type icon in DebugTargetInfo component r=jdescottes,Ola
☠☠ backed out by ae6b824bbe75 ☠ ☠
authorBelén Albeza <balbeza@mozilla.com>
Mon, 08 Apr 2019 12:52:03 +0000
changeset 468505 8b3d1e3ae296e9f4ae5fdda6a8bb4660ea8a1150
parent 468504 29b64aed34748dda4d58f5d3f373f831eacc72b0
child 468506 878f78400ed7123ddfc8b431c9dfc6225dfcbc1b
push id82635
push userbalbeza@mozilla.com
push dateTue, 09 Apr 2019 09:53:35 +0000
treeherderautoland@878f78400ed7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdescottes, Ola
bugs1539344
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1539344 - Part 2: display target type icon in DebugTargetInfo component r=jdescottes,Ola Differential Revision: https://phabricator.services.mozilla.com/D25375
devtools/client/framework/components/DebugTargetInfo.js
devtools/client/framework/components/ToolboxToolbar.js
devtools/client/framework/test/jest/components/__snapshots__/debug-target-info.test.js.snap
devtools/client/framework/test/jest/components/debug-target-info.test.js
devtools/client/framework/toolbox.js
devtools/client/locales/en-US/toolbox.properties
devtools/client/themes/toolbox.css
--- a/devtools/client/framework/components/DebugTargetInfo.js
+++ b/devtools/client/framework/components/DebugTargetInfo.js
@@ -1,89 +1,125 @@
 /* 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 { 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 } =
+const { CONNECTION_TYPES, DEBUG_TARGET_TYPES } =
   require("devtools/client/shared/remote-debugging/constants");
 
 /**
  * This is header that should be displayed on top of the toolbox when using
  * about:devtools-toolbox.
  */
 class DebugTargetInfo extends PureComponent {
   static get propTypes() {
     return {
-      deviceDescription: PropTypes.shape({
-        brandName: PropTypes.string.isRequired,
-        channel: PropTypes.string.isRequired,
-        connectionType: PropTypes.string.isRequired,
-        deviceName: PropTypes.string,
-        version: PropTypes.string.isRequired,
+      debugTargetData: PropTypes.shape({
+        connectionType: PropTypes.oneOf(Object.values(CONNECTION_TYPES)).isRequired,
+        deviceDescription: PropTypes.shape({
+          brandName: PropTypes.string.isRequired,
+          channel: PropTypes.string.isRequired,
+          deviceName: PropTypes.string,
+          version: PropTypes.string.isRequired,
+        }).isRequired,
+        targetType: PropTypes.oneOf(Object.values(DEBUG_TARGET_TYPES)).isRequired,
       }).isRequired,
       L10N: PropTypes.object.isRequired,
       toolbox: PropTypes.object.isRequired,
     };
   }
 
   getRuntimeText() {
-    const { deviceDescription, L10N } = this.props;
-    const { brandName, version, connectionType } = deviceDescription;
+    const { debugTargetData, L10N } = this.props;
+    const { brandName, version } = debugTargetData.deviceDescription;
+    const { connectionType } = debugTargetData;
 
     return (connectionType === CONNECTION_TYPES.THIS_FIREFOX)
       ? L10N.getFormatStr("toolbox.debugTargetInfo.runtimeLabel.thisFirefox", version)
       : L10N.getFormatStr("toolbox.debugTargetInfo.runtimeLabel", brandName, version);
   }
 
   getAssetsForConnectionType() {
-    const { connectionType } = this.props.deviceDescription;
+    const { connectionType } = this.props.debugTargetData;
 
     switch (connectionType) {
       case CONNECTION_TYPES.USB:
         return {
           image: "chrome://devtools/skin/images/aboutdebugging-usb-icon.svg",
           l10nId: "toolbox.debugTargetInfo.connection.usb",
         };
       case CONNECTION_TYPES.NETWORK:
         return {
           image: "chrome://devtools/skin/images/aboutdebugging-globe-icon.svg",
           l10nId: "toolbox.debugTargetInfo.connection.network",
         };
     }
   }
 
+  getAssetsForDebugTargetType() {
+    const { targetType } = this.props.debugTargetData;
+
+    // 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/globe.svg";
+
+    switch (targetType) {
+      case DEBUG_TARGET_TYPES.EXTENSION:
+        return {
+          image: "chrome://devtools/skin/images/debugging-addons.svg",
+          l10nId: "toolbox.debugTargetInfo.targetType.extension",
+        };
+      case DEBUG_TARGET_TYPES.PROCESS:
+        return {
+          image: "chrome://devtools/skin/images/settings.svg",
+          l10nId: "toolbox.debugTargetInfo.targetType.process",
+        };
+      case DEBUG_TARGET_TYPES.TAB:
+        return {
+          image: favicon,
+          l10nId: "toolbox.debugTargetInfo.targetType.tab",
+        };
+      case DEBUG_TARGET_TYPES.WORKER:
+        return {
+          image: "chrome://devtools/skin/images/debugging-workers.svg",
+          l10nId: "toolbox.debugTargetInfo.targetType.worker",
+        };
+    }
+  }
+
   shallRenderConnection() {
-    const { connectionType } = this.props.deviceDescription;
+    const { connectionType } = this.props.debugTargetData;
     const renderableTypes = [
       CONNECTION_TYPES.USB,
       CONNECTION_TYPES.NETWORK,
     ];
 
     return renderableTypes.includes(connectionType);
   }
 
   renderConnection() {
-    const { connectionType } = this.props.deviceDescription;
+    const { connectionType } = this.props.debugTargetData;
     const { image, l10nId } = this.getAssetsForConnectionType();
 
     return dom.span(
       {
         className: "iconized-label js-connection-info",
       },
       dom.img({ src: image, alt: `${connectionType} icon`}),
       this.props.L10N.getStr(l10nId),
     );
   }
 
   renderRuntime() {
-    const { channel, deviceName } = this.props.deviceDescription;
+    const { channel, deviceName } = this.props.debugTargetData.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(
       {
@@ -93,26 +129,24 @@ class DebugTargetInfo extends PureCompon
       dom.b({ className: "devtools-ellipsis-text" }, this.getRuntimeText()),
       dom.span({ className: "devtools-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";
+
+    const { image, l10nId } = this.getAssetsForDebugTargetType();
 
     return dom.span(
       {
         className: "iconized-label",
       },
-      dom.img({ src: favicon, alt: "favicon"}),
+      dom.img({ src: image, alt: this.props.L10N.getStr(l10nId)}),
       title ? dom.b({ className: "devtools-ellipsis-text js-target-title"}, title) : null,
       dom.span({ className: "devtools-ellipsis-text" }, url),
     );
   }
 
   render() {
     return dom.header(
       {
--- a/devtools/client/framework/components/ToolboxToolbar.js
+++ b/devtools/client/framework/components/ToolboxToolbar.js
@@ -91,20 +91,21 @@ class ToolboxToolbar extends Component {
       toolbox: PropTypes.object,
       // Call back function to detect tabs order updated.
       onTabsOrderUpdated: PropTypes.func.isRequired,
       // Count of visible toolbox buttons which is used by ToolboxTabs component
       // to recognize that the visibility of toolbox buttons were changed.
       // Because in the component we cannot compare the visibility since the
       // button definition instance in toolboxButtons will be unchanged.
       visibleToolboxButtonCount: PropTypes.number,
-      // Flag whether need to show DebugTargetInfo.
-      showDebugTargetInfo: PropTypes.bool,
-      // Device description for DebugTargetInfo component.
-      deviceDescription: PropTypes.object,
+      // Data to show debug target info, if needed
+      debugTargetData: PropTypes.shape({
+        deviceDescription: PropTypes.object.isRequired,
+        targetType: PropTypes.string.isRequired,
+      }),
     };
   }
 
   constructor(props) {
     super(props);
 
     this.hideMenu = this.hideMenu.bind(this);
     this.createFrameList = this.createFrameList.bind(this);
@@ -417,17 +418,17 @@ class ToolboxToolbar extends Component {
     );
   }
 
   /**
    * The render function is kept fairly short for maintainability. See the individual
    * render functions for how each of the sections is rendered.
    */
   render() {
-    const {deviceDescription, L10N, showDebugTargetInfo, toolbox} = this.props;
+    const { L10N, debugTargetData, toolbox} = this.props;
     const classnames = ["devtools-tabbar"];
     const startButtons = this.renderToolboxButtonsStart();
     const endButtons = this.renderToolboxButtonsEnd();
 
     if (!startButtons) {
       classnames.push("devtools-tabbar-has-start");
     }
     if (!endButtons) {
@@ -443,18 +444,19 @@ class ToolboxToolbar extends Component {
           startButtons,
           ToolboxTabs(this.props),
           endButtons,
           this.renderToolboxControls()
         )
       )
       : div({ className: classnames.join(" ") });
 
-    const debugTargetInfo =
-      showDebugTargetInfo ? DebugTargetInfo({ deviceDescription, L10N, toolbox }) : null;
+    const debugTargetInfo = debugTargetData
+      ? DebugTargetInfo({ debugTargetData, L10N, toolbox })
+      : null;
 
     if (toolbox.target.canRewind) {
       return div(
         {},
         WebReplayPlayer({
           toolbox: toolbox,
         }),
         debugTargetInfo,
--- a/devtools/client/framework/test/jest/components/__snapshots__/debug-target-info.test.js.snap
+++ b/devtools/client/framework/test/jest/components/__snapshots__/debug-target-info.test.js.snap
@@ -19,18 +19,18 @@ exports[`DebugTargetInfo component rende
     <span
       className="devtools-ellipsis-text"
     />
   </span>
   <span
     className="iconized-label"
   >
     <img
-      alt="favicon"
-      src="chrome://devtools/skin/images/aboutdebugging-globe-icon.svg"
+      alt="toolbox.debugTargetInfo.targetType.tab"
+      src="chrome://devtools/skin/images/globe.svg"
     />
     <b
       className="devtools-ellipsis-text js-target-title"
     >
       Test Tab Name
     </b>
     <span
       className="devtools-ellipsis-text"
@@ -71,18 +71,18 @@ exports[`DebugTargetInfo component rende
     >
       usbDeviceName
     </span>
   </span>
   <span
     className="iconized-label"
   >
     <img
-      alt="favicon"
-      src="chrome://devtools/skin/images/aboutdebugging-globe-icon.svg"
+      alt="toolbox.debugTargetInfo.targetType.tab"
+      src="chrome://devtools/skin/images/globe.svg"
     />
     <b
       className="devtools-ellipsis-text js-target-title"
     >
       Test Tab Name
     </b>
     <span
       className="devtools-ellipsis-text"
@@ -112,18 +112,18 @@ exports[`DebugTargetInfo component rende
     <span
       className="devtools-ellipsis-text"
     />
   </span>
   <span
     className="iconized-label"
   >
     <img
-      alt="favicon"
-      src="chrome://devtools/skin/images/aboutdebugging-globe-icon.svg"
+      alt="toolbox.debugTargetInfo.targetType.tab"
+      src="chrome://devtools/skin/images/globe.svg"
     />
     <span
       className="devtools-ellipsis-text"
     >
       http://some.target/without/a/name
     </span>
   </span>
 </header>
--- a/devtools/client/framework/test/jest/components/debug-target-info.test.js
+++ b/devtools/client/framework/test/jest/components/debug-target-info.test.js
@@ -5,17 +5,18 @@
 
 /**
  * Unit tests for the DebugTargetInfo component.
  */
 
 const renderer = require("react-test-renderer");
 const React = require("devtools/client/shared/vendor/react");
 const DebugTargetInfo = React.createFactory(require("devtools/client/framework/components/DebugTargetInfo"));
-const { CONNECTION_TYPES } = require("devtools/client/shared/remote-debugging/constants");
+const { CONNECTION_TYPES, DEBUG_TARGET_TYPES } =
+  require("devtools/client/shared/remote-debugging/constants");
 
 /**
  * Stub for the L10N property expected by the DebugTargetInfo component.
  */
 const stubL10N = {
   getStr: id => id,
   getFormatStr: (id, ...args) => [id, ...args].join("-"),
 };
@@ -51,28 +52,31 @@ const THIS_FIREFOX_DEVICE_DESCRIPTION = 
   brandName: "thisFirefoxRuntimeBrandName",
   connectionType: CONNECTION_TYPES.THIS_FIREFOX,
   channel: "release",
   version: "1.0.0",
 };
 
 const USB_TARGET_INFO = DebugTargetInfo({
   deviceDescription: USB_DEVICE_DESCRIPTION,
+  targetType: DEBUG_TARGET_TYPES.TAB,
   toolbox: TEST_TOOLBOX,
   L10N: stubL10N,
 });
 
 const THIS_FIREFOX_TARGET_INFO = DebugTargetInfo({
   deviceDescription: THIS_FIREFOX_DEVICE_DESCRIPTION,
+  targetType: DEBUG_TARGET_TYPES.TAB,
   toolbox: TEST_TOOLBOX,
   L10N: stubL10N,
 });
 
 const THIS_FIREFOX_NO_NAME_TARGET_INFO = DebugTargetInfo({
   deviceDescription: THIS_FIREFOX_DEVICE_DESCRIPTION,
+  targetType: DEBUG_TARGET_TYPES.TAB,
   toolbox: TEST_TOOLBOX_NO_NAME,
   L10N: stubL10N,
 });
 
 describe("DebugTargetInfo component", () => {
   it("displays connection info for USB Release target", () => {
     const targetInfo = renderer.create(USB_TARGET_INFO);
     expect(findByClassName(targetInfo.root, "js-connection-info").length).toEqual(1);
--- a/devtools/client/framework/toolbox.js
+++ b/devtools/client/framework/toolbox.js
@@ -449,19 +449,18 @@ Toolbox.prototype = {
       if (isToolboxURL) {
         // Update the URL so that onceDOMReady watch for the right url.
         this._URL = this.win.location.href;
       }
 
       if (this.hostType === Toolbox.HostType.PAGE) {
         // Displays DebugTargetInfo which shows the basic information of debug target,
         // if `about:devtools-toolbox` URL opens directly.
-        // DebugTargetInfo requires this._deviceDescription to be populated
-        this._showDebugTargetInfo = true;
-        this._deviceDescription = await this._getDeviceDescription();
+        // DebugTargetInfo requires this._debugTargetData to be populated
+        this._debugTargetData = await this._getDebugTargetData();
       }
 
       const domHelper = new DOMHelpers(this.win);
       const domReady = new Promise(resolve => {
         domHelper.onceDOMReady(() => {
           resolve();
         }, this._URL);
       });
@@ -602,22 +601,32 @@ Toolbox.prototype = {
     }.bind(this))().catch(e => {
       console.error("Exception while opening the toolbox", String(e), e);
       // While the exception stack is correctly printed in the Browser console when
       // passing `e` to console.error, it is not on the stdout, so print it via dump.
       dump(e.stack + "\n");
     });
   },
 
-  _getDeviceDescription: async function() {
+  _getDebugTargetData: async function() {
+    const url = new URL(this.win.location);
+    const searchParams = new this.win.URLSearchParams(url.search);
+
+    const targetType = searchParams.get("type");
+
     const deviceFront = await this.target.client.mainRoot.getFront("device");
-    const description = await deviceFront.getDescription();
-    const remoteId = new this.win.URLSearchParams(this.win.location.href).get("remoteId");
+    const deviceDescription = await deviceFront.getDescription();
+    const remoteId = searchParams.get("remoteId");
     const connectionType = remoteClientManager.getConnectionTypeByRemoteId(remoteId);
-    return Object.assign({}, description, { connectionType });
+
+    return {
+      connectionType,
+      deviceDescription,
+      targetType,
+    };
   },
 
   _onTargetClosed: async function() {
     const win = this.win; // .destroy() will set this.win to null
 
     // clean up the toolbox
     this.destroy();
     // NOTE: we should await this.destroy() to ensure a proper clean up.
@@ -1201,18 +1210,17 @@ Toolbox.prototype = {
       currentToolId: this.currentToolId,
       selectTool: this.selectTool,
       toggleOptions: this.toggleOptions,
       toggleSplitConsole: this.toggleSplitConsole,
       toggleNoAutohide: this.toggleNoAutohide,
       closeToolbox: this.closeToolbox,
       focusButton: this._onToolbarFocus,
       toolbox: this,
-      showDebugTargetInfo: this._showDebugTargetInfo,
-      deviceDescription: this._deviceDescription,
+      debugTargetData: this._debugTargetData,
       onTabsOrderUpdated: this._onTabsOrderUpdated,
     });
 
     this.component = this.ReactDOM.render(element, this._componentMount);
   },
 
   /**
    * Reset tabindex attributes across all focusable elements inside the toolbar.
--- a/devtools/client/locales/en-US/toolbox.properties
+++ b/devtools/client/locales/en-US/toolbox.properties
@@ -245,16 +245,24 @@ toolbox.debugTargetInfo.targetLabel=%1$S
 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 (toolbox.debugTargetInfo.targetType.*): This is displayed as the
+# alt attribute for an icon in the toolbox header in about:devtools-toolbox,
+# to indicate what is the type of the debug target being inspected.
+toolbox.debugTargetInfo.targetType.extension=Extension
+toolbox.debugTargetInfo.targetType.process=Process
+toolbox.debugTargetInfo.targetType.tab=Tab
+toolbox.debugTargetInfo.targetType.worker=Worker
+
 # 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.
 browserToolbox.statusMessage=Browser Toolbox connection status:
 
 # LOCALIZATION NOTE (toolbox.replay.jumpMessage): This is the label
 # shown in the web replay timeline marker
 toolbox.replay.jumpMessage=Jump to message %1$S
--- a/devtools/client/themes/toolbox.css
+++ b/devtools/client/themes/toolbox.css
@@ -33,16 +33,21 @@
   padding: 0 24px;
   white-space: nowrap;
 }
 
 .debug-target-info .iconized-label:not(:last-child) {
   border-inline-end: 1px solid var(--theme-splitter-color);
 }
 
+.debug-target-info .iconized-label img {
+  width: 20px;
+  height: 20px;
+}
+
 .debug-target-info img {
   -moz-context-properties: fill;
   fill: var(--theme-toolbar-icon-color);
 }
 
 /* Toolbox tabbar */
 
 .devtools-tabbar {