Bug 1509791: Display error message which occurred during reloading temporary extension. r=ladybenko,Ola
authorDaisuke Akatsuka <dakatsuka@mozilla.com>
Wed, 17 Apr 2019 01:03:29 +0000
changeset 469736 f7418820531d
parent 469735 a1c8daed8d7f
child 469737 c250a69bbdd7
push id35880
push usercbrindusan@mozilla.com
push dateWed, 17 Apr 2019 09:36:19 +0000
treeherdermozilla-central@79e6ed0b08d6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersladybenko, Ola
bugs1509791
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 1509791: Display error message which occurred during reloading temporary extension. r=ladybenko,Ola Differential Revision: https://phabricator.services.mozilla.com/D25203
devtools/client/aboutdebugging-new/src/actions/debug-targets.js
devtools/client/aboutdebugging-new/src/base.css
devtools/client/aboutdebugging-new/src/components/debugtarget/DebugTargetItem.css
devtools/client/aboutdebugging-new/src/components/debugtarget/DebugTargetItem.js
devtools/client/aboutdebugging-new/src/components/debugtarget/ServiceWorkerAdditionalActions.js
devtools/client/aboutdebugging-new/src/components/debugtarget/TemporaryExtensionAdditionalActions.js
devtools/client/aboutdebugging-new/src/constants.js
devtools/client/aboutdebugging-new/src/reducers/debug-targets-state.js
devtools/client/aboutdebugging-new/src/types/debug-target.js
--- a/devtools/client/aboutdebugging-new/src/actions/debug-targets.js
+++ b/devtools/client/aboutdebugging-new/src/actions/debug-targets.js
@@ -33,16 +33,19 @@ const {
   REQUEST_TABS_START,
   REQUEST_TABS_SUCCESS,
   REQUEST_WORKERS_FAILURE,
   REQUEST_WORKERS_START,
   REQUEST_WORKERS_SUCCESS,
   TEMPORARY_EXTENSION_INSTALL_FAILURE,
   TEMPORARY_EXTENSION_INSTALL_START,
   TEMPORARY_EXTENSION_INSTALL_SUCCESS,
+  TEMPORARY_EXTENSION_RELOAD_FAILURE,
+  TEMPORARY_EXTENSION_RELOAD_START,
+  TEMPORARY_EXTENSION_RELOAD_SUCCESS,
   RUNTIMES,
 } = require("../constants");
 
 const Actions = require("./index");
 
 function getTabForUrl(url) {
   for (const navigator of Services.wm.getEnumerator("navigator:browser")) {
     for (const browser of navigator.gBrowser.browsers) {
@@ -115,24 +118,27 @@ function pushServiceWorker(id) {
       await workerActor.push();
     } catch (e) {
       console.error(e);
     }
   };
 }
 
 function reloadTemporaryExtension(id) {
-  return async (_, getState) => {
+  return async (dispatch, getState) => {
+    dispatch({ type: TEMPORARY_EXTENSION_RELOAD_START, id });
     const clientWrapper = getCurrentClient(getState().runtimes);
 
     try {
       const addonTargetFront = await clientWrapper.getAddon({ id });
       await addonTargetFront.reload();
+      dispatch({ type: TEMPORARY_EXTENSION_RELOAD_SUCCESS, id });
     } catch (e) {
-      console.error(e);
+      const error = typeof e === "string" ? new Error(e) : e;
+      dispatch({ type: TEMPORARY_EXTENSION_RELOAD_FAILURE, id, error });
     }
   };
 }
 
 function removeTemporaryExtension(id) {
   return async () => {
     try {
       await uninstallAddon(id);
--- a/devtools/client/aboutdebugging-new/src/base.css
+++ b/devtools/client/aboutdebugging-new/src/base.css
@@ -259,16 +259,20 @@ p, h1 {
 }
 
 /* a series of button-like elements, layed out horizontally */
 .toolbar {
   display: flex;
   column-gap: calc(var(--base-unit) * 3);
 }
 
+.toolbar--right-align {
+  justify-content: end;
+}
+
 /*
 Form controls
 */
 .default-button, .default-input {
   box-sizing: border-box;
   font-size: 1em;
 }
 
--- a/devtools/client/aboutdebugging-new/src/components/debugtarget/DebugTargetItem.css
+++ b/devtools/client/aboutdebugging-new/src/components/debugtarget/DebugTargetItem.css
@@ -52,17 +52,16 @@
   grid-area: action;
   align-self: center;
   margin-inline-end: calc(var(--base-unit) * 2);
 }
 
 .debug-target-item__additional_actions {
   grid-area: additional_actions;
   border-top: 1px solid var(--grey-20);
-  justify-content: end;
   margin-block-start: calc(var(--base-unit) * 3);
   padding-block-start: calc(var(--base-unit) * 2);
   padding-inline-end: calc(var(--base-unit) * 2);
 }
 
 .debug-target-item__detail {
   grid-area: detail;
   margin-block-start: calc(var(--base-unit) * 3);
--- a/devtools/client/aboutdebugging-new/src/components/debugtarget/DebugTargetItem.js
+++ b/devtools/client/aboutdebugging-new/src/components/debugtarget/DebugTargetItem.js
@@ -38,17 +38,17 @@ class DebugTargetItem extends PureCompon
     const { additionalActionsComponent, dispatch, target } = this.props;
 
     if (!additionalActionsComponent) {
       return null;
     }
 
     return dom.section(
       {
-        className: "debug-target-item__additional_actions toolbar",
+        className: "debug-target-item__additional_actions",
       },
       additionalActionsComponent({ dispatch, target }),
     );
   }
 
   renderDetail() {
     const { detailComponent, target } = this.props;
     return detailComponent({ target });
--- a/devtools/client/aboutdebugging-new/src/components/debugtarget/ServiceWorkerAdditionalActions.js
+++ b/devtools/client/aboutdebugging-new/src/components/debugtarget/ServiceWorkerAdditionalActions.js
@@ -89,17 +89,17 @@ class ServiceWorkerAdditionalActions ext
     return this._renderButton({
       className: "default-button default-button--micro js-unregister-button",
       key: "service-worker-unregister-button",
       labelId: "about-debugging-worker-action-unregister",
       onClick: this.unregister.bind(this),
     });
   }
 
-  render() {
+  _renderActionButtons() {
     const { status } = this.props.target.details;
 
     switch (status) {
       case SERVICE_WORKER_STATUSES.RUNNING:
         return [
           this._renderUnregisterButton(),
           this._renderPushButton(),
         ];
@@ -110,16 +110,25 @@ class ServiceWorkerAdditionalActions ext
           this._renderUnregisterButton(),
           this._renderStartButton(),
         ];
       default:
         console.error("Unexpected service worker status: " + status);
         return null;
     }
   }
+
+  render() {
+    return dom.div(
+      {
+        className: "toolbar toolbar--right-align",
+      },
+      this._renderActionButtons(),
+    );
+  }
 }
 
 const mapStateToProps = state => {
   return {
     runtimeDetails: getCurrentRuntimeDetails(state.runtimes),
   };
 };
 
--- a/devtools/client/aboutdebugging-new/src/components/debugtarget/TemporaryExtensionAdditionalActions.js
+++ b/devtools/client/aboutdebugging-new/src/components/debugtarget/TemporaryExtensionAdditionalActions.js
@@ -8,16 +8,18 @@ const { createFactory, PureComponent } =
 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 Actions = require("../../actions/index");
 const Types = require("../../types/index");
+const Message = createFactory(require("../shared/Message"));
+const { MESSAGE_LEVEL } = require("../../constants");
 
 /**
  * This component provides components that reload/remove temporary extension.
  */
 class TemporaryExtensionAdditionalActions extends PureComponent {
   static get propTypes() {
     return {
       dispatch: PropTypes.func.isRequired,
@@ -30,43 +32,64 @@ class TemporaryExtensionAdditionalAction
     dispatch(Actions.reloadTemporaryExtension(target.id));
   }
 
   remove() {
     const { dispatch, target } = this.props;
     dispatch(Actions.removeTemporaryExtension(target.id));
   }
 
+  renderReloadError() {
+    const { reloadError } = this.props.target.details;
+
+    if (!reloadError) {
+      return null;
+    }
+
+    return Message(
+      {
+        level: MESSAGE_LEVEL.ERROR,
+        key: "reload-error",
+      },
+      dom.p({ className: "technical-text" }, reloadError),
+    );
+  }
+
   render() {
     return [
-      Localized(
+      dom.div(
         {
-          id: "about-debugging-tmp-extension-reload-button",
-          key: "reload-button",
+          className: "toolbar toolbar--right-align",
+          key: "actions",
         },
-        dom.button(
+        Localized(
           {
-            className: "default-button default-button--micro " +
-                       "js-temporary-extension-reload-button",
-            onClick: e => this.reload(),
+            id: "about-debugging-tmp-extension-reload-button",
           },
-          "Reload",
-        )
+          dom.button(
+            {
+              className: "default-button default-button--micro " +
+                         "js-temporary-extension-reload-button",
+              onClick: e => this.reload(),
+            },
+            "Reload",
+          )
+        ),
+        Localized(
+          {
+            id: "about-debugging-tmp-extension-remove-button",
+          },
+          dom.button(
+            {
+              className: "default-button default-button--micro " +
+                         "js-temporary-extension-remove-button",
+              onClick: e => this.remove(),
+            },
+            "Remove",
+          )
+        ),
       ),
-      Localized(
-        {
-          id: "about-debugging-tmp-extension-remove-button",
-          key: "remove-button",
-        },
-        dom.button(
-          {
-            className: "default-button default-button--micro " +
-                       "js-temporary-extension-remove-button",
-            onClick: e => this.remove(),
-          },
-          "Remove",
-        )
-      ),
+      this.renderReloadError(),
     ];
   }
 }
 
 module.exports = TemporaryExtensionAdditionalActions;
--- a/devtools/client/aboutdebugging-new/src/constants.js
+++ b/devtools/client/aboutdebugging-new/src/constants.js
@@ -42,16 +42,19 @@ const actionTypes = {
   SELECT_PAGE_START: "SELECT_PAGE_START",
   SELECT_PAGE_SUCCESS: "SELECT_PAGE_SUCCESS",
   SELECTED_RUNTIME_ID_UPDATED: "SELECTED_RUNTIME_ID_UPDATED",
   SHOW_PROFILER_DIALOG: "SHOW_PROFILER_DIALOG",
   TELEMETRY_RECORD: "TELEMETRY_RECORD",
   TEMPORARY_EXTENSION_INSTALL_FAILURE: "TEMPORARY_EXTENSION_INSTALL_FAILURE",
   TEMPORARY_EXTENSION_INSTALL_START: "TEMPORARY_EXTENSION_INSTALL_START",
   TEMPORARY_EXTENSION_INSTALL_SUCCESS: "TEMPORARY_EXTENSION_INSTALL_SUCCESS",
+  TEMPORARY_EXTENSION_RELOAD_FAILURE: "TEMPORARY_EXTENSION_RELOAD_FAILURE",
+  TEMPORARY_EXTENSION_RELOAD_START: "TEMPORARY_EXTENSION_RELOAD_START",
+  TEMPORARY_EXTENSION_RELOAD_SUCCESS: "TEMPORARY_EXTENSION_RELOAD_SUCCESS",
   THIS_FIREFOX_RUNTIME_CREATED: "THIS_FIREFOX_RUNTIME_CREATED",
   UNWATCH_RUNTIME_FAILURE: "UNWATCH_RUNTIME_FAILURE",
   UNWATCH_RUNTIME_START: "UNWATCH_RUNTIME_START",
   UNWATCH_RUNTIME_SUCCESS: "UNWATCH_RUNTIME_SUCCESS",
   UPDATE_CONNECTION_PROMPT_SETTING_FAILURE: "UPDATE_CONNECTION_PROMPT_SETTING_FAILURE",
   UPDATE_CONNECTION_PROMPT_SETTING_START: "UPDATE_CONNECTION_PROMPT_SETTING_START",
   UPDATE_CONNECTION_PROMPT_SETTING_SUCCESS: "UPDATE_CONNECTION_PROMPT_SETTING_SUCCESS",
   UPDATE_EXTENSION_DEBUG_SETTING_FAILURE: "UPDATE_EXTENSION_DEBUG_SETTING_FAILURE",
--- a/devtools/client/aboutdebugging-new/src/reducers/debug-targets-state.js
+++ b/devtools/client/aboutdebugging-new/src/reducers/debug-targets-state.js
@@ -4,31 +4,43 @@
 
 "use strict";
 
 const {
   REQUEST_EXTENSIONS_SUCCESS,
   REQUEST_PROCESSES_SUCCESS,
   REQUEST_TABS_SUCCESS,
   REQUEST_WORKERS_SUCCESS,
+  TEMPORARY_EXTENSION_RELOAD_FAILURE,
+  TEMPORARY_EXTENSION_RELOAD_START,
   UNWATCH_RUNTIME_SUCCESS,
 } = require("../constants");
 
 function DebugTargetsState() {
   return {
     installedExtensions: [],
     otherWorkers: [],
     processes: [],
     serviceWorkers: [],
     sharedWorkers: [],
     tabs: [],
     temporaryExtensions: [],
   };
 }
 
+function updateTemporaryExtension(state, id, updatedDetails) {
+  return state.temporaryExtensions.map(extension => {
+    if (extension.id === id) {
+      extension = Object.assign({}, extension);
+      extension.details = Object.assign({}, extension.details, updatedDetails);
+    }
+    return extension;
+  });
+}
+
 function debugTargetsReducer(state = DebugTargetsState(), action) {
   switch (action.type) {
     case UNWATCH_RUNTIME_SUCCESS: {
       return DebugTargetsState();
     }
     case REQUEST_EXTENSIONS_SUCCESS: {
       const { installedExtensions, temporaryExtensions } = action;
       return Object.assign({}, state, { installedExtensions, temporaryExtensions });
@@ -40,16 +52,28 @@ function debugTargetsReducer(state = Deb
     case REQUEST_TABS_SUCCESS: {
       const { tabs } = action;
       return Object.assign({}, state, { tabs });
     }
     case REQUEST_WORKERS_SUCCESS: {
       const { otherWorkers, serviceWorkers, sharedWorkers } = action;
       return Object.assign({}, state, { otherWorkers, serviceWorkers, sharedWorkers });
     }
+    case TEMPORARY_EXTENSION_RELOAD_FAILURE: {
+      const { id, error } = action;
+      const temporaryExtensions =
+        updateTemporaryExtension(state, id, { reloadError: error.message });
+      return Object.assign({}, state, { temporaryExtensions });
+    }
+    case TEMPORARY_EXTENSION_RELOAD_START: {
+      const { id } = action;
+      const temporaryExtensions =
+        updateTemporaryExtension(state, id, { reloadError: null });
+      return Object.assign({}, state, { temporaryExtensions });
+    }
 
     default:
       return state;
   }
 }
 
 module.exports = {
   DebugTargetsState,
--- a/devtools/client/aboutdebugging-new/src/types/debug-target.js
+++ b/devtools/client/aboutdebugging-new/src/types/debug-target.js
@@ -9,16 +9,18 @@ const { DEBUG_TARGETS } = require("../co
 
 const extensionTargetDetails = {
   // actor ID for this extention.
   actor: PropTypes.string.isRequired,
   location: PropTypes.string.isRequired,
   // manifestURL points to the manifest.json file. This URL is only valid when debugging
   // local extensions so it might be null.
   manifestURL: PropTypes.string,
+  // error message forwarded from the addon manager during reloading temporary extension.
+  reloadError: PropTypes.string,
   // unique extension id.
   uuid: PropTypes.string.isRequired,
   // warning messages forwarded from the addon manager.
   warnings: PropTypes.arrayOf(PropTypes.string).isRequired,
 };
 
 const processTargetDetails = {
   // Description for the process.