Bug 1488506 - Add button to enable/disable USB debugging in Connect page;r=ladybenko,daisuke
authorJulian Descottes <jdescottes@mozilla.com>
Wed, 17 Oct 2018 08:47:30 +0000
changeset 500396 97207813052bd7a33c671422198b5d1e43adab49
parent 500395 3e2d47ca7a2a199ab58bf0b7605882a205e6cece
child 500397 cac4aff89a39a7df33305397268510e8c7d2d840
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersladybenko, daisuke
bugs1488506
milestone64.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 1488506 - Add button to enable/disable USB debugging in Connect page;r=ladybenko,daisuke Differential Revision: https://phabricator.services.mozilla.com/D8556
devtools/client/aboutdebugging-new/aboutdebugging.css
devtools/client/aboutdebugging-new/src/actions/ui.js
devtools/client/aboutdebugging-new/src/components/App.js
devtools/client/aboutdebugging-new/src/components/connect/ConnectPage.css
devtools/client/aboutdebugging-new/src/components/connect/ConnectPage.js
devtools/client/aboutdebugging-new/src/components/connect/moz.build
devtools/client/aboutdebugging-new/src/constants.js
devtools/client/aboutdebugging-new/tmp-locale/en-US/aboutdebugging.notftl
--- a/devtools/client/aboutdebugging-new/aboutdebugging.css
+++ b/devtools/client/aboutdebugging-new/aboutdebugging.css
@@ -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/. */
 
 @import "chrome://global/skin/in-content/common.css";
 @import "resource://devtools/client/themes/variables.css";
 @import "resource://devtools/client/aboutdebugging-new/src/components/App.css";
 @import "resource://devtools/client/aboutdebugging-new/src/components/RuntimeInfo.css";
+@import "resource://devtools/client/aboutdebugging-new/src/components/connect/ConnectPage.css";
 @import "resource://devtools/client/aboutdebugging-new/src/components/connect/ConnectSteps.css";
 @import "resource://devtools/client/aboutdebugging-new/src/components/connect/NetworkLocationsForm.css";
 @import "resource://devtools/client/aboutdebugging-new/src/components/connect/NetworkLocationsList.css";
 @import "resource://devtools/client/aboutdebugging-new/src/components/debugtarget/DebugTargetItem.css";
 @import "resource://devtools/client/aboutdebugging-new/src/components/debugtarget/DebugTargetList.css";
 @import "resource://devtools/client/aboutdebugging-new/src/components/debugtarget/DebugTargetPane.css";
 @import "resource://devtools/client/aboutdebugging-new/src/components/debugtarget/ExtensionDetail.css";
 @import "resource://devtools/client/aboutdebugging-new/src/components/debugtarget/WorkerDetail.css";
