Bug 1454931 - Display help screen when no service worker is available;r=sole draft
authorJulian Descottes <jdescottes@mozilla.com>
Mon, 19 Mar 2018 18:55:22 +0100
changeset 785955 73e5f73be441e11a160276344fcd14cc6b379149
parent 785650 b6e3933bd36c89524f707c528375afc410992622
push id107371
push userjdescottes@mozilla.com
push dateFri, 20 Apr 2018 22:01:14 +0000
reviewerssole
bugs1454931
milestone61.0a1
Bug 1454931 - Display help screen when no service worker is available;r=sole MozReview-Commit-ID: JDPX45YIkrB
devtools/client/application/application.css
devtools/client/application/initializer.js
devtools/client/application/src/components/App.css
devtools/client/application/src/components/App.js
devtools/client/application/src/components/WorkerList.js
devtools/client/application/src/components/WorkerListEmpty.css
devtools/client/application/src/components/WorkerListEmpty.js
devtools/client/application/src/components/moz.build
--- a/devtools/client/application/application.css
+++ b/devtools/client/application/application.css
@@ -1,15 +1,16 @@
 /* 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 "resource://devtools/client/application/src/components/App.css";
 @import "resource://devtools/client/application/src/components/Worker.css";
 @import "resource://devtools/client/application/src/components/WorkerList.css";
+@import "resource://devtools/client/application/src/components/WorkerListEmpty.css";
 
 * {
   box-sizing: border-box;
 }
 
 html,
 body,
 #mount {
--- a/devtools/client/application/initializer.js
+++ b/devtools/client/application/initializer.js
@@ -31,19 +31,28 @@ window.Application = {
     this.mount = document.querySelector("#mount");
     this.toolbox = toolbox;
     this.client = toolbox.target.client;
 
     this.store = configureStore();
     this.actions = bindActionCreators(actions, this.store.dispatch);
 
     const serviceContainer = {
-      openAboutDebugging() {
+      openWebLink(url) {
         let win = toolbox.doc.defaultView.top;
-        win.openUILinkIn("about:debugging#workers", "tab", { relatedToCurrent: true });
+        win.openWebLinkIn(url, "tab", { relatedToCurrent: true });
+      },
+
+      openTrustedLink(url) {
+        let win = toolbox.doc.defaultView.top;
+        win.openTrustedLinkIn(url, "tab", { relatedToCurrent: true });
+      },
+
+      selectTool(toolId) {
+        return toolbox.selectTool(toolId);
       }
     };
 
     // Render the root Application component.
     const app = App({ client: this.client, serviceContainer });
     render(Provider({ store: this.store }, app), this.mount);
 
     this.client.addListener("workerListChanged", this.updateWorkers);
--- a/devtools/client/application/src/components/App.css
+++ b/devtools/client/application/src/components/App.css
@@ -18,16 +18,20 @@
 .application {
   height: 100%;
   padding: 0 0 0 20px;
   overflow: auto;
   display: flex;
   flex-direction: column;
 }
 
+.application.empty {
+  background-color: var(--grey-30);
+}
+
 h1 {
   font-size: 22px;
   font-weight: normal;
 }
 
 a,
 a:hover,
 a:visited {
--- a/devtools/client/application/src/components/App.js
+++ b/devtools/client/application/src/components/App.js
@@ -5,34 +5,42 @@
 "use strict";
 
 const PropTypes = require("devtools/client/shared/vendor/react-prop-types");
 const { createFactory, Component } = require("devtools/client/shared/vendor/react");
 const { connect } = require("devtools/client/shared/vendor/react-redux");
 const { div } = require("devtools/client/shared/vendor/react-dom-factories");
 
 const WorkerList = createFactory(require("./WorkerList"));
+const WorkerListEmpty = createFactory(require("./WorkerListEmpty"));
 
 /**
  * This is the main component for the application panel.
  */
 class App extends Component {
   static get propTypes() {
     return {
       client: PropTypes.object.isRequired,
       workers: PropTypes.object.isRequired,
       serviceContainer: PropTypes.object.isRequired,
     };
   }
 
   render() {
     let { workers, client, serviceContainer } = this.props;
+    const isEmpty = workers.length == 0;
 
-    return div({className: "application"},
-      WorkerList({ workers, client, serviceContainer }));
+    return (
+      div(
+        { className: `application ${isEmpty ? "empty" : ""}` },
+        isEmpty
+          ? WorkerListEmpty({ serviceContainer })
+          : WorkerList({ workers, client, serviceContainer })
+      )
+    );
   }
 }
 
 // Exports
 
 module.exports = connect(
   (state) => ({ workers: state.workers.list }),
 )(App);
