Bug 1473178 - Reinstate about:newaddon draft
authorGeoff Lankow <geoff@darktrojan.net>
Mon, 03 Sep 2018 16:09:05 +1200
changeset 67095 47adddcee716639103ff0c7172b4eb10e57c49b5
parent 67094 e73cc44f959a287a8efb3a322385391b99dd9442
child 67096 86f603213f7bd7ba77b1d41734f43bd18da1bca3
push id6804
push usergeoff@darktrojan.net
push dateMon, 03 Sep 2018 04:29:25 +0000
treeherdertry-comm-central@06e92d870703 [default view] [failures only]
bugs1473178
Bug 1473178 - Reinstate about:newaddon
mail/base/content/aboutNewAddon.js
mail/base/content/aboutNewAddon.xul
mail/base/jar.mn
mail/components/aboutRedirector.js
mail/components/mailComponents.manifest
mail/locales/en-US/chrome/messenger/aboutNewAddon.dtd
mail/locales/en-US/chrome/messenger/aboutNewAddon.properties
mail/locales/jar.mn
mail/themes/shared/jar.inc.mn
mail/themes/shared/mail/aboutNewAddon.css
new file mode 100644
--- /dev/null
+++ b/mail/base/content/aboutNewAddon.js
@@ -0,0 +1,135 @@
+/* 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/. */
+
+/* exported cancelClicked, continueClicked, initialize, restartClicked, unload */
+
+ChromeUtils.import("resource://gre/modules/Services.jsm");
+ChromeUtils.import("resource://gre/modules/AddonManager.jsm");
+ChromeUtils.defineModuleGetter(this, "ExtensionParent", "resource://gre/modules/ExtensionParent.jsm");
+
+var gAddon = null;
+
+// If the user enables the add-on through some other UI close this window
+var EnableListener = {
+  onEnabled(aAddon) {
+    if (aAddon.id == gAddon.id) {
+      AddonManager.removeAddonListener(EnableListener);
+
+      let webextension = ExtensionParent.GlobalManager.getExtension(gAddon.id);
+      if (webextension && webextension.manifest.legacy) {
+        document.getElementById("allow").disabled = true;
+        document.getElementById("buttonDeck").selectedPanel = document.getElementById("restartPanel");
+      } else {
+        window.close();
+      }
+    }
+  }
+};
+AddonManager.addAddonListener(EnableListener);
+
+function initialize() {
+  // About URIs don't implement nsIURL so we have to find the query string
+  // manually
+  let spec = document.location.href;
+  let pos = spec.indexOf("?");
+  let query = "";
+  if (pos >= 0)
+    query = spec.substring(pos + 1);
+
+  // Just assume the query is "id=<id>"
+  let id = query.substring(3);
+  if (!id) {
+    window.location = "about:blank";
+    return;
+  }
+
+  let bundle = Services.strings.createBundle("chrome://messenger/locale/aboutNewAddon.properties");
+
+  AddonManager.getAddonByID(id).then(function(aAddon) {
+    // If the add-on doesn't exist or it is already enabled or it has already
+    // been seen or it cannot be enabled then this UI is useless, just close it.
+    // This shouldn't normally happen unless session restore restores the tab.
+    if (!aAddon || !aAddon.userDisabled || aAddon.seen ||
+        !(aAddon.permissions & AddonManager.PERM_CAN_ENABLE)) {
+      window.close();
+      return;
+    }
+
+    gAddon = aAddon;
+
+    document.getElementById("addon-info").setAttribute("type", aAddon.type);
+
+    let icon = document.getElementById("icon");
+    if (aAddon.icon64URL)
+      icon.src = aAddon.icon64URL;
+    else if (aAddon.iconURL)
+      icon.src = aAddon.iconURL;
+
+    let name = bundle.formatStringFromName("name", [aAddon.name, aAddon.version],
+                                           2);
+    document.getElementById("name").value = name;
+
+    if (aAddon.creator) {
+      let creator = bundle.formatStringFromName("author", [aAddon.creator], 1);
+      document.getElementById("author").value = creator;
+    } else {
+      document.getElementById("author").hidden = true;
+    }
+
+    let uri = "getResourceURI" in aAddon ? aAddon.getResourceURI() : null;
+    let locationLabel = document.getElementById("location");
+    if (uri instanceof Ci.nsIFileURL) {
+      let location = bundle.formatStringFromName("location", [uri.file.path], 1);
+      locationLabel.value = location;
+      locationLabel.setAttribute("tooltiptext", location);
+    } else {
+      document.getElementById("location").hidden = true;
+    }
+
+    // Only mark the add-on as seen if the page actually gets focus
+    if (document.hasFocus()) {
+      aAddon.markAsSeen();
+    } else {
+      document.addEventListener("focus", () => aAddon.markAsSeen());
+    }
+
+    var event = document.createEvent("Events");
+    event.initEvent("AddonDisplayed", true, true);
+    document.dispatchEvent(event);
+  });
+}
+
+function unload() {
+  AddonManager.removeAddonListener(EnableListener);
+}
+
+function continueClicked() {
+  if (document.getElementById("allow").checked) {
+    gAddon.enable();
+  } else {
+    AddonManager.removeAddonListener(EnableListener);
+    window.close();
+  }
+}
+
+function restartClicked() {
+  let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].
+                   createInstance(Ci.nsISupportsPRBool);
+  Services.obs.notifyObservers(cancelQuit, "quit-application-requested",
+                               "restart");
+  if (cancelQuit.data)
+    return; // somebody canceled our quit request
+
+  window.close();
+
+  Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit | Ci.nsIAppStartup.eRestart);
+}
+
+function cancelClicked() {
+  gAddon.disable();
+  AddonManager.addAddonListener(EnableListener);
+
+  document.getElementById("allow").disabled = false;
+  document.getElementById("buttonDeck").selectedPanel = document.getElementById("continuePanel");
+}
new file mode 100644
--- /dev/null
+++ b/mail/base/content/aboutNewAddon.xul
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<!-- 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/. -->
+
+<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
+<?xml-stylesheet href="chrome://messenger/skin/aboutNewAddon.css"?>
+
+<!DOCTYPE page [
+<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" >
+%brandDTD;
+<!ENTITY % newaddonDTD SYSTEM "chrome://messenger/locale/aboutNewAddon.dtd">
+%newaddonDTD;
+]>
+
+<page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
+      xmlns:xhtml="http://www.w3.org/1999/xhtml" title="&title;"
+      disablefastfind="true" id="addon-page" onload="initialize()"
+      onunload="unload()" role="application" align="stretch" pack="stretch">
+
+  <xhtml:link rel="shortcut icon" style="display: none"
+              href="chrome://mozapps/skin/extensions/extensionGeneric-16.svg"/>
+
+  <script type="application/javascript"
+          src="chrome://messenger/content/aboutNewAddon.js"/>
+
+  <scrollbox id="addon-scrollbox" align="center">
+    <spacer id="spacer-start"/>
+
+    <vbox id="addon-container" class="main-content">
+      <description>&intro;</description>
+
+      <hbox id="addon-info">
+        <image id="icon"/>
+        <vbox flex="1">
+          <label id="name"/>
+          <label id="author"/>
+          <label id="location" crop="end"/>
+        </vbox>
+      </hbox>
+
+      <hbox id="warning">
+        <image id="warning-icon"/>
+        <description flex="1">&warning;</description>
+      </hbox>
+
+      <checkbox id="allow" label="&allow;"/>
+      <description id="later">&later;</description>
+
+      <deck id="buttonDeck">
+        <hbox id="continuePanel">
+          <button id="continue-button" label="&continue;"
+                  oncommand="continueClicked()"/>
+        </hbox>
+        <vbox id="restartPanel">
+          <description id="restartMessage">&restartMessage;</description>
+          <hbox id="restartPanelButtons">
+            <button id="restart-button" label="&restartButton;" oncommand="restartClicked()"/>
+            <button id="cancel-button" label="&cancelButton;" oncommand="cancelClicked()"/>
+          </hbox>
+        </vbox>
+      </deck>
+    </vbox>
+
+    <spacer id="spacer-end"/>
+  </scrollbox>
+</page>
--- a/mail/base/jar.mn
+++ b/mail/base/jar.mn
@@ -58,16 +58,18 @@ messenger.jar:
     content/messenger/ABSearchDialog.js             (content/ABSearchDialog.js)
     content/messenger/FilterListDialog.xul          (content/FilterListDialog.xul)
     content/messenger/FilterListDialog.js           (content/FilterListDialog.js)
     content/messenger/plugins.js                    (content/plugins.js)
     content/messenger/specialTabs.js                (content/specialTabs.js)
     content/messenger/aboutDialog-appUpdater.js     (content/aboutDialog-appUpdater.js)
 *   content/messenger/aboutDialog.xul               (content/aboutDialog.xul)
     content/messenger/aboutDialog.js                (content/aboutDialog.js)
