Bug 563135: Add-ons manager should expose outdated plugins. r=Unfocused, a=blocking-b6
authorDave Townsend <dtownsend@oxymoronical.com>
Wed, 01 Sep 2010 09:58:42 -0700
changeset 51836 7739cff04a0be9af3e16fdc499b1b2679fb89d4b
parent 51835 ea01bf6029f18d47a0882189ef8aed6b806daf08
child 51837 6654555a3ca78df939d2452fe142dc47fe36596b
push idunknown
push userunknown
push dateunknown
reviewersUnfocused, blocking-b6
bugs563135
milestone2.0b6pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 563135: Add-ons manager should expose outdated plugins. r=Unfocused, a=blocking-b6
toolkit/locales/en-US/chrome/mozapps/extensions/extensions.properties
toolkit/mozapps/extensions/content/extensions.js
toolkit/mozapps/extensions/content/extensions.xml
toolkit/mozapps/extensions/test/browser/browser_details.js
toolkit/mozapps/extensions/test/browser/browser_list.js
--- a/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.properties
+++ b/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.properties
@@ -18,16 +18,19 @@ dateUpdated=Updated %S
 #LOCALIZATION NOTE (notification.incompatible) %1$S is the add-on name, %2$S is brand name, %3$S is application version
 notification.incompatible=%1$S is incompatible with %2$S %3$S.
 #LOCALIZATION NOTE (notification.blocked) %1$S is the add-on name
 notification.blocked=%1$S has been disabled due to security or stability issues.
 notification.blocked.link=More Information
 #LOCALIZATION NOTE (notification.softblocked) %1$S is the add-on name
 notification.softblocked=%1$S is known to cause security or stability issues.
 notification.softblocked.link=More Information
+#LOCALIZATION NOTE (notification.outdated) %1$S is the add-on name
+notification.outdated=An important update is available for %1$S.
+notification.outdated.link=Update Now
 #LOCALIZATION NOTE (notification.enable) %1$S is the add-on name, %2$S is brand name
 notification.enable=%1$S will be enabled after you restart %2$S.
 #LOCALIZATION NOTE (notification.disable) %1$S is the add-on name, %2$S is brand name
 notification.disable=%1$S will be disabled after you restart %2$S.
 #LOCALIZATION NOTE (notification.install) %1$S is the add-on name, %2$S is brand name
 notification.install=%1$S will be installed after you restart %2$S.
 #LOCALIZATION NOTE (notification.uninstall) %1$S is the add-on name, %2$S is brand name
 notification.uninstall=%1$S will be uninstalled after you restart %2$S.
@@ -50,16 +53,19 @@ installCancelled=Install cancelled
 #LOCALIZATION NOTE (details.notification.incompatible) %1$S is the add-on name, %2$S is brand name, %3$S is application version
 details.notification.incompatible=%1$S is incompatible with %2$S %3$S.
 #LOCALIZATION NOTE (details.notification.blocked) %1$S is the add-on name
 details.notification.blocked=%1$S has been disabled due to security or stability issues.
 details.notification.blocked.link=More Information
 #LOCALIZATION NOTE (details.notification.softblocked) %1$S is the add-on name
 details.notification.softblocked=%1$S is known to cause security or stability issues.
 details.notification.softblocked.link=More Information
