Bug 1170841 - Show warning in add-on manager for add-ons that aren't properly signed. r=liuche
authorMargaret Leibovic <margaret.leibovic@gmail.com>
Wed, 17 Jun 2015 17:46:27 -0700
changeset 250334 e796ac2a6f7a7b95245bce5cd40d66ce309d6ede
parent 250333 1334841730922daf695b651349b55872d77e06af
child 250335 9a24aa4d7e69acf7f4452c638c939aa8c8095890
push id13740
push usermleibovic@mozilla.com
push dateFri, 26 Jun 2015 18:26:46 +0000
treeherderfx-team@e796ac2a6f7a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersliuche
bugs1170841
milestone41.0a1
Bug 1170841 - Show warning in add-on manager for add-ons that aren't properly signed. r=liuche
mobile/android/chrome/content/aboutAddons.js
mobile/android/chrome/content/aboutAddons.xhtml
mobile/android/locales/en-US/chrome/aboutAddons.dtd
mobile/android/themes/core/aboutAddons.css
mobile/android/themes/core/images/grey-caution.svg
mobile/android/themes/core/jar.mn
--- a/mobile/android/chrome/content/aboutAddons.js
+++ b/mobile/android/chrome/content/aboutAddons.js
@@ -97,33 +97,27 @@ var ContextMenus = {
 function init() {
   window.addEventListener("popstate", onPopState, false);
 
   AddonManager.addInstallListener(Addons);
   AddonManager.addAddonListener(Addons);
   Addons.init();
   showList();
   ContextMenus.init();
-
 }
 
 
 function uninit() {
   AddonManager.removeInstallListener(Addons);
   AddonManager.removeAddonListener(Addons);
 }
 
-function openLink(aEvent) {
-  try {
-    let formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].getService(Ci.nsIURLFormatter);
-
-    let url = formatter.formatURLPref(aEvent.currentTarget.getAttribute("pref"));
-    let BrowserApp = gChromeWin.BrowserApp;
-    BrowserApp.addTab(url, { selected: true, parentId: BrowserApp.selectedTab.id });
-  } catch (ex) {}
+function openLink(url) {
+  let BrowserApp = gChromeWin.BrowserApp;
+  BrowserApp.addTab(url, { selected: true, parentId: BrowserApp.selectedTab.id });
 }
 
 function onPopState(aEvent) {
   // Called when back/forward is used to change the state of the page
   if (aEvent.state) {
     // Show the detail page for an addon
     Addons.showDetails(Addons._getElementForAddon(aEvent.state.id));
   } else {
@@ -189,18 +183,24 @@ var Addons = {
     outer.appendChild(inner);
     return outer;
   },
 
   _createBrowseItem: function _createBrowseItem() {
     let outer = document.createElement("div");
     outer.className = "addon-item list-item";
     outer.setAttribute("role", "button");
-    outer.setAttribute("pref", "extensions.getAddons.browseAddons");
-    outer.addEventListener("click", openLink, true);
+    outer.addEventListener("click", function(event) {
+      try {
+        let formatter = Cc["@mozilla.org/toolkit/URLFormatterService;1"].getService(Ci.nsIURLFormatter);
+        openLink(formatter.formatURLPref("extensions.getAddons.browseAddons"));
+      } catch (e) {
+        Cu.reportError(e);
+      }
+    }, true);
 
     let img = document.createElement("img");
     img.className = "icon";
     img.setAttribute("src", AMO_ICON);
     outer.appendChild(img);
 
     let inner = document.createElement("div");
     inner.className = "inner";
@@ -231,16 +231,17 @@ var Addons = {
         break;
       case Ci.nsIBlocklistService.STATE_OUTDATED:
         blocked = "outdated";
         break;
     }
 
     let item = this._createItem(aAddon);
     item.setAttribute("isDisabled", !aAddon.isActive);
+    item.setAttribute("isUnsigned", aAddon.signedState <= AddonManager.SIGNEDSTATE_MISSING);
     item.setAttribute("opType", opType);
     item.setAttribute("updateable", updateable);
     if (blocked)
       item.setAttribute("blockedStatus", blocked);
     item.setAttribute("optionsURL", aAddon.optionsURL || "");
     item.addon = aAddon;
 
     return item;
@@ -271,16 +272,20 @@ var Addons = {
       let browseItem = self._createBrowseItem();
       list.appendChild(browseItem);
     });
 
     document.getElementById("uninstall-btn").addEventListener("click", Addons.uninstallCurrent.bind(this), false);
     document.getElementById("cancel-btn").addEventListener("click", Addons.cancelUninstall.bind(this), false);
     document.getElementById("disable-btn").addEventListener("click", Addons.disable.bind(this), false);
     document.getElementById("enable-btn").addEventListener("click", Addons.enable.bind(this), false);
+
+    document.getElementById("unsigned-learn-more").addEventListener("click", function() {
+      openLink(Services.urlFormatter.formatURLPref("app.support.baseURL") + "unsigned-addons");
+    }, false);
   },
 
   _getOpTypeForOperations: function _getOpTypeForOperations(aOperations) {
     if (aOperations & AddonManager.PENDING_UNINSTALL)
       return "needs-uninstall";
     if (aOperations & AddonManager.PENDING_ENABLE)
       return "needs-enable";
     if (aOperations & AddonManager.PENDING_DISABLE)
@@ -302,16 +307,17 @@ var Addons = {
           text += stripTextNodes(aNode.childNodes[i]);
         }
       }
       return text;
     }
 
     let detailItem = document.querySelector("#addons-details > .addon-item");
     detailItem.setAttribute("isDisabled", aListItem.getAttribute("isDisabled"));
+    detailItem.setAttribute("isUnsigned", aListItem.getAttribute("isUnsigned"));
     detailItem.setAttribute("opType", aListItem.getAttribute("opType"));
     detailItem.setAttribute("optionsURL", aListItem.getAttribute("optionsURL"));
     let addon = detailItem.addon = aListItem.addon;
 
     let favicon = document.querySelector("#addons-details > .addon-item .icon");
     favicon.setAttribute("src", addon.iconURL || AMO_ICON);
 
     detailItem.querySelector(".title").textContent = addon.name;
--- a/mobile/android/chrome/content/aboutAddons.xhtml
+++ b/mobile/android/chrome/content/aboutAddons.xhtml
@@ -42,16 +42,17 @@
       <div class="inner">
         <div class="details">
           <div class="title"></div><div class="version"></div>
         </div>
         <div class="description-full"></div>
         <div class="options-header">&aboutAddons.options;</div>
         <div class="options-box"></div>
       </div>
+      <div class="warn-unsigned">&addonUnsigned.message; <a id="unsigned-learn-more">&addonUnsigned.learnMore;</a></div>
       <div class="status status-uninstalled show-on-uninstall"></div>
       <div class="buttons">
         <button id="enable-btn" class="show-on-disable hide-on-enable hide-on-uninstall" >&addonAction.enable;</button>
         <button id="disable-btn" class="show-on-enable hide-on-disable hide-on-uninstall" >&addonAction.disable;</button>
         <button id="uninstall-btn" class="hide-on-uninstall" >&addonAction.uninstall;</button>
         <button id="cancel-btn" class="show-on-uninstall" >&addonAction.undo;</button>
       </div>
     </div>
--- a/mobile/android/locales/en-US/chrome/aboutAddons.dtd
+++ b/mobile/android/locales/en-US/chrome/aboutAddons.dtd
@@ -5,8 +5,11 @@
 <!ENTITY aboutAddons.title2                     "Add-ons">
 <!ENTITY aboutAddons.header2                    "Your Add-ons">
 <!ENTITY aboutAddons.options                    "Options">
 
 <!ENTITY addonAction.enable                     "Enable">
 <!ENTITY addonAction.disable                    "Disable">
 <!ENTITY addonAction.uninstall                  "Uninstall">
 <!ENTITY addonAction.undo                       "Undo">
+
+<!ENTITY addonUnsigned.message                  "This add-on could not be verified by &brandShortName;.">
+<!ENTITY addonUnsigned.learnMore                "Learn more">
--- a/mobile/android/themes/core/aboutAddons.css
+++ b/mobile/android/themes/core/aboutAddons.css
@@ -1,15 +1,24 @@
 /* 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/. */
 
 %filter substitution
 %include defines.inc
 
+a {
+  text-decoration: none;
+  color: #0096DD;
+}
+
+a:active {
+  color: #0082C6;
+}
+
 .details {
   width: 100%;
 }
 
 .details > div {
   display: inline;
 }
 
@@ -20,16 +29,31 @@
 
 .description {
   width: 100%;
   overflow: hidden;
   white-space: nowrap;
   text-overflow: ellipsis;
 }
 
+.warn-unsigned {
+  border-top: 1px solid @color_about_item_border@;
+  padding: 1em;
+  -moz-padding-start: calc(var(--icon-size) + var(--icon-margin) * 2);
+  background-image: url("chrome://browser/skin/images/grey-caution.svg");
+  background-size: var(--icon-size);
+  background-position: var(--icon-margin);
+  background-repeat: no-repeat;
+  display: none;
+}
+
+.addon-item[isUnsigned] .warn-unsigned {
+  display: block;
+}
+
 .status {
   border-top: 1px solid @color_about_item_border@;
   font-weight: bold;
   padding: 0.5em;
   width: 100%;
 }
 
 .options-header {
new file mode 100644
--- /dev/null
+++ b/mobile/android/themes/core/images/grey-caution.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg width="60px" height="60px" viewBox="0 0 60 60" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
+    <!-- Generator: Sketch 3.3.2 (12043) - http://www.bohemiancoding.com/sketch -->
+    <title>Rectangle 62</title>
+    <desc>Created with Sketch.</desc>
+    <defs/>
+    <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
+        <g id="Artboard-16" sketch:type="MSArtboardGroup" transform="translate(-62.000000, -310.000000)" fill="#AFB1B3">
+            <g id="Insecure-icon-Copy" sketch:type="MSLayerGroup" transform="translate(60.000000, 308.000000)">
+                <path d="M34.6570853,3.89861537 L61.6191658,57.8227763 C62.6631009,60.0994422 61.4905756,62 58.9609325,62 L5.03677158,62 C2.50636943,62 1.33487292,60.0971201 2.37853829,57.8227763 L29.3406187,3.89861537 C30.6694576,1.36596731 33.3285163,1.36828938 34.6570853,3.89861537 Z M28.2013759,23.6360478 C28.2013759,21.5439751 29.9058314,19.8480151 31.998852,19.8480151 C34.0961402,19.8480151 35.7963281,21.5419679 35.7963281,23.6360478 L35.7963281,38.844839 C35.7963281,40.9369118 34.0918726,42.6328718 31.998852,42.6328718 C29.9015639,42.6328718 28.2013759,40.938919 28.2013759,38.844839 L28.2013759,23.6360478 Z M31.998852,54.7847954 C34.0961402,54.7847954 35.7963281,53.0846074 35.7963281,50.9873193 C35.7963281,48.8900311 34.0961402,47.1898431 31.998852,47.1898431 C29.9015639,47.1898431 28.2013759,48.8900311 28.2013759,50.9873193 C28.2013759,53.0846074 29.9015639,54.7847954 31.998852,54.7847954 Z" id="Rectangle-62" sketch:type="MSShapeGroup"/>
+            </g>
+        </g>
+    </g>
+</svg>
\ No newline at end of file
--- a/mobile/android/themes/core/jar.mn
+++ b/mobile/android/themes/core/jar.mn
@@ -68,16 +68,17 @@ chrome.jar:
   skin/images/checkbox_unchecked_pressed.png  (images/checkbox_unchecked_pressed.png)
   skin/images/chevron.png                   (images/chevron.png)
   skin/images/default-app-icon.png          (images/default-app-icon.png)
   skin/images/dropmarker.svg                (images/dropmarker.svg)
   skin/images/dropmarker-right.svg          (images/dropmarker-right.svg)
   skin/images/errorpage-warning.png         (images/errorpage-warning.png)
   skin/images/exitfullscreen-hdpi.png       (images/exitfullscreen-hdpi.png)
   skin/images/fullscreen-hdpi.png           (images/fullscreen-hdpi.png)
+  skin/images/grey-caution.svg              (images/grey-caution.svg)
   skin/images/certerror-warning.png         (images/certerror-warning.png)
   skin/images/errorpage-larry-white.png     (images/errorpage-larry-white.png)
   skin/images/errorpage-larry-black.png     (images/errorpage-larry-black.png)
   skin/images/marketplace-logo.png          (images/marketplace-logo.png)
   skin/images/throbber.png                  (images/throbber.png)
   skin/images/search-clear-30.png           (images/search-clear-30.png)
   skin/images/play-hdpi.png                 (images/play-hdpi.png)
   skin/images/pause-hdpi.png                (images/pause-hdpi.png)