--- a/devtools/client/application/src/components/WorkerList.js
+++ b/devtools/client/application/src/components/WorkerList.js
@@ -20,32 +20,35 @@ class WorkerList extends Component {
       client: PropTypes.object.isRequired,
       workers: PropTypes.object.isRequired,
       serviceContainer: PropTypes.object.isRequired,
     };
   }
 
   render() {
     const { workers, client, serviceContainer } = this.props;
-    const { openAboutDebugging } = serviceContainer;
+    const { openTrustedLink } = serviceContainer;
 
     return [
       ul({ className: "application-workers-container" },
         li({},
           h1({ className: "application-title" }, "Service Workers")
         ),
         workers.map(worker => Worker({
           client,
           debugDisabled: false,
           worker,
         }))
       ),
       div({ className: "application-aboutdebugging-plug" },
         "See about:debugging for Service Workers from other domains",
-        a({ onClick: () => openAboutDebugging() }, "Open about:debugging")
+        a(
+          { onClick: () => openTrustedLink("about:debugging#workers") },
+          "Open about:debugging"
+        )
       )
     ];
   }
 }
 
 // Exports
 
 module.exports = WorkerList;
new file mode 100644
--- /dev/null
+++ b/devtools/client/application/src/components/WorkerListEmpty.css
@@ -0,0 +1,19 @@
+/* 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/. */
+
+.worker-list-empty {
+  width: 700px;
+  line-height: 24px;
+  left: 50%;
+  top: 50%;
+  margin-top: -100px;
+  margin-left: -350px;
+  position: absolute;
+  font-size: 13px;
+}
+
+.worker-list-empty ul {
+  list-style: unset;
+  padding: 0 40px;
+}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/devtools/client/application/src/components/WorkerListEmpty.js
@@ -0,0 +1,88 @@
+/* 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 PropTypes = require("devtools/client/shared/vendor/react-prop-types");
+const { Component } = require("devtools/client/shared/vendor/react");
+const { a, div, li, ul } = require("devtools/client/shared/vendor/react-dom-factories");
+const DOC_URL = "https://developer.mozilla.org/docs/Web/API/Service_Worker_API/Using_Service_Workers";
+
+/**
+ * This component displays help information when no service workers are found for the
+ * current target.
+ */
+class WorkerListEmpty extends Component {
+  static get propTypes() {
+    return {
+      serviceContainer: PropTypes.object.isRequired,
+    };
+  }
+
+  switchToConsole() {
+    this.props.serviceContainer.selectTool("webconsole");
+  }
+
+  switchToDebugger() {
+    this.props.serviceContainer.selectTool("jsdebugger");
+  }
+
+  openAboutDebugging() {
+    this.props.serviceContainer.openTrustedLink("about:debugging#workers");
+  }
+
+  openDocumentation() {
+    this.props.serviceContainer.openWebLink(DOC_URL);
+  }
+
+  render() {
+    return div(
+      { className: "worker-list-empty" },
+      div(
+        {},
+        "You need to register a Service Worker to inspect it here.",
+        a(
+          { className: "external-link", onClick: () => this.openDocumentation() },
+          "Learn More"
+        )
+      ),
+      div(
+        {},
+        `If the current page should have a service worker, ` +
+        `here are some things you can try`,
+      ),
+      ul(
+        {},
+        li(
+          {},
+          "Look for errors in the Console.",
+          a(
+            { className: "link", onClick: () => this.switchToConsole() },
+            "Open the Console"
+          )
+        ),
+        li(
+          {},
+          "Step through you Service Worker registration and look for exceptions.",
+          a(
+            { className: "link", onClick: () => this.switchToDebugger()},
+            "Open the Debugger"
+          )
+        ),
+        li(
+          {},
+          "Inspect Service Workers from other domains.",
+          a(
+            { className: "external-link", onClick: () => this.openAboutDebugging() },
+            "Open about:debugging"
+          )
+        )
+      )
+    );
+  }
+}
+
+// Exports
+
+module.exports = WorkerListEmpty;
--- a/devtools/client/application/src/components/moz.build
+++ b/devtools/client/application/src/components/moz.build
@@ -4,9 +4,11 @@
 
 DevToolsModules(
     'App.css',
     'App.js',
     'Worker.css',
     'Worker.js',
     'WorkerList.css',
     'WorkerList.js',
+    'WorkerListEmpty.css',
+    'WorkerListEmpty.js',
 )