Bug 552761: Switch PFS over to the new API. r=robstrong
authorDave Townsend <dtownsend@oxymoronical.com>
Tue, 06 Apr 2010 10:30:59 -0700
changeset 41576 a5a5ebf9c4c3dc5b357201224dcd55a68d699e77
parent 41575 2d8104630e545271c40de4d6e0267470fb5b14f3
child 41577 29083d3e09b3194b3393ed9c6f63c3bead1f99e0
push idunknown
push userunknown
push dateunknown
reviewersrobstrong
bugs552761
milestone1.9.3a5pre
Bug 552761: Switch PFS over to the new API. r=robstrong
toolkit/mozapps/plugins/content/pluginInstallerService.js
toolkit/mozapps/plugins/tests/browser_bug435788.js
--- a/toolkit/mozapps/plugins/content/pluginInstallerService.js
+++ b/toolkit/mozapps/plugins/content/pluginInstallerService.js
@@ -30,17 +30,23 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-const nsIXPIProgressDialog = Components.interfaces.nsIXPIProgressDialog;
+Components.utils.import("resource://gre/modules/AddonManager.jsm");
+
+const DOWNLOAD_STARTED = 0;
+const DOWNLOAD_FINISHED = 1;
+const INSTALL_STARTED = 2;
+const INSTALL_FINISHED = 3;
+const INSTALLS_COMPLETE = 4;
 
 function getLocalizedError(key)
 {
   return document.getElementById("xpinstallStrings").getString(key);
 }
 
 function binaryToHex(input)
 {
@@ -103,38 +109,37 @@ InstallerObserver.prototype = {
 
       var channel = ios.newChannelFromURI(uri);
       this._downloader =
         Components.classes["@mozilla.org/network/downloader;1"].
           createInstance(Components.interfaces.nsIDownloader);
       this._downloader.init(this, resultFile);
       channel.notificationCallbacks = this;
 
-      this._fireNotification(nsIXPIProgressDialog.DOWNLOAD_START, null);
+      this._fireNotification(DOWNLOAD_STARTED, null);
 
       channel.asyncOpen(this._downloader, null);
     }
     catch (e) {
       Components.utils.reportError(e);
-      this._fireNotification(nsIXPIProgressDialog.INSTALL_DONE,
-                             getLocalizedError("error-228"));
+      this._fireNotification(INSTALL_FINISHED, getLocalizedError("error-228"));
       if (resultFile && resultFile.exists())
         resultfile.remove(false);
     }
   },
 
   /**
    * Inform the gPluginInstaller about what's going on.
    */
   _fireNotification: function(aStatus, aErrorMsg)
   {
     gPluginInstaller.pluginInstallationProgress(this._plugin.pid,
                                                 aStatus, aErrorMsg);
 
-    if (aStatus == nsIXPIProgressDialog.INSTALL_DONE) {
+    if (aStatus == INSTALL_FINISHED) {
       --PluginInstallService._installersPending;
       PluginInstallService._fireFinishedNotification();
     }
   },
 
   QueryInterface: function(iid)
   {
     if (iid.equals(Components.interfaces.nsISupports) ||
@@ -153,66 +158,63 @@ InstallerObserver.prototype = {
 
     return null;
   },
 
   onDownloadComplete: function(downloader, request, ctxt, status, result)
   {
     if (!Components.isSuccessCode(status)) {
       // xpinstall error 228 is "Download Error"
-      this._fireNotification(nsIXPIProgressDialog.INSTALL_DONE,
-                             getLocalizedError("error-228"));
+      this._fireNotification(INSTALL_FINISHED, getLocalizedError("error-228"));
       result.remove(false);
       return;
     }
 
-    this._fireNotification(nsIXPIProgressDialog.DOWNLOAD_DONE);
+    this._fireNotification(DOWNLOAD_FINISHED);
 
     if (this._plugin.InstallerHash &&
         !verifyHash(result, this._plugin.InstallerHash)) {
       // xpinstall error 261 is "Invalid file hash..."
-      this._fireNotification(nsIXPIProgressDialog.INSTALL_DONE,
-                             getLocalizedError("error-261"));
+      this._fireNotification(INSTALL_FINISHED, getLocalizedError("error-261"));
       result.remove(false);
       return;
     }
 
-    this._fireNotification(nsIXPIProgressDialog.INSTALL_START);
+    this._fireNotification(INSTALL_STARTED);
 
     result.QueryInterface(Components.interfaces.nsILocalFile);
     try {
       // Make sure the file is executable
       result.permissions = 0770;
       var process = Components.classes["@mozilla.org/process/util;1"]
                               .createInstance(Components.interfaces.nsIProcess);
       process.init(result);
       var self = this;
       process.runAsync([], 0, {
         observe: function(subject, topic, data) {
           if (topic != "process-finished") {
             Components.utils.reportError("Failed to launch installer");
-            self._fireNotification(nsIXPIProgressDialog.INSTALL_DONE,
+            self._fireNotification(INSTALL_FINISHED,
                                    getLocalizedError("error-207"));
           }
           else if (process.exitValue != 0) {
             Components.utils.reportError("Installer returned exit code " + process.exitValue);
-            self._fireNotification(nsIXPIProgressDialog.INSTALL_DONE,
+            self._fireNotification(INSTALL_FINISHED,
                                    getLocalizedError("error-203"));
           }
           else {
-            self._fireNotification(nsIXPIProgressDialog.INSTALL_DONE, null);
+            self._fireNotification(INSTALL_FINISHED, null);
           }
           result.remove(false);
         }
       });
     }
     catch (e) {
       Components.utils.reportError(e);
-      this._fireNotification(nsIXPIProgressDialog.INSTALL_DONE,
-                             getLocalizedError("error-207"));
+      this._fireNotification(INSTALL_FINISHED, getLocalizedError("error-207"));
       result.remove(false);
     }
   },
 
   onProgress: function(aRequest, aContext, aProgress, aProgressMax)
   {
     gPluginInstaller.pluginInstallationProgressMeter(this._plugin.pid,
                                                      aProgress,
@@ -235,73 +237,96 @@ var PluginInstallService = {
    * @param aXPIPlugins       An array of objects which should have the
    *                          properties "pid", "XPILocation",
    *                          and "XPIHash"
    */
   startPluginInstallation: function (aInstallerPlugins,
                                      aXPIPlugins)
   {
     this._xpiPlugins = aXPIPlugins;
-
-    if (this._xpiPlugins.length > 0) {
-      this._xpisDone = false;
+    this._xpisPending = aXPIPlugins.length;
 
-      var xpiManager = Components.classes["@mozilla.org/xpinstall/install-manager;1"]
-                                 .createInstance(Components.interfaces.nsIXPInstallManager);
-      xpiManager.initManagerWithHashes(
-        [plugin.XPILocation for each (plugin in this._xpiPlugins)],
-        [plugin.XPIHash for each (plugin in this._xpiPlugins)],
-        this._xpiPlugins.length, this);
-    }
-    else {
-      this._xpisDone = true;
-    }
+    aXPIPlugins.forEach(function(plugin) {
+      AddonManager.getInstallForURL(plugin.XPILocation, function(install) {
+        install.addListener(PluginInstallService);
+        install.install();
+      }, "application/x-xpinstall", plugin.XPIHash);
+    });
 
     // InstallerObserver may finish immediately so we must initialise the
     // installers after setting the number of installers and xpis pending
     this._installersPending = aInstallerPlugins.length;
     this._installerPlugins = [new InstallerObserver(plugin)
                               for each (plugin in aInstallerPlugins)];
   },
 
   _fireFinishedNotification: function()
   {
-    if (this._installersPending == 0 && this._xpisDone)
-      gPluginInstaller.
-        pluginInstallationProgress(null, nsIXPIProgressDialog.DIALOG_CLOSE,
-                                   null);
+    if (this._installersPending == 0 && this._xpisPending == 0)
+      gPluginInstaller.pluginInstallationProgress(null, INSTALLS_COMPLETE, null);
+  },
+
+  getPidForInstall: function(install) {
+    for (let i = 0; i < this._xpiPlugins.length; i++) {
+      if (install.sourceURL == this._xpiPlugins[i].XPILocation)
+        return this._xpiPlugins[i].pid;
+    }
+    return -1;
+  },
+
+  // InstallListener interface
+  onDownloadStarted: function(install) {
+    var pid = this.getPidForInstall(install);
+    gPluginInstaller.pluginInstallationProgress(pid, DOWNLOAD_STARTED, null);
+  },
+
+  onDownloadProgress: function(install) {
+    var pid = this.getPidForInstall(install);
+    gPluginInstaller.pluginInstallationProgressMeter(pid, install.progress,
+                                                     install.maxProgress);
+  },
+
+  onDownloadEnded: function(install) {
+    var pid = this.getPidForInstall(install);
+    gPluginInstaller.pluginInstallationProgress(pid, DOWNLOAD_FINISHED, null);
   },
 
-  // XPI progress listener stuff
-  onStateChange: function (aIndex, aState, aValue)
-  {
-    // get the pid to return to the wizard
-    var pid = this._xpiPlugins[aIndex].pid;
-    var errorMsg;
+  onDownloadFailed: function(install, error) {
+    var pid = this.getPidForInstall(install);
+    switch (error) {
+    case AddonManager.ERROR_NETWORK_FAILURE:
+      var errorMsg = getLocalizedError("error-228");
+      break;
+    case AddonManager.ERROR_INCORRECT_HASH:
+      var errorMsg = getLocalizedError("error-261");
+      break;
+    case AddonManager.ERROR_CORRUPT_FILE:
+      var errorMsg = getLocalizedError("error-207");
+      break;
+    }
+    gPluginInstaller.pluginInstallationProgress(pid, INSTALL_FINISHED, errorMsg);
 
-    if (aState == nsIXPIProgressDialog.INSTALL_DONE) {
-      if (aValue != 0) {
-        var xpinstallStrings = document.getElementById("xpinstallStrings");
-        try {
-          errorMsg = xpinstallStrings.getString("error" + aValue);
-        }
-        catch (e) {
-          errorMsg = xpinstallStrings.getFormattedString("unknown.error", [aValue]);
-        }
-      }
-    }
-
-    if (aState == nsIXPIProgressDialog.DIALOG_CLOSE) {
-      this._xpisDone = true;
-      this._fireFinishedNotification();
-    }
-    else {
-      gPluginInstaller.pluginInstallationProgress(pid, aState, errorMsg);
-    }
+    this._xpisPending--;
+    this._fireFinishedNotification();
   },
 
-  onProgress: function (aIndex, aValue, aMaxValue)
-  {
-    // get the pid to return to the wizard
-    var pid = this._xpiPlugins[aIndex].pid;
-    gPluginInstaller.pluginInstallationProgressMeter(pid, aValue, aMaxValue);
+  onInstallStarted: function(install) {
+    var pid = this.getPidForInstall(install);
+    gPluginInstaller.pluginInstallationProgress(pid, INSTALL_STARTED, null);
+  },
+
+  onInstallEnded: function(install, addon) {
+    var pid = this.getPidForInstall(install);
+    gPluginInstaller.pluginInstallationProgress(pid, INSTALL_FINISHED, null);
+
+    this._xpisPending--;
+    this._fireFinishedNotification();
+  },
+
+  onInstallFailed: function(install, error) {
+    var pid = this.getPidForInstall(install);
+    gPluginInstaller.pluginInstallationProgress(pid, INSTALL_FINISHED,
+                                                getLocalizedError("error-203"));
+
+    this._xpisPending--;
+    this._fireFinishedNotification();
   }
 }
--- a/toolkit/mozapps/plugins/tests/browser_bug435788.js
+++ b/toolkit/mozapps/plugins/tests/browser_bug435788.js
@@ -1,13 +1,15 @@
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
 const TEST_ROOT = "http://example.com/browser/toolkit/mozapps/plugins/tests/";
 
+Components.utils.import("resource://gre/modules/AddonManager.jsm");
+
 var gPrefs, gPFS, gDS, gSeenAvailable;
 
 function test() {
   waitForExplicitFinish();
 
   gPrefs = Cc["@mozilla.org/preferences-service;1"].
            getService(Ci.nsIPrefBranch);
   gDS = Cc["@mozilla.org/file/directory_service;1"].
@@ -300,22 +302,24 @@ function test_5_available() {
 
 function test_5_complete() {
   ok(gSeenAvailable, "Should have seen the list of available plugins");
   is(getResultCount(), 1, "Should have attempted to install 1 plugin");
   var item = getResultItem("Test extension 1", null);
   ok(item, "Should have seen the installed item");
   is(item.status, "Installed", "Should have been a successful install");
 
-  var em = Cc["@mozilla.org/extensions/manager;1"].
-           getService(Ci.nsIExtensionManager);
-  ok(em.getItemForID("bug435788_1@tests.mozilla.org"), "Should have installed the extension");
-  em.cancelInstallItem("bug435788_1@tests.mozilla.org");
+  AddonManager.getInstalls(null, function(installs) {
+    is(installs.length, 1, "Should be just one install");
+    is(installs[0].state, AddonManager.STATE_INSTALLED, "Should be fully installed");
+    is(installs[0].addon.id, "bug435788_1@tests.mozilla.org", "Should have installed the extension");
+    installs[0].cancel();
 
-  gPFS.document.documentElement.getButton("finish").click();
+    gPFS.document.documentElement.getButton("finish").click();
+  });
 }
 
 // Test a broke xpi (no install.rdf)
 function prepare_test_6() {
   ok(true, "Test 6");
   var missingPluginsArray = {
     "application/x-broken-extension": {
       mimetype: "application/x-broken-extension",
@@ -407,20 +411,24 @@ function test_7_complete() {
   is(getResultCount(), 2, "Should have attempted to install 2 plugins");
   var item = getResultItem("Test extension 1", null);
   ok(item, "Should have seen the installed item");
   is(item.status, "Installed", "Should have been a failed install");
   item = getResultItem("Test extension 2", null);
   ok(item, "Should have seen the installed item");
   is(item.status, "Failed", "Should have been a failed install");
 
-  var em = Cc["@mozilla.org/extensions/manager;1"].
-           getService(Ci.nsIExtensionManager);
-  ok(em.getItemForID("bug435788_1@tests.mozilla.org"), "Should have installed the extension");
-  em.cancelInstallItem("bug435788_1@tests.mozilla.org");
+  AddonManager.getInstalls(null, function(installs) {
+    is(installs.length, 4, "Should be just one install");
+    is(installs[3].state, AddonManager.STATE_DOWNLOAD_FAILED, "Should have failed to download");
+    is(installs[3].addon.id, "bug435788_1@tests.mozilla.org", "Should have installed the extension");
+    installs[3].cancel();
+
+    gPFS.document.documentElement.getButton("finish").click();
+  });
 
   gPFS.document.documentElement.getButton("finish").click();
 }
 
 // Test an xpi with a bad hash
 function prepare_test_8() {
   ok(true, "Test 8");
   var missingPluginsArray = {
@@ -459,19 +467,21 @@ function test_8_available() {
 
 function test_8_complete() {
   ok(gSeenAvailable, "Should have seen the list of available plugins");
   is(getResultCount(), 1, "Should have attempted to install 1 plugin");
   var item = getResultItem("Test extension 3", null);
   ok(item, "Should have seen the installed item");
   is(item.status, "Failed", "Should have not been a successful install");
 
-  var em = Cc["@mozilla.org/extensions/manager;1"].
-           getService(Ci.nsIExtensionManager);
-  ok(!em.getItemForID("bug435788_1@tests.mozilla.org"), "Should not have installed the extension");
+  AddonManager.getInstalls(null, function(installs) {
+    is(installs.length, 5, "Should not be any installs");
+
+    gPFS.document.documentElement.getButton("finish").click();
+  });
 
   gPFS.document.documentElement.getButton("finish").click();
 }
 
 // Test when no plugin exists in the datasource
 function prepare_test_9() {
   ok(true, "Test 9");
   var missingPluginsArray = {