Bug 1505131: Show warning when the connecting is taking time. r=jdescottes,flod
authorDaisuke Akatsuka <dakatsuka@mozilla.com>
Tue, 02 Apr 2019 06:22:33 +0000
changeset 467529 1fc7cb8410278022f2d31f9fb00de6d67c52b192
parent 467528 67c4c04fe27c37cf540d4f03c7e246c5c78a5d62
child 467530 3737b3b3acb0d45b1fbb2d11fc99916df80a7ea6
push id112633
push usercbrindusan@mozilla.com
push dateTue, 02 Apr 2019 15:52:18 +0000
treeherdermozilla-inbound@a6c6359636f7 [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 warning when the connecting is taking time. r=jdescottes,flod Depends on D25033 Differential Revision: https://phabricator.services.mozilla.com/D25034
devtools/client/aboutdebugging-new/src/actions/runtimes.js
devtools/client/aboutdebugging-new/src/components/sidebar/Sidebar.js
devtools/client/aboutdebugging-new/src/components/sidebar/SidebarRuntimeItem.js
devtools/client/aboutdebugging-new/src/constants.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
@@ -19,16 +19,17 @@ const {
   isSupportedDebugTargetPane,
 } = require("../modules/debug-target-support");
 
 const { remoteClientManager } =
   require("devtools/client/shared/remote-debugging/remote-client-manager");
 
 const {
   CONNECT_RUNTIME_FAILURE,
+  CONNECT_RUNTIME_NOT_RESPONDING,
   CONNECT_RUNTIME_START,
   CONNECT_RUNTIME_SUCCESS,
   DEBUG_TARGET_PANE,
   DISCONNECT_RUNTIME_FAILURE,
   DISCONNECT_RUNTIME_START,
   DISCONNECT_RUNTIME_SUCCESS,
   PAGE_TYPES,
   REMOTE_RUNTIMES_UPDATED,
@@ -47,16 +48,18 @@ const {
   UPDATE_RUNTIME_MULTIE10S_FAILURE,
   UPDATE_RUNTIME_MULTIE10S_START,
   UPDATE_RUNTIME_MULTIE10S_SUCCESS,
   WATCH_RUNTIME_FAILURE,
   WATCH_RUNTIME_START,
   WATCH_RUNTIME_SUCCESS,
 } = require("../constants");
 
+const CONNECTION_TIMING_OUT_DELAY = 3000;
+
 async function getRuntimeIcon(channel) {
   return (channel === "release" || channel === "beta" || channel === "aurora")
     ? `chrome://devtools/skin/images/aboutdebugging-firefox-${ channel }.svg`
     : "chrome://devtools/skin/images/aboutdebugging-firefox-nightly.svg";
 }
 
 function onRemoteDebuggerClientClosed() {
   window.AboutDebugging.onNetworkLocationsUpdated();
@@ -65,16 +68,23 @@ function onRemoteDebuggerClientClosed() 
 
 function onMultiE10sUpdated() {
   window.AboutDebugging.store.dispatch(updateMultiE10s());
 }
 
 function connectRuntime(id) {
   return async (dispatch, getState) => {
     dispatch({ type: CONNECT_RUNTIME_START, id });
+    const connectionNotRespondingTimer = setTimeout(() => {
+      // If connecting to the runtime takes time over CONNECTION_TIMING_OUT_DELAY,
+      // we assume the connection prompt is showing on the runtime, show a dialog
+      // to let user know that.
+      dispatch({ type: CONNECT_RUNTIME_NOT_RESPONDING, id });
+    }, CONNECTION_TIMING_OUT_DELAY);
+
     try {
       const runtime = findRuntimeById(id, getState().runtimes);
       const clientWrapper = await createClientForRuntime(runtime);
 
       const deviceDescription = await clientWrapper.getDeviceDescription();
       const compatibilityReport = await clientWrapper.checkVersionCompatibility();
       const icon = await getRuntimeIcon(deviceDescription.channel);
 
@@ -131,26 +141,29 @@ function connectRuntime(id) {
         runtime: {
           id,
           runtimeDetails,
           type: runtime.type,
         },
       });
     } catch (e) {
       dispatch({ type: CONNECT_RUNTIME_FAILURE, id, error: e });
+    } finally {
+      clearTimeout(connectionNotRespondingTimer);
     }
   };
 }
 
 function createThisFirefoxRuntime() {
   return (dispatch, getState) => {
     const thisFirefoxRuntime = {
       id: RUNTIMES.THIS_FIREFOX,
       isConnecting: false,
       isConnectionFailed: false,
+      isConnectionNotResponding: false,
       isUnknown: false,
       name: l10n.getString("about-debugging-this-firefox-runtime-name"),
       type: RUNTIMES.THIS_FIREFOX,
     };
     dispatch({ type: THIS_FIREFOX_RUNTIME_CREATED, runtime: thisFirefoxRuntime });
   };
 }
 
@@ -301,16 +314,17 @@ function updateNetworkRuntimes(locations
     const [ host, port ] = location.split(":");
     return {
       id: location,
       extra: {
         connectionParameters: { host, port: parseInt(port, 10) },
       },
       isConnecting: false,
       isConnectionFailed: false,
+      isConnectionNotResponding: false,
       isUnknown: false,
       name: location,
       type: RUNTIMES.NETWORK,
     };
   });
   return updateRemoteRuntimes(runtimes, RUNTIMES.NETWORK);
 }
 
