Bug 1361080 - Introduce tab page to install DevTools add-on. r=jdescottes draft
authorAlexandre Poirot <poirot.alex@gmail.com>
Wed, 09 Aug 2017 11:26:50 +0200
changeset 643112 1ca9566b7681bb757418f54704c9858ce6242881
parent 643099 fa9f4d05a7511ce857a324199b1da1e42cce380b
child 725211 afd9426056ca03828a3cf9d04be69dc75d876d0f
push id72997
push userbmo:poirot.alex@gmail.com
push dateWed, 09 Aug 2017 09:29:07 +0000
reviewersjdescottes
bugs1361080
milestone57.0a1
Bug 1361080 - Introduce tab page to install DevTools add-on. r=jdescottes MozReview-Commit-ID: 7B4OuKnlhs
browser/locales/en-US/chrome/browser/devtools/aboutdevtools.dtd
browser/locales/jar.mn
devtools/shim/aboutdevtools.js
devtools/shim/aboutdevtools.manifest
devtools/shim/aboutdevtools.xhtml
devtools/shim/devtools-startup.js
devtools/shim/jar.mn
devtools/shim/moz.build
new file mode 100644
--- /dev/null
+++ b/browser/locales/en-US/chrome/browser/devtools/aboutdevtools.dtd
@@ -0,0 +1,9 @@
+<!ENTITY  aboutDevtools.install.title "Install Firefox Developer Tools">
+<!ENTITY  aboutDevtools.install.systemMenuMessage "Examine, edit and debug HTML, CSS, and JavaScript with tools like Inspector and Debugger.">
+<!ENTITY  aboutDevtools.install.keyShortcutMessage "You activated a Developer Tool shortcut. If that was a mistake, you can close this tab.">
+<!ENTITY  aboutDevtools.install.commonMessage "As of Firefox 56, Developer Tools are released as an add-on instead of built-in to allow faster updates.">
+<!ENTITY  aboutDevtools.install.learnMoreLink "Learn more about DevTools">
+<!ENTITY  aboutDevtools.install.installButton "Install Developer Tools">
+<!ENTITY  aboutDevtools.install.installingText "Installing…">
+<!ENTITY  aboutDevtools.welcome.title "Welcome to Firefox Developer Tools!">
+<!ENTITY  aboutDevtools.welcome.message "<p>You've successfully installed DevTools! To get started, click on the Tools toggle in the toolbar or open the Inspector with Cmd-Opt-I.</p><p>Check out the tutorials below to learn more about what you can do with DevTools.</p>">
--- a/browser/locales/jar.mn
+++ b/browser/locales/jar.mn
@@ -40,16 +40,17 @@
     locale/browser/engineManager.properties        (%chrome/browser/engineManager.properties)
     locale/browser/setDesktopBackground.dtd        (%chrome/browser/setDesktopBackground.dtd)
     locale/browser/shellservice.properties         (%chrome/browser/shellservice.properties)
     locale/browser/tabbrowser.properties           (%chrome/browser/tabbrowser.properties)
     locale/browser/taskbar.properties              (%chrome/browser/taskbar.properties)
     locale/browser/translation.dtd                 (%chrome/browser/translation.dtd)
     locale/browser/translation.properties          (%chrome/browser/translation.properties)
     locale/browser/webrtcIndicator.properties      (%chrome/browser/webrtcIndicator.properties)
+    locale/browser/devtools/aboutdevtools.dtd      (%chrome/browser/devtools/aboutdevtools.dtd)
     locale/browser/downloads/downloads.dtd         (%chrome/browser/downloads/downloads.dtd)
     locale/browser/downloads/downloads.properties  (%chrome/browser/downloads/downloads.properties)
     locale/browser/places/places.dtd               (%chrome/browser/places/places.dtd)
     locale/browser/places/places.properties        (%chrome/browser/places/places.properties)
     locale/browser/places/editBookmarkOverlay.dtd  (%chrome/browser/places/editBookmarkOverlay.dtd)
     locale/browser/places/bookmarkProperties.properties (%chrome/browser/places/bookmarkProperties.properties)
     locale/browser/places/moveBookmarks.dtd        (%chrome/browser/places/moveBookmarks.dtd)
     locale/browser/safebrowsing/phishing-afterload-warning-message.dtd (%chrome/browser/safebrowsing/phishing-afterload-warning-message.dtd)
