Bug 707328: backgroundUpdateCheck isn't firing its complete notification correctly. r=Unfocused
authorDave Townsend <dtownsend@oxymoronical.com>
Fri, 02 Dec 2011 16:58:22 -0800
changeset 82004 99e27f500ad32a2e3fffc65372f87f5ea677dc8e
parent 82003 dcf31efc8c12acad913f829c769298758b03310b
child 82005 1b9ca56d4aab132ab290aeecafbcf3740894aaa5
push idunknown
push userunknown
push dateunknown
reviewersUnfocused
bugs707328
milestone11.0a1
Bug 707328: backgroundUpdateCheck isn't firing its complete notification correctly. r=Unfocused
toolkit/mozapps/extensions/AddonManager.jsm
toolkit/mozapps/extensions/XPIProvider.jsm
toolkit/mozapps/extensions/test/xpcshell/data/test_backgroundupdate.rdf
toolkit/mozapps/extensions/test/xpcshell/test_backgroundupdate.js
toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini
--- a/toolkit/mozapps/extensions/AddonManager.jsm
+++ b/toolkit/mozapps/extensions/AddonManager.jsm
@@ -627,16 +627,17 @@ var AddonManagerInternal = {
       }
     }
 
     let scope = {};
     Components.utils.import("resource://gre/modules/AddonRepository.jsm", scope);
     Components.utils.import("resource://gre/modules/LightweightThemeManager.jsm", scope);
     scope.LightweightThemeManager.updateCurrentTheme();
 