@@ -323,16 +337,17 @@ function updateUSBRuntimes(adbRuntimes) 
     return {
       id: adbRuntime.id,
       extra: {
         connectionParameters,
         deviceName: adbRuntime.deviceName,
       },
       isConnecting: false,
       isConnectionFailed: false,
+      isConnectionNotResponding: false,
       isUnknown: adbRuntime.isUnknown(),
       name: adbRuntime.shortName,
       type: RUNTIMES.USB,
     };
   });
   return updateRemoteRuntimes(runtimes, RUNTIMES.USB);
 }
 
@@ -369,24 +384,28 @@ function updateRemoteRuntimes(runtimes, 
       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)
+    // - isConnectionNotResponding
+    //     (set by about:debugging if connection is taking too much time)
     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;
+      runtime.isConnectionNotResponding =
+        existingRuntime ? existingRuntime.isConnectionNotResponding : 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/components/sidebar/Sidebar.js
+++ b/devtools/client/aboutdebugging-new/src/components/sidebar/Sidebar.js
@@ -110,16 +110,17 @@ class Sidebar extends PureComponent {
       return SidebarRuntimeItem({
         deviceName: runtime.extra.deviceName,
         dispatch,
         icon,
         key: keyId,
         isConnected: runtimeHasDetails,
         isConnecting: runtime.isConnecting,
         isConnectionFailed: runtime.isConnectionFailed,
+        isConnectionNotResponding: runtime.isConnectionNotResponding,
         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
@@ -25,16 +25,17 @@ class SidebarRuntimeItem extends PureCom
       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,
+      isConnectionNotResponding: PropTypes.bool.isRequired,
       isSelected: PropTypes.bool.isRequired,
       isUnknown: PropTypes.bool.isRequired,
       name: PropTypes.string.isRequired,
       runtimeId: PropTypes.string.isRequired,
     };
   }
 
   renderConnectButton() {
@@ -79,16 +80,40 @@ class SidebarRuntimeItem extends PureCom
         {
           id: localizationId,
         },
         dom.p({ className: "word-wrap-anywhere" }, localizationId)
       )
     );
   }
 
+  renderConnectionNotResponding() {
+    const { isConnectionNotResponding } = this.props;
+
+    if (!isConnectionNotResponding) {
+      return null;
+    }
+
+    const localizationId =
+      "about-debugging-sidebar-item-connect-button-connection-not-responding";
+
+    return Message(
+      {
+        level: MESSAGE_LEVEL.WARNING,
+        key: "connection-not-responding",
+      },
+      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"
@@ -168,13 +193,14 @@ class SidebarRuntimeItem extends PureCom
               title: connectionStatus,
             }
           ),
           this.renderName(),
           !isUnknown && !isConnected ? this.renderConnectButton() : null
         ),
       ),
       this.renderConnectionError(),
+      this.renderConnectionNotResponding(),
     ];
   }
 }
 
 module.exports = FluentReact.withLocalization(SidebarRuntimeItem);