+#LOCALIZATION NOTE (details.notification.outdated) %1$S is the add-on name
+details.notification.outdated=An important update is available for %1$S.
+details.notification.outdated.link=Update Now
 #LOCALIZATION NOTE (details.notification.enable) %1$S is the add-on name, %2$S is brand name
 details.notification.enable=%1$S will be enabled after you restart %2$S.
 #LOCALIZATION NOTE (details.notification.disable) %1$S is the add-on name, %2$S is brand name
 details.notification.disable=%1$S will be disabled after you restart %2$S.
 #LOCALIZATION NOTE (details.notification.install) %1$S is the add-on name, %2$S is brand name
 details.notification.install=%1$S will be installed after you restart %2$S.
 #LOCALIZATION NOTE (details.notification.uninstall) %1$S is the add-on name, %2$S is brand name
 details.notification.uninstall=%1$S will be uninstalled after you restart %2$S.
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -1818,16 +1818,26 @@ var gDetailView = {
         document.getElementById("detail-warning").textContent = gStrings.ext.formatStringFromName(
           "details.notification.softblocked",
           [this._addon.name], 1
         );
         var warningLink = document.getElementById("detail-warning-link");
         warningLink.value = gStrings.ext.GetStringFromName("details.notification.softblocked.link");
         warningLink.href = Services.urlFormatter.formatURLPref("extensions.blocklist.detailsURL");
         warningLink.hidden = false;
+      } else if (this._addon.blocklistState == Ci.nsIBlocklistService.STATE_OUTDATED) {
+        this.node.setAttribute("notification", "warning");
+        document.getElementById("detail-warning").textContent = gStrings.ext.formatStringFromName(
+          "details.notification.outdated",
+          [this._addon.name], 1
+        );
+        var warningLink = document.getElementById("detail-warning-link");
+        warningLink.value = gStrings.ext.GetStringFromName("details.notification.outdated.link");
+        warningLink.href = Services.urlFormatter.formatURLPref("plugins.update.url");
+        warningLink.hidden = false;
       } else {
         this.node.removeAttribute("notification");
       }
     }
 
     this.node.setAttribute("active", this._addon.isActive);
   },
 
--- a/toolkit/mozapps/extensions/content/extensions.xml
+++ b/toolkit/mozapps/extensions/content/extensions.xml
@@ -1076,16 +1076,25 @@
               this.setAttribute("notification", "warning");
               this._warning.textContent = gStrings.ext.formatStringFromName(
                 "notification.softblocked",
                 [this.mAddon.name], 1
               );
               this._warningLink.value = gStrings.ext.GetStringFromName("notification.softblocked.link");
               this._warningLink.href = Services.urlFormatter.formatURLPref("extensions.blocklist.detailsURL");
               this._warningLink.hidden = false;
+            } else if (this.mAddon.blocklistState == Ci.nsIBlocklistService.STATE_OUTDATED) {
+              this.setAttribute("notification", "warning");
+              this._warning.textContent = gStrings.ext.formatStringFromName(
+                "notification.outdated",
+                [this.mAddon.name], 1
+              );
+              this._warningLink.value = gStrings.ext.GetStringFromName("notification.outdated.link");
+              this._warningLink.href = Services.urlFormatter.formatURLPref("plugins.update.url");
+              this._warningLink.hidden = false;
             } else {
               this.removeAttribute("notification");
             }
           }
 
           this._preferencesBtn.hidden = !this.mAddon.optionsURL;
 
           if (this.hasPermission("enable")) {
--- a/toolkit/mozapps/extensions/test/browser/browser_details.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_details.js
@@ -8,16 +8,17 @@ const PREF_GETADDONS_GETSEARCHRESULTS = 
 const SEARCH_URL = TESTROOT + "browser_details.xml";
 
 var gManagerWindow;
 var gCategoryUtilities;
 
 var gApp = document.getElementById("bundle_brand").getString("brandShortName");
 var gVersion = Services.appinfo.version;
 var gBlocklistURL = Services.urlFormatter.formatURLPref("extensions.blocklist.detailsURL");
+var gPluginURL = Services.urlFormatter.formatURLPref("plugins.update.url");
 var gDate = new Date(2010, 7, 1);
 
 function open_details(aId, aType, aCallback) {
   gCategoryUtilities.openType(aType, function() {
     var list = gManagerWindow.document.getElementById("addon-list");
     var item = list.firstChild;
     while (item) {
       if ("mAddon" in item && item.mAddon.id == aId) {
@@ -106,16 +107,20 @@ function test() {
     id: "addon6@tests.mozilla.org",
     name: "Test add-on 6",
     operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE
   }, {
     id: "addon7@tests.mozilla.org",
     name: "Test add-on 7",
     _userDisabled: true,
     isActive: false
+  }, {
+    id: "addon8@tests.mozilla.org",
+    name: "Test add-on 8",
+    blocklistState: Ci.nsIBlocklistService.STATE_OUTDATED
   }]);
 
   open_manager(null, function(aWindow) {
     gManagerWindow = aWindow;
     gCategoryUtilities = new CategoryUtilities(gManagerWindow);
 
     run_next_test();
   });
@@ -535,8 +540,76 @@ add_test(function() {
       is_element_hidden(get("detail-error"), "Error message should be hidden");
       is_element_hidden(get("detail-error-link"), "Error link should be hidden");
       is_element_hidden(get("detail-pending"), "Pending message should be hidden");
 
       run_next_test();
     });
   });
 });