+    pendingUpdates++;
     this.getAllAddons(function getAddonsCallback(aAddons) {
       // Repopulate repository cache first, to ensure compatibility overrides
       // are up to date before checking for addon updates.
       var ids = [a.id for each (a in aAddons)];
       scope.AddonRepository.repopulateCache(ids, function BUC_repopulateCacheCallback() {
         AddonManagerInternal.updateAddonRepositoryData(function BUC_updateAddonCallback() {
 
           pendingUpdates += aAddons.length;
--- a/toolkit/mozapps/extensions/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/XPIProvider.jsm
@@ -3358,16 +3358,21 @@ var XPIProvider = {
    *
    * @param  aCallback
    *         Function to call when operation is complete.
    */
   updateAddonRepositoryData: function XPI_updateAddonRepositoryData(aCallback) {
     let self = this;
     XPIDatabase.getVisibleAddons(null, function UARD_getVisibleAddonsCallback(aAddons) {
       let pending = aAddons.length;
+      if (pending == 0) {
+        aCallback();
+        return;
+      }
+
       function notifyComplete() {
         if (--pending == 0)
           aCallback();
       }
 
       aAddons.forEach(function UARD_forEachCallback(aAddon) {
         AddonRepository.getCachedAddonByID(aAddon.id,
                                            function UARD_getCachedAddonCallback(aRepoAddon) {
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/data/test_backgroundupdate.rdf
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<RDF:RDF xmlns:RDF="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+         xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+
+  <RDF:Description about="urn:mozilla:extension:addon1@tests.mozilla.org">
+    <em:updates>
+      <RDF:Seq>
+        <!-- app id compatible update available -->
+        <RDF:li>
+          <RDF:Description>
+            <em:version>2</em:version>
+            <em:targetApplication>
+              <RDF:Description>
+                <em:id>xpcshell@tests.mozilla.org</em:id>
+                <em:minVersion>1</em:minVersion>
+                <em:maxVersion>1</em:maxVersion>
+                <em:updateLink>http://localhost:4444/broken.xpi</em:updateLink>
+              </RDF:Description>
+            </em:targetApplication>
+          </RDF:Description>
+        </RDF:li>
+      </RDF:Seq>
+    </em:updates>
+  </RDF:Description>
+
+  <RDF:Description about="urn:mozilla:extension:addon2@tests.mozilla.org">
+    <em:updates>
+      <RDF:Seq>
+        <!-- app id compatible update available -->
+        <RDF:li>
+          <RDF:Description>
+            <em:version>2</em:version>
+            <em:targetApplication>
+              <RDF:Description>
+                <em:id>xpcshell@tests.mozilla.org</em:id>
+                <em:minVersion>1</em:minVersion>
+                <em:maxVersion>1</em:maxVersion>
+                <em:updateLink>http://localhost:4444/broken.xpi</em:updateLink>
+              </RDF:Description>
+            </em:targetApplication>
+          </RDF:Description>
+        </RDF:li>
+      </RDF:Seq>
+    </em:updates>
+  </RDF:Description>
+
+</RDF:RDF>
+
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_backgroundupdate.js
@@ -0,0 +1,105 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+// This verifies that background update notifications work as expected
+
+// The test extension uses an insecure update url.
+Services.prefs.setBoolPref(PREF_EM_CHECK_UPDATE_SECURITY, false);
+
+do_load_httpd_js();
+var testserver;
+const profileDir = gProfD.clone();
+profileDir.append("extensions");
+
+function run_test() {
+  createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2");
+
+  // Create and configure the HTTP server.
+  testserver = new nsHttpServer();
+  testserver.registerDirectory("/data/", do_get_file("data"));
+  testserver.registerDirectory("/addons/", do_get_file("addons"));
+  testserver.start(4444);
+
+  startupManager();
+
+  do_test_pending();
+  run_test_1();
+}
+
+function end_test() {
+  testserver.stop(do_test_finished);
+}
+
+// Verify that with no add-ons installed the background update notifications get
+// called
+function run_test_1() {
+  AddonManager.getAddonsByTypes(["extension", "theme", "locale"], function(aAddons) {
+    do_check_eq(aAddons.length, 0);
+
+    Services.obs.addObserver(function() {
+      Services.obs.removeObserver(arguments.callee, "addons-background-update-complete");
+
+      run_test_2();
+    }, "addons-background-update-complete", false);
+
+    AddonManagerPrivate.backgroundUpdateCheck();
+  });
+}
+
+// Verify that with two add-ons installed both of which claim to have updates
+// available we get the notification after both updates attempted to start
+function run_test_2() {
+  writeInstallRDFForExtension({
+    id: "addon1@tests.mozilla.org",
+    version: "1.0",
+    updateURL: "http://localhost:4444/data/test_backgroundupdate.rdf",
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "1",
+      maxVersion: "1"
+    }],
+    name: "Test Addon 1",
+  }, profileDir);
+
+  writeInstallRDFForExtension({
+    id: "addon2@tests.mozilla.org",
+    version: "1.0",
+    updateURL: "http://localhost:4444/data/test_backgroundupdate.rdf",
+    targetApplications: [{
+      id: "xpcshell@tests.mozilla.org",
+      minVersion: "1",
+      maxVersion: "1"
+    }],
+    name: "Test Addon 2",
+  }, profileDir);
+
+  restartManager();
+
+  let installCount = 0;
+  let completeCount = 0;
+  let sawCompleteNotification = false;
+
+  Services.obs.addObserver(function() {
+    Services.obs.removeObserver(arguments.callee, "addons-background-update-complete");
+
+    do_check_eq(installCount, 2);
+    sawCompleteNotification = true;
+  }, "addons-background-update-complete", false);
+
+  AddonManager.addInstallListener({
+    onNewInstall: function(aInstall) {
+      installCount++;
+    },
+
+    onDownloadFailed: function(aInstall) {
+      completeCount++;
+      if (completeCount == 2) {
+        do_check_true(sawCompleteNotification);
+        end_test();
+      }
+    }
+  });
+
+  AddonManagerPrivate.backgroundUpdateCheck();
+}
--- a/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini
+++ b/toolkit/mozapps/extensions/test/xpcshell/xpcshell.ini
@@ -4,16 +4,17 @@ tail =
 
 [test_AddonRepository.js]
 # Bug 676992: test consistently hangs on Android
 skip-if = os == "android"
 [test_AddonRepository_cache.js]
 # Bug 676992: test consistently hangs on Android
 skip-if = os == "android"
 [test_LightweightThemeManager.js]
+[test_backgroundupdate.js]
 [test_badschema.js]
 [test_blocklistchange.js]
 # Bug 676992: test consistently hangs on Android
 skip-if = os == "android"
 [test_bootstrap.js]
 # Bug 676992: test consistently hangs on Android
 skip-if = os == "android"
 [test_bug299716.js]