--- a/devtools/client/aboutdebugging-new/src/constants.js
+++ b/devtools/client/aboutdebugging-new/src/constants.js
@@ -11,16 +11,17 @@ const actionTypes = {
   ADB_ADDON_INSTALL_START: "ADB_ADDON_INSTALL_START",
   ADB_ADDON_INSTALL_SUCCESS: "ADB_ADDON_INSTALL_SUCCESS",
   ADB_ADDON_INSTALL_FAILURE: "ADB_ADDON_INSTALL_FAILURE",
   ADB_ADDON_UNINSTALL_START: "ADB_ADDON_UNINSTALL_START",
   ADB_ADDON_UNINSTALL_SUCCESS: "ADB_ADDON_UNINSTALL_SUCCESS",
   ADB_ADDON_UNINSTALL_FAILURE: "ADB_ADDON_UNINSTALL_FAILURE",
   ADB_ADDON_STATUS_UPDATED: "ADB_ADDON_STATUS_UPDATED",
   CONNECT_RUNTIME_FAILURE: "CONNECT_RUNTIME_FAILURE",
+  CONNECT_RUNTIME_NOT_RESPONDING: "CONNECT_RUNTIME_NOT_RESPONDING",
   CONNECT_RUNTIME_START: "CONNECT_RUNTIME_START",
   CONNECT_RUNTIME_SUCCESS: "CONNECT_RUNTIME_SUCCESS",
   DEBUG_TARGET_COLLAPSIBILITY_UPDATED: "DEBUG_TARGET_COLLAPSIBILITY_UPDATED",
   DISCONNECT_RUNTIME_FAILURE: "DISCONNECT_RUNTIME_FAILURE",
   DISCONNECT_RUNTIME_START: "DISCONNECT_RUNTIME_START",
   DISCONNECT_RUNTIME_SUCCESS: "DISCONNECT_RUNTIME_SUCCESS",
   HIDE_PROFILER_DIALOG: "HIDE_PROFILER_DIALOG",
   NETWORK_LOCATIONS_UPDATED: "NETWORK_LOCATIONS_UPDATED",
--- a/devtools/client/aboutdebugging-new/src/reducers/runtimes-state.js
+++ b/devtools/client/aboutdebugging-new/src/reducers/runtimes-state.js
@@ -1,16 +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 {
   CONNECT_RUNTIME_FAILURE,
+  CONNECT_RUNTIME_NOT_RESPONDING,
   CONNECT_RUNTIME_START,
   CONNECT_RUNTIME_SUCCESS,
   DISCONNECT_RUNTIME_SUCCESS,
   RUNTIMES,
   UPDATE_CONNECTION_PROMPT_SETTING_SUCCESS,
   UPDATE_EXTENSION_DEBUG_SETTING_SUCCESS,
   UPDATE_RUNTIME_MULTIE10S_SUCCESS,
   REMOTE_RUNTIMES_UPDATED,
@@ -71,31 +72,49 @@ 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, isConnectionFailed: false }, state);
+      const updatedState = {
+        isConnecting: true,
+        isConnectionFailed: false,
+        isConnectionNotResponding: false,
+      };
+      return _updateRuntimeById(id, updatedState, state);
+    }
+
+    case CONNECT_RUNTIME_NOT_RESPONDING: {
+      const { id } = action;
+      return _updateRuntimeById(id, { isConnectionNotResponding: true }, state);
     }
 
     case CONNECT_RUNTIME_SUCCESS: {
       const { id, runtimeDetails, type } = action.runtime;
       remoteClientManager.setClient(id, type, runtimeDetails.clientWrapper.client);
-      return _updateRuntimeById(
-        id, { isConnecting: false, isConnectionFailed: false, runtimeDetails }, state);
+      const updatedState = {
+        isConnecting: false,
+        isConnectionFailed: false,
+        isConnectionNotResponding: false,
+        runtimeDetails,
+      };
+      return _updateRuntimeById(id, updatedState, state);
     }
 
     case CONNECT_RUNTIME_FAILURE: {
       const { id } = action;
-      return _updateRuntimeById(
-        id, { isConnecting: false, isConnectionFailed: true }, state);
+      const updatedState = {
+        isConnecting: false,
+        isConnectionFailed: true,
+        isConnectionNotResponding: false,
+      };
+      return _updateRuntimeById(id, updatedState, 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
@@ -117,16 +117,20 @@ const runtime = {
 
   // 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,
 
+  // will be true if connecting to runtime is taking time, will be false after connecting
+  // or failing.
+  isConnectionNotResponding: 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
@@ -47,16 +47,20 @@ about-debugging-sidebar-no-devices = No 
 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
 
+# Text displayed in connection warning on sidebar item of the runtime when connecting to
+# the runtime is taking too much time.
+about-debugging-sidebar-item-connect-button-connection-not-responding = Connection still pending, check for messages on the target browser
+
 # 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…