Bug 1505131: Show error message when the connecting was failed. r=jdescottes,flod
authorDaisuke Akatsuka <dakatsuka@mozilla.com>
Tue, 02 Apr 2019 06:44:34 +0000
changeset 467524 67c4c04fe27c37cf540d4f03c7e246c5c78a5d62
parent 467523 e7244491701593d2d1ee0e31bc48db08ccf43859
child 467525 1fc7cb8410278022f2d31f9fb00de6d67c52b192
push id35802
push usercbrindusan@mozilla.com
push dateTue, 02 Apr 2019 15:46:39 +0000
treeherdermozilla-central@2eb225d3082f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjdescottes, flod
bugs1505131
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 1505131: Show error message when the connecting was failed. r=jdescottes,flod Depends on D25032 Differential Revision: https://phabricator.services.mozilla.com/D25033
devtools/client/aboutdebugging-new/src/actions/runtimes.js
devtools/client/aboutdebugging-new/src/base.css
devtools/client/aboutdebugging-new/src/components/sidebar/Sidebar.js
devtools/client/aboutdebugging-new/src/components/sidebar/SidebarRuntimeItem.js
devtools/client/aboutdebugging-new/src/reducers/runtimes-state.js
devtools/client/aboutdebugging-new/src/types/runtime.js
devtools/client/locales/en-US/aboutdebugging.ftl
--- a/devtools/client/aboutdebugging-new/src/actions/runtimes.js
+++ b/devtools/client/aboutdebugging-new/src/actions/runtimes.js
@@ -140,16 +140,17 @@ function connectRuntime(id) {
   };
 }
 
 function createThisFirefoxRuntime() {
   return (dispatch, getState) => {
     const thisFirefoxRuntime = {
       id: RUNTIMES.THIS_FIREFOX,
       isConnecting: false,
+      isConnectionFailed: false,
       isUnknown: false,
       name: l10n.getString("about-debugging-this-firefox-runtime-name"),
       type: RUNTIMES.THIS_FIREFOX,
     };
     dispatch({ type: THIS_FIREFOX_RUNTIME_CREATED, runtime: thisFirefoxRuntime });
   };
 }
 
@@ -299,16 +300,17 @@ function updateNetworkRuntimes(locations
   const runtimes = locations.map(location => {
     const [ host, port ] = location.split(":");
     return {
       id: location,
       extra: {
         connectionParameters: { host, port: parseInt(port, 10) },
       },
       isConnecting: false,
+      isConnectionFailed: false,
       isUnknown: false,
       name: location,
       type: RUNTIMES.NETWORK,
     };
   });
   return updateRemoteRuntimes(runtimes, RUNTIMES.NETWORK);
 }
 
@@ -320,16 +322,17 @@ function updateUSBRuntimes(adbRuntimes) 
     const connectionParameters = adbRuntime.isUnknown() ? null : { deviceId, socketPath };
     return {
       id: adbRuntime.id,
       extra: {
         connectionParameters,
         deviceName: adbRuntime.deviceName,
       },
       isConnecting: false,
+      isConnectionFailed: false,
       isUnknown: adbRuntime.isUnknown(),
       name: adbRuntime.shortName,
       type: RUNTIMES.USB,
     };
   });
   return updateRemoteRuntimes(runtimes, RUNTIMES.USB);
 }
 
@@ -365,22 +368,25 @@ function updateRemoteRuntimes(runtimes, 
       // `unwatchRuntime` correctly.
       await dispatch(Actions.selectPage(PAGE_TYPES.RUNTIME, RUNTIMES.THIS_FIREFOX));
     }
 
     // For existing runtimes, transfer all properties that are not available in the
     // runtime objects passed to this method:
     // - runtimeDetails (set by about:debugging after a successful connection)
     // - isConnecting (set by about:debugging during the connection)