--- a/devtools/client/aboutdebugging-new/src/actions/ui.js
+++ b/devtools/client/aboutdebugging-new/src/actions/ui.js
@@ -1,23 +1,30 @@
 /* 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 {
+  ADB_ADDON_INSTALL_START,
+  ADB_ADDON_INSTALL_SUCCESS,
+  ADB_ADDON_INSTALL_FAILURE,
+  ADB_ADDON_UNINSTALL_START,
+  ADB_ADDON_UNINSTALL_SUCCESS,
+  ADB_ADDON_UNINSTALL_FAILURE,
   ADB_ADDON_STATUS_UPDATED,
   DEBUG_TARGET_COLLAPSIBILITY_UPDATED,
   NETWORK_LOCATIONS_UPDATED,
   PAGE_SELECTED,
   PAGES,
 } = require("../constants");
 
 const NetworkLocationsModule = require("../modules/network-locations");
+const { adbAddon } = require("devtools/shared/adb/adb-addon");
 
 const Actions = require("./index");
 
 // XXX: Isolating the code here, because it feels wrong to rely solely on the page "not"
 // being CONNECT to decide what to do. Should we have a page "type" on top of page "id"?
 function _isRuntimePage(page) {
   return page && page !== PAGES.CONNECT;
 }
@@ -64,16 +71,44 @@ function removeNetworkLocation(location)
 function updateAdbAddonStatus(adbAddonStatus) {
   return { type: ADB_ADDON_STATUS_UPDATED, adbAddonStatus };
 }
 
 function updateNetworkLocations(locations) {
   return { type: NETWORK_LOCATIONS_UPDATED, locations };
 }
 
+function installAdbAddon() {
+  return async (dispatch, getState) => {
+    dispatch({ type: ADB_ADDON_INSTALL_START });
+
+    try {
+      await adbAddon.install();
+      dispatch({ type: ADB_ADDON_INSTALL_SUCCESS });
+    } catch (e) {
+      dispatch({ type: ADB_ADDON_INSTALL_FAILURE, error: e.message });
+    }
+  };
+}
+
+function uninstallAdbAddon() {
+  return async (dispatch, getState) => {
+    dispatch({ type: ADB_ADDON_UNINSTALL_START });
+
+    try {
+      await adbAddon.uninstall();
+      dispatch({ type: ADB_ADDON_UNINSTALL_SUCCESS });
+    } catch (e) {
+      dispatch({ type: ADB_ADDON_UNINSTALL_FAILURE, error: e.message });
+    }
+  };
+}
+
 module.exports = {
   addNetworkLocation,
+  installAdbAddon,
   removeNetworkLocation,
   selectPage,
+  uninstallAdbAddon,
   updateAdbAddonStatus,
   updateDebugTargetCollapsibility,
   updateNetworkLocations,
 };
--- a/devtools/client/aboutdebugging-new/src/components/App.js
+++ b/devtools/client/aboutdebugging-new/src/components/App.js
@@ -31,26 +31,35 @@ class App extends PureComponent {
       networkLocations: PropTypes.arrayOf(PropTypes.string).isRequired,
       networkRuntimes: PropTypes.arrayOf(Types.runtime).isRequired,
       selectedPage: PropTypes.string,
       usbRuntimes: PropTypes.arrayOf(Types.runtime).isRequired,
     };
   }
 
   getSelectedPageComponent() {
-    const { dispatch, networkLocations, selectedPage } = this.props;
+    const {
+      adbAddonStatus,
+      dispatch,
+      networkLocations,
+      selectedPage
+    } = this.props;
 
     if (!selectedPage) {
       // No page selected.
       return null;
     }
 
     switch (selectedPage) {
       case PAGES.CONNECT:
-        return ConnectPage({ dispatch, networkLocations });
+        return ConnectPage({
+          adbAddonStatus,
+          dispatch,
+          networkLocations
+        });
       default:
         // All pages except for the CONNECT page are RUNTIME pages.
         return RuntimePage({ dispatch });
     }
   }
 
   render() {
     const {
new file mode 100644
--- /dev/null
+++ b/devtools/client/aboutdebugging-new/src/components/connect/ConnectPage.css
@@ -0,0 +1,7 @@
+/* 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/. */
+
+.connect-page__usb__toggle-button {
+  margin-top: calc(var(--base-distance) * 4);
+}
--- a/devtools/client/aboutdebugging-new/src/components/connect/ConnectPage.js
+++ b/devtools/client/aboutdebugging-new/src/components/connect/ConnectPage.js
@@ -6,28 +6,37 @@
 
 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 {
+  USB_STATES,
+} = require("../../constants");
+
+const Actions = require("../../actions/index");
+
+loader.lazyRequireGetter(this, "ADB_ADDON_STATES", "devtools/shared/adb/adb-addon", true);
+
 const ConnectSection = createFactory(require("./ConnectSection"));
 const ConnectSteps = createFactory(require("./ConnectSteps"));
 const NetworkLocationsForm = createFactory(require("./NetworkLocationsForm"));
 const NetworkLocationsList = createFactory(require("./NetworkLocationsList"));
 
 const USB_ICON_SRC = "chrome://devtools/skin/images/aboutdebugging-connect-icon.svg";
 const WIFI_ICON_SRC = "chrome://devtools/skin/images/aboutdebugging-connect-icon.svg";
 const GLOBE_ICON_SRC = "chrome://devtools/skin/images/aboutdebugging-globe-icon.svg";
 
 class ConnectPage extends PureComponent {
   static get propTypes() {
     return {
+      adbAddonStatus: PropTypes.string,
       dispatch: PropTypes.func.isRequired,
       // Provided by wrapping the component with FluentReact.withLocalization.
       getString: PropTypes.func.isRequired,
       networkLocations: PropTypes.arrayOf(PropTypes.string).isRequired,
     };
   }
 
   renderWifi() {
@@ -49,35 +58,98 @@ class ConnectPage extends PureComponent 
             getString("about-debugging-connect-wifi-step-open-options"),
             getString("about-debugging-connect-wifi-step-enable-debug"),
           ]
         })
       )
     );
   }
 