+    content/messenger/aboutNewAddon.js              (content/aboutNewAddon.js)
+    content/messenger/aboutNewAddon.xul             (content/aboutNewAddon.xul)
 *   content/messenger/aboutRights.xhtml             (content/aboutRights.xhtml)
 *   content/messenger/systemIntegrationDialog.xul   (content/systemIntegrationDialog.xul)
     content/messenger/systemIntegrationDialog.js    (content/systemIntegrationDialog.js)
     content/messenger/folderPane.js                 (content/folderPane.js)
     content/messenger/searchBar.js                  (content/searchBar.js)
     content/messenger/phishingDetector.js           (content/phishingDetector.js)
     content/messenger/mail-offline.js               (content/mail-offline.js)
     content/messenger/aboutDialog.css               (content/aboutDialog.css)
--- a/mail/components/aboutRedirector.js
+++ b/mail/components/aboutRedirector.js
@@ -9,16 +9,19 @@ AboutRedirector.prototype = {
   classDescription: "Mail about: Redirector",
   classID: Components.ID("{8cc51368-6aa0-43e8-b762-bde9b9fd828c}"),
   QueryInterface: ChromeUtils.generateQI([Ci.nsIAboutModule]),
 
   // Each entry in the map has the key as the part after the "about:" and the
   // value as a record with url and flags entries. Note that each addition here
   // should be coupled with a corresponding addition in mailComponents.manifest.
   _redirMap: {
+    "newaddon": {url: "chrome://messenger/content/aboutNewAddon.xul",
+                 flags: (Ci.nsIAboutModule.ALLOW_SCRIPT |
+                         Ci.nsIAboutModule.HIDE_FROM_ABOUTABOUT)},
     "newserror": {url: "chrome://messenger/content/newsError.xhtml",
                   flags: Ci.nsIAboutModule.ALLOW_SCRIPT},
     "rights": {url: "chrome://messenger/content/aboutRights.xhtml",
                flags: (Ci.nsIAboutModule.ALLOW_SCRIPT |
                        Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT)},
     "support": {url: "chrome://messenger/content/about-support/aboutSupport.xhtml",
                 flags: Ci.nsIAboutModule.ALLOW_SCRIPT},
     "preferences": {url: "chrome://messenger/content/preferences/aboutPreferences.xul",
--- a/mail/components/mailComponents.manifest
+++ b/mail/components/mailComponents.manifest
@@ -1,11 +1,12 @@
 component {8cc51368-6aa0-43e8-b762-bde9b9fd828c} aboutRedirector.js
 # Each addition here should be coupled with a corresponding addition in
 # aboutRedirector.js.
+contract @mozilla.org/network/protocol/about;1?what=newaddon {8cc51368-6aa0-43e8-b762-bde9b9fd828c}
 contract @mozilla.org/network/protocol/about;1?what=newserror {8cc51368-6aa0-43e8-b762-bde9b9fd828c}
 contract @mozilla.org/network/protocol/about;1?what=rights {8cc51368-6aa0-43e8-b762-bde9b9fd828c}
 contract @mozilla.org/network/protocol/about;1?what=support {8cc51368-6aa0-43e8-b762-bde9b9fd828c}
 contract @mozilla.org/network/protocol/about;1?what=preferences {8cc51368-6aa0-43e8-b762-bde9b9fd828c}
 contract @mozilla.org/network/protocol/about;1?what=downloads {8cc51368-6aa0-43e8-b762-bde9b9fd828c}
 
 component {44346520-c5d2-44e5-a1ec-034e04d7fac4} nsMailDefaultHandler.js
 contract @mozilla.org/mail/clh;1 {44346520-c5d2-44e5-a1ec-034e04d7fac4}
new file mode 100644
--- /dev/null
+++ b/mail/locales/en-US/chrome/messenger/aboutNewAddon.dtd
@@ -0,0 +1,15 @@
+<!-- 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/. -->
+
+<!ENTITY title           "Install Add-on">
+<!ENTITY intro           "Another program on your computer would like to modify
+                          &brandShortName; with the following add-on:">
+<!ENTITY warning         "Install add-ons only from authors whom you trust.">
+<!ENTITY allow           "Allow this installation">
+<!ENTITY later           "You can always change your mind at any time by going
+                          to the Add-ons Manager.">
+<!ENTITY continue        "Continue">
+<!ENTITY restartMessage  "You must restart &brandShortName; to finish installing this add-on.">
+<!ENTITY restartButton   "Restart &brandShortName;">
+<!ENTITY cancelButton    "Cancel">
new file mode 100644
--- /dev/null
+++ b/mail/locales/en-US/chrome/messenger/aboutNewAddon.properties
@@ -0,0 +1,10 @@
+# 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/.
+
+#LOCALIZATION NOTE (name) %1$S is the add-on name, %2$S is the add-on version
+name=%1$S %2$S
+#LOCALIZATION NOTE (author) %S is the author of the add-on
+author=By %S
+#LOCALIZATION NOTE (location) %S is the path the add-on is installed in
+location=Location: %S
--- a/mail/locales/jar.mn
+++ b/mail/locales/jar.mn
@@ -11,16 +11,18 @@
 [localization] @AB_CD@.jar:
   messenger                                                             (%messenger/**/*.ftl)
 
 
 @AB_CD@.jar:
 % locale messenger @AB_CD@ %locale/@AB_CD@/messenger/
   locale/@AB_CD@/messenger/aboutDialog.dtd                              (%chrome/messenger/aboutDialog.dtd)
   locale/@AB_CD@/messenger/aboutDownloads.dtd                           (%chrome/messenger/aboutDownloads.dtd)
+  locale/@AB_CD@/messenger/aboutNewAddon.dtd                            (%chrome/messenger/aboutNewAddon.dtd)
+  locale/@AB_CD@/messenger/aboutNewAddon.properties                     (%chrome/messenger/aboutNewAddon.properties)
   locale/@AB_CD@/messenger/aboutRights.dtd                              (%chrome/messenger/aboutRights.dtd)
   locale/@AB_CD@/messenger/aboutRights.properties                       (%chrome/messenger/aboutRights.properties)
   locale/@AB_CD@/messenger/aboutSupportMail.dtd                         (%chrome/messenger/aboutSupportMail.dtd)
   locale/@AB_CD@/messenger/aboutSupportMail.properties                  (%chrome/messenger/aboutSupportMail.properties)
   locale/@AB_CD@/messenger/telemetry.properties                         (%chrome/messenger/telemetry.properties)
   locale/@AB_CD@/messenger/accountCreation.dtd                          (%chrome/messenger/accountCreation.dtd)
   locale/@AB_CD@/messenger/accountCreation.properties                   (%chrome/messenger/accountCreation.properties)
   locale/@AB_CD@/messenger/accountCreationModel.properties              (%chrome/messenger/accountCreationModel.properties)
--- a/mail/themes/shared/jar.inc.mn
+++ b/mail/themes/shared/jar.inc.mn
@@ -3,16 +3,17 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 # This is not a complete / proper jar manifest. It is included by the
 # actual theme-specific manifests, so that shared resources need only
 # be specified once. As a result, the source file paths are relative
 # to the location of the actual manifest.
 
   skin/classic/messenger/aboutNetError.css                    (../shared/mail/aboutNetError.css)
+  skin/classic/messenger/aboutNewAddon.css                    (../shared/mail/aboutNewAddon.css)
   skin/classic/messenger/aboutSupport.css                     (../shared/mail/aboutSupport.css)
   skin/classic/messenger/addressbook/icons/menu.svg           (../shared/mail/icons/menu.svg)
   skin/classic/messenger/downloads/download.svg               (../shared/mail/icons/download.svg)
   skin/classic/messenger/extensionsOverlay.css                (../shared/mail/extensionsOverlay.css)
   skin/classic/messenger/icons/address.svg                    (../shared/mail/icons/address.svg)
   skin/classic/messenger/icons/addcontact.svg                 (../shared/mail/icons/addcontact.svg)
   skin/classic/messenger/icons/addlist.svg                    (../shared/mail/icons/addlist.svg)
   skin/classic/messenger/icons/accounts.svg                   (../shared/mail/icons/accounts.svg)
new file mode 100644
--- /dev/null
+++ b/mail/themes/shared/mail/aboutNewAddon.css
@@ -0,0 +1,113 @@
+/* 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 url("chrome://global/skin/in-content/common.css");
+
+#addon-page {
+  font-size: 1.1em;
+}
+
+#addon-scrollbox {
+  overflow: auto;
+  -moz-box-orient: vertical;
+  -moz-box-flex: 1;
+}
+
+#spacer-start {
+  -moz-box-flex: 1;
+}
+
+#spacer-end {
+  -moz-box-flex: 3;
+}
+
+#addon-container {
+  overflow: visible;
+  max-width: 800px;
+  margin: 20px;
+  padding: 30px 90px;
+}
+
+#addon-info {
+  -moz-box-align: start;
+  margin: 25px 10px;
+}
+
+#icon {
+  margin-top: 8px;
+  margin-inline-end: 10px;
+  max-width: 64px;
+  max-height: 64px;
+  list-style-image: url("chrome://mozapps/skin/extensions/extensionGeneric.svg");
+}
+
+.addon-info[type="theme"] #icon {
+  list-style-image: url("chrome://mozapps/skin/extensions/themeGeneric.svg");
+}
+
+.addon-info[type="locale"] #icon {
+  list-style-image: url("chrome://mozapps/skin/extensions/localeGeneric.svg");
+}
+
+.addon-info[type="plugin"] #icon {
+  list-style-image: url("chrome://mozapps/skin/plugins/pluginGeneric.svg");
+}
+
+.addon-info[type="dictionary"] #icon {
+  list-style-image: url("chrome://mozapps/skin/extensions/dictionaryGeneric.svg");
+}
+
+#name {
+  font-size: 130%;
+}
+
+#author {
+  color: GrayText;
+}
+
+#location {
+  color: GrayText;
+}
+
+#warning {
+  margin-bottom: 25px;
+  -moz-box-align: start;
+}
+
+#warning-icon {
+  list-style-image: url("chrome://mozapps/skin/extensions/alerticon-warning.svg");
+  width: 16px;
+  height: 16px;
+  margin-top: 5px;
+  margin-inline-end: 5px;
+}
+
+#allow {
+  margin-inline-start: 84px;
+  margin-bottom: 20px;
+}
+
+#buttonDeck {
+  margin-top: 25px;
+  -moz-box-align: stretch;
+}
+
+#continuePanel {
+  -moz-box-pack: end;
+  -moz-box-align: end;
+}
+
+#restartPanel {
+  -moz-box-pack: end;
+  -moz-box-align: stretch;
+}
+
+#restartPanelButtons {
+  margin-top: 25px;
+  -moz-box-pack: end;
+}
+
+#later {
+  color: GrayText;
+}