new file mode 100644
--- /dev/null
+++ b/devtools/shim/aboutdevtools.js
@@ -0,0 +1,45 @@
+/* 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";
+
+// Register the about:devtools URL, that is open whenever user attempt to open
+// DevTools for the first time.
+// This page prompt for DevTools add-on installation only if user confirm his
+// intent to use the tools.
+const Ci = Components.interfaces;
+const Cu = Components.utils;
+
+const { XPCOMUtils } = Cu.import("resource://gre/modules/XPCOMUtils.jsm", {});
+const { Services } = Cu.import("resource://gre/modules/Services.jsm", {});
+
+const { nsIAboutModule } = Ci;
+
+function AboutDevtools() {}
+
+AboutDevtools.prototype = {
+  uri: Services.io.newURI("chrome://devtools-shim/content/aboutdevtools.xhtml"),
+  classDescription: "about:devtools",
+  classID: Components.ID("3a16d383-92bd-4c24-ac10-0e2bd66883ab"),
+  contractID: "@mozilla.org/network/protocol/about;1?what=devtools",
+
+  QueryInterface: XPCOMUtils.generateQI([nsIAboutModule]),
+
+  newChannel: function (uri, loadInfo) {
+    let chan = Services.io.newChannelFromURIWithLoadInfo(
+      this.uri,
+      loadInfo
+    );
+    chan.owner = Services.scriptSecurityManager.getSystemPrincipal();
+    return chan;
+  },
+
+  getURIFlags: function (uri) {
+    return nsIAboutModule.ALLOW_SCRIPT;
+  }
+};
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([
+  AboutDevtools
+]);
new file mode 100644
--- /dev/null
+++ b/devtools/shim/aboutdevtools.manifest
@@ -0,0 +1,2 @@
+component {3a16d383-92bd-4c24-ac10-0e2bd66883ab} aboutdevtools.js
+contract @mozilla.org/network/protocol/about;1?what=devtools {3a16d383-92bd-4c24-ac10-0e2bd66883ab}
new file mode 100644
--- /dev/null
+++ b/devtools/shim/aboutdevtools.xhtml
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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/. -->
+<!DOCTYPE html [
+<!ENTITY % htmlDTD PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd"> %htmlDTD;
+<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd"> %globalDTD;
+<!ENTITY % aboutdevtoolsDTD SYSTEM "chrome://browser/locale/devtools/aboutdevtools.dtd"> %aboutdevtoolsDTD;
+]>
+
+<html xmlns="http://www.w3.org/1999/xhtml" dir="&locale.dir;">
+<head>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+  <style>
+  html {
+    background: #f5f5f7;
+    color: #4d4d4d;
+    font-size: 15px;
+		line-height: 22px;
+  }
+  .box {
+    width: 960px;
+    height: 510px;
+    position: absolute;
+    margin: 0 calc(50% - 480px);
+    top: calc(50% - 255px);
+    display: flex;
+  }
+  .left-pane {
+    width: 360px;
+  }
+  .right-pane {
+    flex: 1;
+  }
+  a {
+    color: #0A84FF;
+  }
+  h1 {
+    font-size: 36px;
+    margin-top: 16px;
+    font-weight: 300;
+    line-height: 44px;
+  }
+  button {
+    margin-top: 2em;
+    display: block;
+    padding: 10px 20px;
+    font-size: 15px;
+    font-weight: 600;
+    line-height: 21px;
+    background: #0d96ff;
+    border: none;
+    border-radius: 3px;
+    color: #fff;
+    box-shadow: 0 1px 0 rgba(0,0,0,0.23);
+    cursor: pointer;
+  }
+  /* Remove light gray outline when clicking on the button */
+  button::-moz-focus-inner { border: 0; }
+  [hidden="true"] {
+    display: none;
+  }
+  </style>
+  <script type="text/javascript">
+  "use strict";
+
+  // URL constructor doesn't support about: scheme,
+  // we have to use http in order to have working searchParams.
+  let url = new URL(window.location.href.replace("about:", "http://"));
+  let reason = url.searchParams.get("reason");
+  window.addEventListener("load", function () {
+    // Display the message specific to the reason
+    let id = "";
+    if (reason == "menu" || reason == "hamburger") {
+      id = "system-menu";
+    } else if (reason == "key") {
+      id = "key-shortcut";
+    }
+    if (id) {
+      let message = document.getElementById(id);
+      message.removeAttribute("hidden");
+    }
+
+    let btn = document.getElementById("install");
+    btn.addEventListener("click", function () {
+      btn.disabled = true;
+      let Cu = Components.utils;
+      let { DevToolsShim } =
+       Cu.import("chrome://devtools-shim/content/DevToolsShim.jsm", {});
+      DevToolsShim.install(onProgress)
+        .then(() => {
+          let installPage = document.getElementById("install-page");
+          installPage.setAttribute("hidden", "true");
+          let welcomePage = document.getElementById("welcome-page");
+          welcomePage.removeAttribute("hidden");
+        });
+      btn.textContent = btn.getAttribute("installing");
+    });
+    function onProgress(progress) {
+      if (progress == 0 || progress == 1) {
+        delete btn.style.background;
+      } else {
+        progress = Math.round(progress * 100);
+        // Use linear-gradient, not so gradient, to simulator a progress bar
+        btn.style.background =
+          "linear-gradient(90deg, #0dff96 " + progress + "%," +
+                                 "#0d96ff " + (progress + 3) + "%)";
+      }
+    }
+  }, { once: true });
+  </script>
+</head>
+<body>
+  <div id="install-page" class="box">
+    <div class="left-pane" />
+    <div class="right-pane">
+      <h1>&aboutDevtools.install.title;</h1>
+
+      <!-- Include all the possible message, hidden by default
+           as we can't lazily load localized strings from dtd -->
+      <p id="key-shortcut" hidden="true">&aboutDevtools.install.keyShortcutMessage;</p>
+      <p id="system-menu" hidden="true">&aboutDevtools.install.systemMenuMessage;</p>
+
+      <p>&aboutDevtools.install.commonMessage;</p>
+      <a href="#">&aboutDevtools.install.learnMoreLink;</a>
+      <button id="install" installing="&aboutDevtools.install.installingText;">&aboutDevtools.install.installButton;</button>
+    </div>
+  </div>
+
+  <!-- This page, hidden by default is displayed once the add-on is installed -->
+  <div id="welcome-page" class="box" hidden="true">
+    <div class="left-pane" />
+    <div class="right-pane">
+      <h1>&aboutDevtools.welcome.title;</h1>
+      &aboutDevtools.welcome.message;
+    </div>
+  </div>
+</body>
+</html>
--- a/devtools/shim/devtools-startup.js
+++ b/devtools/shim/devtools-startup.js
@@ -395,16 +395,29 @@ DevToolsStartup.prototype = {
       // only change the currently selected tool.
       try {
         Services.telemetry.getHistogramById("DEVTOOLS_ENTRY_POINT")
                           .add(reason);
       } catch (e) {
         dump("DevTools telemetry entry point failed: " + e + "\n");
       }
     }