+  onToggleUSBClick() {
+    const { adbAddonStatus } = this.props;
+    const isAddonInstalled = adbAddonStatus === ADB_ADDON_STATES.INSTALLED;
+    if (isAddonInstalled) {
+      this.props.dispatch(Actions.uninstallAdbAddon());
+    } else {
+      this.props.dispatch(Actions.installAdbAddon());
+    }
+  }
+
+  getUsbStatus() {
+    switch (this.props.adbAddonStatus) {
+      case ADB_ADDON_STATES.INSTALLED:
+        return USB_STATES.ENABLED_USB;
+      case ADB_ADDON_STATES.UNINSTALLED:
+        return USB_STATES.DISABLED_USB;
+      default:
+        return USB_STATES.UPDATING_USB;
+    }
+  }
+
+  renderUsbToggleButton() {
+    const usbStatus = this.getUsbStatus();
+
+    const localizedStates = {
+      [USB_STATES.ENABLED_USB]: "about-debugging-connect-usb-disable-button",
+      [USB_STATES.DISABLED_USB]: "about-debugging-connect-usb-enable-button",
+      [USB_STATES.UPDATING_USB]: "about-debugging-connect-usb-updating-button",
+    };
+    const localizedState = localizedStates[usbStatus];
+
+    // Disable the button while the USB status is updating.
+    const disabled = usbStatus === USB_STATES.UPDATING_USB;
+
+    return Localized(
+      {
+        id: localizedState
+      },
+      dom.button(
+        {
+          className: "std-button connect-page__usb__toggle-button",
+          disabled,
+          onClick: () => this.onToggleUSBClick(),
+        },
+        localizedState
+      )
+    );
+  }
+
   renderUsb() {
-    const { getString } = this.props;
+    const { adbAddonStatus, getString } = this.props;
+    const isAddonInstalled = adbAddonStatus === ADB_ADDON_STATES.INSTALLED;
     return Localized(
       {
         id: "about-debugging-connect-usb",
         attrs: { title: true }
       },
       ConnectSection(
         {
           icon: USB_ICON_SRC,
           title: "Via USB",
         },
-        ConnectSteps({
-          steps: [
-            getString("about-debugging-connect-usb-step-enable-dev-menu"),
-            getString("about-debugging-connect-usb-step-enable-debug"),
-            getString("about-debugging-connect-usb-step-plug-device"),
-          ]
-        })
+        (isAddonInstalled ?
+          ConnectSteps({
+            steps: [
+              getString("about-debugging-connect-usb-step-enable-dev-menu"),
+              getString("about-debugging-connect-usb-step-enable-debug"),
+              getString("about-debugging-connect-usb-step-plug-device"),
+            ]
+          }) :
+          Localized(
+            {
+              id: "about-debugging-connect-usb-disabled",
+            },
+            dom.aside(
+              {},
+              "Enabling this will download and add the required Android USB debugging " +
+              "components to Firefox."
+            )
+          )
+        ),
+        this.renderUsbToggleButton()
       )
     );
   }
 
   renderNetwork() {
     const { dispatch, networkLocations } = this.props;
     return Localized(
       {
--- a/devtools/client/aboutdebugging-new/src/components/connect/moz.build
+++ b/devtools/client/aboutdebugging-new/src/components/connect/moz.build
@@ -1,13 +1,14 @@
 # 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/.
 
 DevToolsModules(
+    'ConnectPage.css',
     'ConnectPage.js',
     'ConnectSection.js',
     'ConnectSteps.css',
     'ConnectSteps.js',
     'NetworkLocationsForm.css',
     'NetworkLocationsForm.js',
     'NetworkLocationsList.css',
     'NetworkLocationsList.js',
--- a/devtools/client/aboutdebugging-new/src/constants.js
+++ b/devtools/client/aboutdebugging-new/src/constants.js
@@ -1,15 +1,21 @@
 /* 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 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_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",
@@ -65,17 +71,24 @@ const SERVICE_WORKER_FETCH_STATES = {
 };
 
 const SERVICE_WORKER_STATUSES = {
   RUNNING: "RUNNING",
   REGISTERING: "REGISTERING",
   STOPPED: "STOPPED",
 };
 
+const USB_STATES = {
+  DISABLED_USB: "DISABLED_USB",
+  ENABLED_USB: "ENABLED_USB",
+  UPDATING_USB: "UPDATING_USB",
+};
+
 // flatten constants
 module.exports = Object.assign({}, {
   DEBUG_TARGETS,
   DEBUG_TARGET_PANE,
   PAGES,
   RUNTIMES,
   SERVICE_WORKER_FETCH_STATES,
   SERVICE_WORKER_STATUSES,
+  USB_STATES,
 }, actionTypes);
--- a/devtools/client/aboutdebugging-new/tmp-locale/en-US/aboutdebugging.notftl
+++ b/devtools/client/aboutdebugging-new/tmp-locale/en-US/aboutdebugging.notftl
@@ -54,16 +54,21 @@ about-debugging-connect-wifi-step-open-o
 
 # WiFi section step by step guide
 about-debugging-connect-wifi-step-enable-debug = Enable Remote Debugging via WiFi in the Developer Tools section
 
 # USB section of the Connect page
 about-debugging-connect-usb
   .title = Via USB
 
+about-debugging-connect-usb-disabled = Enabling this will download and add the required Android USB debugging components to Firefox.
+about-debugging-connect-usb-enable-button = Enable USB Devices
+about-debugging-connect-usb-disable-button = Disable USB Devices
+about-debugging-connect-usb-updating-button = Updating…
+
 # USB section step by step guide
 about-debugging-connect-usb-step-enable-dev-menu = Enable Developer menu on your Android device
 
 # USB section step by step guide
 about-debugging-connect-usb-step-enable-debug = Enable USB Debugging on the Android Developer Menu
 
 # USB section step by step guide
 about-debugging-connect-usb-step-plug-device = Connect the USB Device to your computer