+    // - isConnectionFailed (set by about:debugging if connection was failed)
     runtimes.forEach(runtime => {
       const existingRuntime = findRuntimeById(runtime.id, getState().runtimes);
       const isConnectionValid = existingRuntime && existingRuntime.runtimeDetails &&
         !existingRuntime.runtimeDetails.clientWrapper.isClosed();
       runtime.runtimeDetails = isConnectionValid ? existingRuntime.runtimeDetails : null;
       runtime.isConnecting = existingRuntime ? existingRuntime.isConnecting : false;
+      runtime.isConnectionFailed =
+        existingRuntime ? existingRuntime.isConnectionFailed : false;
     });
 
     const existingRuntimes = getAllRuntimes(getState().runtimes);
     for (const runtime of existingRuntimes) {
       // Runtime was connected before.
       const isConnected = runtime.runtimeDetails;
       // Runtime is of the same type as the updated runtimes array, so we should check it.
       const isSameType = runtime.type === type;
--- a/devtools/client/aboutdebugging-new/src/base.css
+++ b/devtools/client/aboutdebugging-new/src/base.css
@@ -158,16 +158,21 @@ p, h1 {
 
 /* Links that need to look like current text */
 .undecorated-link,
 .undecorated-link:hover {
   text-decoration: none;
   color: currentColor;
 }
 
+/* Text needs to wrap anywhere */
+.word-wrap-anywhere {
+  word-wrap: anywhere;
+}
+
 /*
 * Typography
 */
 
 /* Main style for heading (i.e. h1) */
 .main-heading {
   font-size: var(--display-20-font-size);
   font-weight: var(--display-20-font-weight);
--- a/devtools/client/aboutdebugging-new/src/components/sidebar/Sidebar.js
+++ b/devtools/client/aboutdebugging-new/src/components/sidebar/Sidebar.js
@@ -109,16 +109,17 @@ class Sidebar extends PureComponent {
 
       return SidebarRuntimeItem({
         deviceName: runtime.extra.deviceName,
         dispatch,
         icon,
         key: keyId,
         isConnected: runtimeHasDetails,
         isConnecting: runtime.isConnecting,
+        isConnectionFailed: runtime.isConnectionFailed,
         isSelected,
         isUnknown: runtime.isUnknown,
         name,
         runtimeId: runtime.id,
       });
     });
   }
 
--- a/devtools/client/aboutdebugging-new/src/components/sidebar/SidebarRuntimeItem.js
+++ b/devtools/client/aboutdebugging-new/src/components/sidebar/SidebarRuntimeItem.js
@@ -6,32 +6,35 @@
 
 const { createFactory, 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 FluentReact = require("devtools/client/shared/vendor/fluent-react");
 const Localized = createFactory(FluentReact.Localized);
 
+const Message = createFactory(require("../shared/Message"));
 const SidebarItem = createFactory(require("./SidebarItem"));
 const Actions = require("../../actions/index");
+const { MESSAGE_LEVEL } = require("../../constants");
 
 /**
  * This component displays a runtime item of the Sidebar component.
  */
 class SidebarRuntimeItem extends PureComponent {
   static get propTypes() {
     return {
       deviceName: PropTypes.string,
       dispatch: PropTypes.func.isRequired,
       // Provided by wrapping the component with FluentReact.withLocalization.
       getString: PropTypes.func.isRequired,
       icon: PropTypes.string.isRequired,
       isConnected: PropTypes.bool.isRequired,
       isConnecting: PropTypes.bool.isRequired,
+      isConnectionFailed: PropTypes.bool.isRequired,
       isSelected: PropTypes.bool.isRequired,
       isUnknown: PropTypes.bool.isRequired,
       name: PropTypes.string.isRequired,
       runtimeId: PropTypes.string.isRequired,
     };
   }
 
   renderConnectButton() {
@@ -52,16 +55,40 @@ class SidebarRuntimeItem extends PureCom
             dispatch(Actions.connectRuntime(runtimeId));
           },
         },
         localizationId
       )
     );
   }
 
+  renderConnectionError() {
+    const { isConnectionFailed } = this.props;
+
+    if (!isConnectionFailed) {
+      return null;
+    }
+
+    const localizationId =
+      "about-debugging-sidebar-item-connect-button-connection-failed";
+
+    return Message(
+      {
+        level: MESSAGE_LEVEL.ERROR,
+        key: "connection-error",
+      },
+      Localized(
+        {
+          id: localizationId,
+        },
+        dom.p({ className: "word-wrap-anywhere" }, localizationId)
+      )
+    );
+  }
+
   renderName() {
     const { deviceName, getString, isUnknown, name } = this.props;
 
     const displayName = isUnknown ?
       getString("about-debugging-sidebar-runtime-item-waiting-for-browser") : name;
 
     const localizationId = deviceName
       ? "about-debugging-sidebar-runtime-item-name"
@@ -116,34 +143,38 @@ class SidebarRuntimeItem extends PureCom
       isUnknown,
       runtimeId,
     } = this.props;
 
     const connectionStatus = isConnected ?
       getString("aboutdebugging-sidebar-runtime-connection-status-connected") :
       getString("aboutdebugging-sidebar-runtime-connection-status-disconnected");
 