+
+// Opens and tests the details view for add-on 8
+add_test(function() {
+  open_details("addon8@tests.mozilla.org", "extension", function() {
+    is(get("detail-name").value, "Test add-on 8", "Name should be correct");
+
+    is_element_hidden(get("detail-prefs"), "Preferences button should be hidden");
+    is_element_hidden(get("detail-enable"), "Enable button should be hidden");
+    is_element_visible(get("detail-disable"), "Disable button should be visible");
+    is_element_visible(get("detail-uninstall"), "Remove button should be visible");
+
+    is_element_visible(get("detail-warning"), "Warning message should be visible");
+    is(get("detail-warning").textContent, "An important update is available for Test add-on 8.", "Warning message should be correct");
+    is_element_visible(get("detail-warning-link"), "Warning link should be visible");
+    is(get("detail-warning-link").value, "Update Now", "Warning link text should be correct");
+    is(get("detail-warning-link").href, gPluginURL, "Warning link should be correct");
+    is_element_hidden(get("detail-error"), "Error message should be hidden");
+    is_element_hidden(get("detail-error-link"), "Error link should be hidden");
+    is_element_hidden(get("detail-pending"), "Pending message should be hidden");
+
+    // Disable it
+    EventUtils.synthesizeMouse(get("detail-disable"), 2, 2, {}, gManagerWindow);
+    is_element_hidden(get("detail-prefs"), "Preferences button should be hidden");
+    is_element_visible(get("detail-enable"), "Enable button should be visible");
+    is_element_hidden(get("detail-disable"), "Disable button should be hidden");
+    is_element_visible(get("detail-uninstall"), "Remove button should be visible");
+
+    is_element_hidden(get("detail-warning"), "Warning message should be hidden");
+    is_element_hidden(get("detail-warning-link"), "Warning link should be hidden");
+    is_element_hidden(get("detail-error"), "Error message should be hidden");
+    is_element_hidden(get("detail-error-link"), "Error link should be hidden");
+    is_element_visible(get("detail-pending"), "Pending message should be visible");
+    is(get("detail-pending").textContent, "Test add-on 8 will be disabled after you restart " + gApp + ".", "Pending message should be correct");
+
+    // Reopen it
+    open_details("addon8@tests.mozilla.org", "extension", function() {
+      is_element_hidden(get("detail-prefs"), "Preferences button should be hidden");
+      is_element_visible(get("detail-enable"), "Enable button should be visible");
+      is_element_hidden(get("detail-disable"), "Disable button should be hidden");
+      is_element_visible(get("detail-uninstall"), "Remove button should be visible");
+
+      is_element_hidden(get("detail-warning"), "Warning message should be hidden");
+      is_element_hidden(get("detail-warning-link"), "Warning link should be hidden");
+      is_element_hidden(get("detail-error"), "Error message should be hidden");
+      is_element_hidden(get("detail-error-link"), "Error link should be hidden");
+      is_element_visible(get("detail-pending"), "Pending message should be visible");
+      is(get("detail-pending").textContent, "Test add-on 8 will be disabled after you restart " + gApp + ".", "Pending message should be correct");
+
+      // Undo disabling
+      EventUtils.synthesizeMouse(get("detail-undo"), 2, 2, {}, gManagerWindow);
+      is_element_hidden(get("detail-prefs"), "Preferences button should be hidden");
+      is_element_hidden(get("detail-enable"), "Enable button should be hidden");
+      is_element_visible(get("detail-disable"), "Disable button should be visible");
+      is_element_visible(get("detail-uninstall"), "Remove button should be visible");
+
+      is_element_visible(get("detail-warning"), "Warning message should be visible");
+      is(get("detail-warning").textContent, "An important update is available for Test add-on 8.", "Warning message should be correct");
+      is_element_visible(get("detail-warning-link"), "Warning link should be visible");
+      is(get("detail-warning-link").value, "Update Now", "Warning link text should be correct");
+      is(get("detail-warning-link").href, gPluginURL, "Warning link should be correct");
+      is_element_hidden(get("detail-error"), "Error message should be hidden");
+      is_element_hidden(get("detail-error-link"), "Error link should be hidden");
+      is_element_hidden(get("detail-pending"), "Pending message should be hidden");
+
+      run_next_test();
+    });
+  });
+});
--- a/toolkit/mozapps/extensions/test/browser/browser_list.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_list.js
@@ -6,16 +6,17 @@
 
 var gProvider;
 var gManagerWindow;
 var gCategoryUtilities;
 
 var gApp = document.getElementById("bundle_brand").getString("brandShortName");
 var gVersion = Services.appinfo.version;
 var gBlocklistURL = Services.urlFormatter.formatURLPref("extensions.blocklist.detailsURL");
