Bug 1309288 - Install addon from sources permanently from about:debugging. r=jdescottes draft
authorAlexandre Poirot <poirot.alex@gmail.com>
Tue, 27 Sep 2016 02:37:05 -0700
changeset 428754 520bf9586b1ea7bb2eea3430611aef15b201ef15
parent 428476 215f9686117673a2c914ed207bc7da9bb8d741ad
child 534833 12e09bf9340c7e75b6effad6f6164d677f878871
push id33415
push userbmo:poirot.alex@gmail.com
push dateMon, 24 Oct 2016 16:10:57 +0000
reviewersjdescottes
bugs1309288
milestone52.0a1
Bug 1309288 - Install addon from sources permanently from about:debugging. r=jdescottes MozReview-Commit-ID: 9GbCEGFSIl7
devtools/client/aboutdebugging/components/addons/controls.js
devtools/client/locales/en-US/aboutdebugging.properties
--- a/devtools/client/aboutdebugging/components/addons/controls.js
+++ b/devtools/client/aboutdebugging/components/addons/controls.js
@@ -4,16 +4,18 @@
 
 /* eslint-env browser */
 /* globals AddonManager */
 
 "use strict";
 
 loader.lazyImporter(this, "AddonManager",
   "resource://gre/modules/AddonManager.jsm");
+loader.lazyImporter(this, "AppConstants",
+  "resource://gre/modules/AppConstants.jsm");
 
 const { Cc, Ci } = require("chrome");
 const { createFactory, createClass, DOM: dom } =
   require("devtools/client/shared/vendor/react");
 const Services = require("Services");
 const AddonsInstallError = createFactory(require("./install-error"));
 
 const Strings = Services.strings.createBundle(
@@ -56,18 +58,49 @@ module.exports = createClass({
 
     AddonManager.installTemporaryAddon(file)
       .catch(e => {
         console.error(e);
         this.setState({ installError: e.message });
       });
   },
 
+  loadAddonFromSources() {
+    this.setState({ installError: null });
+    let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
+    fp.init(window,
+      Strings.GetStringFromName("selectAddonFromSources"),
+      Ci.nsIFilePicker.modeGetFolder);
+    let res = fp.show();
+    if (res == Ci.nsIFilePicker.returnCancel || !fp.file ||
+        !fp.file.isDirectory()) {
+      return;
+    }
+
+    AddonManager.installAddonFromSources(fp.file)
+      .catch(e => {
+        console.error(e);
+        this.setState({ installError: e.message });
+      });
+  },
+
   render() {
     let { debugDisabled } = this.props;
+    let signRequired = Services.prefs.getBoolPref(
+      "xpinstall.signatures.required");
+    let loadFromSourcesTooltip;
+    if (signRequired) {
+      if (AppConstants.RELEASE_OR_BETA) {
+        loadFromSourcesTooltip = Strings.GetStringFromName(
+          "loadPermanentlyAddon.releaseTooltip");
+      } else {
+        loadFromSourcesTooltip = Strings.GetStringFromName(
+          "loadPermanentlyAddon.signature");
+      }
+    }
 
     return dom.div({ className: "addons-top" },
       dom.div({ className: "addons-controls" },
         dom.div({ className: "addons-options" },
           dom.input({
             id: "enable-addon-debugging",
             type: "checkbox",
             checked: !debugDisabled,
@@ -81,13 +114,19 @@ module.exports = createClass({
           "(",
           dom.a({ href: MORE_INFO_URL, target: "_blank" },
             Strings.GetStringFromName("moreInfo")),
           ")"
         ),
         dom.button({
           id: "load-addon-from-file",
           onClick: this.loadAddonFromFile,
-        }, Strings.GetStringFromName("loadTemporaryAddon"))
+        }, Strings.GetStringFromName("loadTemporaryAddon")),
+        dom.button({
+          id: "load-addon-from-sources",
+          onClick: this.loadAddonFromSources,
+          disabled: signRequired,
+          title: loadFromSourcesTooltip
+        }, Strings.GetStringFromName("loadPermanentlyAddon"))
       ),
       AddonsInstallError({ error: this.state.installError }));
   }
 });
--- a/devtools/client/locales/en-US/aboutdebugging.properties
+++ b/devtools/client/locales/en-US/aboutdebugging.properties
@@ -40,25 +40,47 @@ addonDebugging.tooltip = Turning this on
 # with documentation.
 moreInfo = more info
 
 # LOCALIZATION NOTE (loadTemporaryAddon):
 # This string is displayed as a label of a button that allows the user to
 # load additional add-ons.
 loadTemporaryAddon = Load Temporary Add-on
 
+# LOCALIZATION NOTE (loadPermanentlyAddon):
+# This string is displayed as a label of a button that allows the user to
+# load additional add-ons.
+loadPermanentlyAddon = Load Unpackaged Add-on Permanently
+
+# LOCALIZATION NOTE (loadPermanentlyAddon.releaseTooltip):
+# This string is displayed as a tooltip of the 'Load Unpackaged Add-on
+# Permanently' button when running on release build where this button
+# is always disabled.
+loadPermanentlyAddon.releaseTooltip = This features only work on non-release build like Developer Edition or Nightly
+
+# LOCALIZATION NOTE (loadPermanentlyAddon.signature):
+# This string is displayed as a tooltip of the 'Load Unpackaged Add-on
+# Permanently' button when the signature preference is turned on and the button
+# is disabled.
+loadPermanentlyAddon.signature = 'xpinstall.signatures.required' preference needs to be toggled to false
+
 # LOCALIZATION NOTE (extensions):
 # This string is displayed as a header above the list of loaded add-ons.
 extensions = Extensions
 
 # LOCALIZATION NOTE (selectAddonFromFile2):
 # This string is displayed as the title of the file picker that appears when
 # the user clicks the 'Load Temporary Add-on' button
 selectAddonFromFile2 = Select Manifest File or Package (.xpi)
 
+# LOCALIZATION NOTE (selectAddonFromSources):
+# This string is displayed as the title of the file picker that appears when
+# the user clicks the 'Load Unpacked Add-on Permanently' button
+selectAddonFromSources = Select Add-on directory
+
 # LOCALIZATION NOTE (reload):
 # This string is displayed as a label of the button that reloads a given addon.
 reload = Reload
 
 # LOCALIZATION NOTE (reloadDisabledTooltip):
 # This string is displayed in a tooltip that appears when hovering over a
 # disabled 'reload' button.
 reloadDisabledTooltip = Only temporarily installed add-ons can be reloaded