-    return SidebarItem(
-      {
-        className: "sidebar-item--tall",
-        isSelected,
-        to: isConnected ? `/runtime/${encodeURIComponent(runtimeId)}` : null,
-      },
-      dom.section(
+    return [
+      SidebarItem(
         {
-          className: "sidebar-runtime-item__container",
+          className: "sidebar-item--tall",
+          key: "sidebar-item",
+          isSelected,
+          to: isConnected ? `/runtime/${encodeURIComponent(runtimeId)}` : null,
         },
-        dom.img(
+        dom.section(
           {
-            className: "sidebar-runtime-item__icon ",
-            src: icon,
-            alt: connectionStatus,
-            title: connectionStatus,
-          }
+            className: "sidebar-runtime-item__container",
+          },
+          dom.img(
+            {
+              className: "sidebar-runtime-item__icon ",
+              src: icon,
+              alt: connectionStatus,
+              title: connectionStatus,
+            }
+          ),
+          this.renderName(),
+          !isUnknown && !isConnected ? this.renderConnectButton() : null
         ),
-        this.renderName(),
-        !isUnknown && !isConnected ? this.renderConnectButton() : null
-      )
-    );
+      ),
+      this.renderConnectionError(),
+    ];
   }
 }
 
 module.exports = FluentReact.withLocalization(SidebarRuntimeItem);
--- a/devtools/client/aboutdebugging-new/src/reducers/runtimes-state.js
+++ b/devtools/client/aboutdebugging-new/src/reducers/runtimes-state.js
@@ -71,28 +71,31 @@ function _updateRuntimeById(runtimeId, u
   });
   return Object.assign({}, state, { [key]: updatedRuntimes });
 }
 
 function runtimesReducer(state = RuntimesState(), action) {
   switch (action.type) {
     case CONNECT_RUNTIME_START: {
       const { id } = action;
-      return _updateRuntimeById(id, { isConnecting: true }, state);
+      return _updateRuntimeById(
+        id, { isConnecting: true, isConnectionFailed: false }, state);
     }
 
     case CONNECT_RUNTIME_SUCCESS: {
       const { id, runtimeDetails, type } = action.runtime;
       remoteClientManager.setClient(id, type, runtimeDetails.clientWrapper.client);
-      return _updateRuntimeById(id, { isConnecting: false, runtimeDetails }, state);
+      return _updateRuntimeById(
+        id, { isConnecting: false, isConnectionFailed: false, runtimeDetails }, state);
     }
 
     case CONNECT_RUNTIME_FAILURE: {
       const { id } = action;
-      return _updateRuntimeById(id, { isConnecting: false }, state);
+      return _updateRuntimeById(
+        id, { isConnecting: false, isConnectionFailed: true }, state);
     }
 
     case DISCONNECT_RUNTIME_SUCCESS: {
       const { id, type } = action.runtime;
       remoteClientManager.removeClient(id, type);
       return _updateRuntimeById(id, { runtimeDetails: null }, state);
     }
 
--- a/devtools/client/aboutdebugging-new/src/types/runtime.js
+++ b/devtools/client/aboutdebugging-new/src/types/runtime.js
@@ -114,16 +114,19 @@ const runtime = {
   // object containing non standard properties that depend on the runtime type,
   // unavailable on this-firefox runtime
   extra: PropTypes.shape(runtimeExtra),
 
   // this flag will be true when start to connect to the runtime, will be false after
   // connected or has failures.
   isConnecting: PropTypes.bool.isRequired,
 
+  // this flag will be true when the connection failed.
+  isConnectionFailed: PropTypes.bool.isRequired,
+
   // unknown runtimes are placeholders for devices where the runtime has not been started
   // yet. For instance an ADB device connected without a compatible runtime running.
   isUnknown: PropTypes.bool.isRequired,
 
   // display name of the runtime
   name: PropTypes.string.isRequired,
 
   // available after the connection to the runtime is established
--- a/devtools/client/locales/en-US/aboutdebugging.ftl
+++ b/devtools/client/locales/en-US/aboutdebugging.ftl
@@ -44,16 +44,19 @@ about-debugging-sidebar-no-devices = No 
 
 # Text displayed in buttons found in sidebar items representing remote runtimes.
 # Clicking on the button will attempt to connect to the runtime.
 about-debugging-sidebar-item-connect-button = Connect
 
 # Text displayed in buttons found in sidebar items when the runtime is connecting.
 about-debugging-sidebar-item-connect-button-connecting = Connecting…
 
+# Text displayed in buttons found in sidebar items when the connection failed.
+about-debugging-sidebar-item-connect-button-connection-failed = Connection failed
+
 # Temporary text displayed in sidebar items representing remote runtimes after
 # successfully connecting to them. Temporary UI, do not localize.
 about-debugging-sidebar-item-connected-label = Connected
 
 # Text displayed in sidebar items for remote devices where a compatible browser (eg
 # Firefox) has not been detected yet. Typically, Android phones connected via USB with
 # USB debugging enabled, but where Firefox is not started.
 about-debugging-sidebar-runtime-item-waiting-for-browser = Waiting for browser…