+var gPluginURL = Services.urlFormatter.formatURLPref("plugins.update.url");
 var gDate = new Date(2010, 7, 16);
 
 function test() {
   waitForExplicitFinish();
 
   gProvider = new MockProvider();
 
   gProvider.createAddons([{
@@ -53,16 +54,20 @@ function test() {
     name: "Test add-on 5",
     isActive: false,
     blocklistState: Ci.nsIBlocklistService.STATE_BLOCKED,
     appDisabled: true
   }, {
     id: "addon6@tests.mozilla.org",
     name: "Test add-on 6",
     operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE
+  }, {
+    id: "addon7@tests.mozilla.org",
+    name: "Test add-on 7",
+    blocklistState: Ci.nsIBlocklistService.STATE_OUTDATED,
   }]);
 
   open_manager(null, function(aWindow) {
     gManagerWindow = aWindow;
     gCategoryUtilities = new CategoryUtilities(gManagerWindow);
     run_next_test();
   });
 }
@@ -96,17 +101,17 @@ function get_class_node(parent, cls) {
   return parent.ownerDocument.getAnonymousElementByAttribute(parent, "class", cls);
 }
 
 // Check that the list appears to have displayed correctly and trigger some
 // changes
 add_test(function() {
   gCategoryUtilities.openType("extension", function() {
     let items = get_test_items();
-    is(items.length, 6, "Should be six add-ons installed");
+    is(items.length, 7, "Should be seven add-ons installed");
 
     info("Addon 1");
     let addon = items[0];
     addon.parentNode.ensureElementIsVisible(addon);
     is(get_node(addon, "name").value, "Test add-on", "Name should be correct");
     is_element_visible(get_node(addon, "version"), "Version should be visible");
     is(get_node(addon, "version").value, "1.0", "Version should be correct");
     is_element_visible(get_node(addon, "description"), "Description should be visible");
@@ -275,16 +280,49 @@ add_test(function() {
     is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible");
 
     is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden");
     is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden");
     is_element_hidden(get_node(addon, "error"), "Error message should be visible");
     is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden");
     is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden");
 
+    info("Addon 7");
+    addon = items[6];
+    addon.parentNode.ensureElementIsVisible(addon);
+    is(get_node(addon, "name").value, "Test add-on 7", "Name should be correct");
+
+    is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden");
+    is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden");
+    is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible");
+    is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible");
+
+    is_element_visible(get_node(addon, "warning"), "Warning message should be hidden");
+    is(get_node(addon, "warning").textContent, "An important update is available for Test add-on 7.", "Warning message should be correct");
+    is_element_visible(get_node(addon, "warning-link"), "Warning link should be visible");
+    is(get_node(addon, "warning-link").value, "Update Now", "Warning link text should be correct");
+    is(get_node(addon, "warning-link").href, gPluginURL, "Warning link should be correct");
+    is_element_hidden(get_node(addon, "error"), "Error message should be hidden");
+    is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden");
+    is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden");
+
+    info("Disabling");
+    EventUtils.synthesizeMouse(get_node(addon, "disable-btn"), 2, 2, {}, gManagerWindow);
+    is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden");
+    is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible");
+    is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden");
+    is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible");
+
+    is_element_hidden(get_node(addon, "warning"), "Warning message should be visible");
+    is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden");
+    is_element_hidden(get_node(addon, "error"), "Error message should be hidden");
+    is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden");
+    is_element_visible(get_node(addon, "pending"), "Pending message should be visible");
+    is(get_node(addon, "pending").textContent, "Test add-on 7 will be disabled after you restart " + gApp + ".", "Pending message should be correct");
+
     run_next_test();
   });
 });
 
 // Check the add-ons are now in the right state
 add_test(function() {
   AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",
                                "addon2@tests.mozilla.org",
@@ -300,17 +338,17 @@ add_test(function() {
 });
 
 // Reload the list to make sure the changes are still pending and that undoing
 // works
 add_test(function() {
   gCategoryUtilities.openType("plugin", function() {
     gCategoryUtilities.openType("extension", function() {
       let items = get_test_items();
-      is(items.length, 6, "Should be six add-ons installed");
+      is(items.length, 7, "Should be seven add-ons installed");
 
       info("Addon 1");
       let addon = items[0];
       addon.parentNode.ensureElementIsVisible(addon);
       is(get_node(addon, "name").value, "Test add-on", "Name should be correct");
       is_element_visible(get_node(addon, "version"), "Version should be visible");
       is(get_node(addon, "version").value, "1.0", "Version should be correct");
       is_element_visible(get_node(addon, "description"), "Description should be visible");
@@ -442,16 +480,49 @@ add_test(function() {
       is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible");
 
       is_element_hidden(get_node(addon, "warning"), "Warning message should be hidden");
       is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden");
       is_element_hidden(get_node(addon, "error"), "Error message should be visible");
       is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden");
       is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden");
 
+      info("Addon 7");
+      addon = items[6];
+      addon.parentNode.ensureElementIsVisible(addon);
+      is(get_node(addon, "name").value, "Test add-on 7", "Name should be correct");
+
+      is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden");
+      is_element_visible(get_node(addon, "enable-btn"), "Enable button should be visible");
+      is_element_hidden(get_node(addon, "disable-btn"), "Disable button should be hidden");
+      is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible");
+
+      is_element_hidden(get_node(addon, "warning"), "Warning message should be visible");
+      is_element_hidden(get_node(addon, "warning-link"), "Warning link should be hidden");
+      is_element_hidden(get_node(addon, "error"), "Error message should be hidden");
+      is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden");
+      is_element_visible(get_node(addon, "pending"), "Pending message should be visible");
+      is(get_node(addon, "pending").textContent, "Test add-on 7 will be disabled after you restart " + gApp + ".", "Pending message should be correct");
+
+      info("Undoing");
+      EventUtils.synthesizeMouse(get_node(addon, "undo"), 2, 2, {}, gManagerWindow);
+      is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden");
+      is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden");
+      is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible");
+      is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible");
+
+      is_element_visible(get_node(addon, "warning"), "Warning message should be hidden");
+      is(get_node(addon, "warning").textContent, "An important update is available for Test add-on 7.", "Warning message should be correct");
+      is_element_visible(get_node(addon, "warning-link"), "Warning link should be visible");
+      is(get_node(addon, "warning-link").value, "Update Now", "Warning link text should be correct");
+      is(get_node(addon, "warning-link").href, gPluginURL, "Warning link should be correct");
+      is_element_hidden(get_node(addon, "error"), "Error message should be hidden");
+      is_element_hidden(get_node(addon, "error-link"), "Error link should be hidden");
+      is_element_hidden(get_node(addon, "pending"), "Pending message should be hidden");
+
       run_next_test();
     });
   });
 });
 
 // Check the add-ons are now in the right state
 add_test(function() {
   AddonManager.getAddonsByIDs(["addon1@tests.mozilla.org",