+
+    // If any entry point is fired and the tools aren't installed, open the installation
+    // page
+    if (!this.isInstalled) {
+      let { gBrowser } = Services.wm.getMostRecentWindow("navigator:browser");
+      let url = "about:devtools";
+      if (reason) {
+        url += "?reason=" + encodeURIComponent(reason);
+      }
+      gBrowser.selectedTab = gBrowser.addTab(url);
+      return null;
+    }
+
     this.initialized = true;
     let { require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
     // Ensure loading main devtools module that hooks up into browser UI
     // and initialize all devtools machinery.
     require("devtools/client/framework/devtools-browser");
     return require;
   },
 
--- a/devtools/shim/jar.mn
+++ b/devtools/shim/jar.mn
@@ -1,7 +1,8 @@
 # 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/.
 
 devtools-shim.jar:
 %   content devtools-shim %content/
+    content/aboutdevtools.xhtml  (aboutdevtools.xhtml)
     content/DevToolsShim.jsm  (DevToolsShim.jsm)
--- a/devtools/shim/moz.build
+++ b/devtools/shim/moz.build
@@ -14,9 +14,15 @@ JS_PREFERENCE_PP_FILES += [
 if CONFIG['MOZ_DEVTOOLS'] != 'server':
     EXTRA_COMPONENTS += [
         'aboutdebugging-registration.js',
         'aboutdebugging.manifest',
         'devtools-startup.js',
         'devtools-startup.manifest',
     ]
 
+if CONFIG['MOZ_DEVTOOLS'] == 'addon':
+    EXTRA_COMPONENTS += [
+        'aboutdevtools.js',
+        'aboutdevtools.manifest',
+    ]
+
 XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']