Bug 675252 - Check for locale updates before updating Fennec. r=mfinkle
authorWes Johnston <wjohnston@mozilla.com>
Mon, 15 Aug 2011 10:42:52 -0700
changeset 75320 083551a45a833bb34e8d0ef68e7fcbd49dee6851
parent 75319 bc3e24e625c2975847932af2f475dbf3fe408dca
child 75321 485f0838da930c169ee790875405dfc0760b754e
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
reviewersmfinkle
bugs675252
milestone8.0a1
Bug 675252 - Check for locale updates before updating Fennec. r=mfinkle
mobile/components/UpdatePrompt.js
mobile/modules/LocaleRepository.jsm
--- a/mobile/components/UpdatePrompt.js
+++ b/mobile/components/UpdatePrompt.js
@@ -53,16 +53,26 @@ XPCOMUtils.defineLazyGetter(this, "gUpda
 XPCOMUtils.defineLazyGetter(this, "gBrandBundle", function aus_gBrandBundle() {
   return Services.strings.createBundle("chrome://branding/locale/brand.properties");
 });
 
 XPCOMUtils.defineLazyGetter(this, "gBrowserBundle", function aus_gBrowserBundle() {
   return Services.strings.createBundle("chrome://browser/locale/browser.properties");
 });
 
+XPCOMUtils.defineLazyGetter(this, "AddonManager", function() {
+  Cu.import("resource://gre/modules/AddonManager.jsm");
+  return AddonManager;
+});
+
+XPCOMUtils.defineLazyGetter(this, "LocaleRepository", function() {
+  Cu.import("resource://gre/modules/LocaleRepository.jsm");
+  return LocaleRepository;
+});
+
 function getPref(func, preference, defaultValue) {
   try {
     return Services.prefs[func](preference);
   } catch (e) {}
   return defaultValue;
 }
 
 // -----------------------------------------------------------------------
@@ -187,23 +197,55 @@ UpdatePrompt.prototype = {
     let imageUrl = "";
     this._showNotification(aUpdate, title, text, imageUrl, "available");
   },
 
   showUpdateDownloaded: function UP_showUpdateDownloaded(aUpdate, aBackground) {
     if (!this._enabled)
       return;
 
+    // uninstall all installed locales
+    AddonManager.getAddonsByTypes(["locale"], (function (aAddons) {
+      if (aAddons.length > 0) {
+        let listener = this.getAddonListener(aUpdate, this);
+        AddonManager.addAddonListener(listener);  
+        aAddons.forEach(function(aAddon) {
+          listener._uninstalling.push(aAddon.id);
+          aAddon.uninstall();
+        }, this);
+      } else {
+        this._showDownloadedNotification(aUpdate);
+      }
+    }).bind(this));
+  },
+
+  _showDownloadedNotification: function UP_showDlNotification(aUpdate) {
     let stringsPrefix = "updateDownloaded_" + aUpdate.type + ".";
     let title = gUpdateBundle.formatStringFromName(stringsPrefix + "title", [aUpdate.name], 1);
     let text = gUpdateBundle.GetStringFromName(stringsPrefix + "text");
     let imageUrl = "";
     this._showNotification(aUpdate, title, text, imageUrl, "downloaded");
   },
 
+  _uninstalling: [],
+  _installing: [],
+  _currentUpdate: null,
+
+  _reinstallLocales: function UP_reinstallLocales(aUpdate, aListener, aPending) {
+    LocaleRepository.getLocales((function(aLocales) {
+      aLocales.forEach(function(aLocale, aIndex, aArray) {
+        let index = aPending.indexOf(aLocale.addon.id);
+        if (index > -1) {
+          aListener._installing.push(aLocale.addon.id);
+          aLocale.addon.install.install();
+        }
+      }, this);
+    }).bind(this), { buildID: aUpdate.buildID });
+  },
+
   showUpdateInstalled: function UP_showUpdateInstalled() {
     if (!this._enabled || !getPref("getBoolPref", "app.update.showInstalledUI", false))
       return;
 
     let title = gBrandBundle.GetStringFromName("brandShortName");
     let text = gUpdateBundle.GetStringFromName("installSuccess");
     let imageUrl = "";
     this._showNotification(aUpdate, title, text, imageUrl, "installed");
@@ -253,13 +295,44 @@ UpdatePrompt.prototype = {
   // When new data has been downloaded
   onProgress: function(request, context, progress, maxProgress) {
     this._updateDownloadProgress(progress, maxProgress);
   },
 
   // When we have new status text
   onStatus: function(request, context, status, statusText) {
     // NOT IMPL
+  },
+
+  // -------------------------------
+  // AddonListener
+  // -------------------------------
+  getAddonListener: function(aUpdate, aUpdatePrompt) {
+    return {
+      _installing: [],
+      _uninstalling: [],
+      onInstalling: function(aAddon, aNeedsRestart) {
+        let index = this._installing.indexOf(aAddon.id);
+        if (index > -1)
+          this._installing.splice(index, 1);
+    
+        if (this._installing.length == 0) {
+          aUpdatePrompt._showDownloadedNotification(aUpdate);
+          AddonManager.removeAddonListener(this);
+        }
+      },
+    
+      onUninstalling: function(aAddon, aNeedsRestart) {
+        let pending = [];
+        let index = this._uninstalling.indexOf(aAddon.id);
+        if (index > -1) {
+          pending.push(aAddon.id);
+          this._uninstalling.splice(index, 1);
+        }
+        if (this._uninstalling.length == 0)
+          aUpdatePrompt._reinstallLocales(aUpdate, this, pending);
+      }
+    }
   }
-  
+
 };
 
 const NSGetFactory = XPCOMUtils.generateNSGetFactory([UpdatePrompt]);
--- a/mobile/modules/LocaleRepository.jsm
+++ b/mobile/modules/LocaleRepository.jsm
@@ -77,24 +77,36 @@ var LocaleRepository = {
     return (textContent.length > 0) ? textContent : null;
   },
   
   _getDescendantTextContent: function _getDescendantTextContent(aElement, aTagName) {
     let descendant = this._getUniqueDescendant(aElement, aTagName);
     return (descendant != null) ? this._getTextContent(descendant) : null;
   },
 
-  getLocales: function getLocales(aCallback) {
-    if (!gServiceURL) {
+  getLocales: function getLocales(aCallback, aFilters) {
+    let url = gServiceURL;
+
+    if (!url) {
       aCallback([]);
       return;
     }
+
+    let buildID = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULAppInfo).QueryInterface(Ci.nsIXULRuntime).appBuildID;
+    if (aFilters) {
+      if (aFilters.buildID)
+        buildid = aFilters.buildID;
+    }
+    buildID = buildID.substring(0,4) + "-" + buildID.substring(4).replace(/\d{2}(?=\d)/g, "$&-");
+    url = url.replace(/%BUILDID_EXPANDED%/g, buildID);
+    url = Services.urlFormatter.formatURL(url);
+
     let request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);
     request.mozBackgroundRequest = true;
-    request.open("GET", gServiceURL, true);
+    request.open("GET", url, true);
     request.overrideMimeType("text/xml");
   
     let self = this;
     request.onreadystatechange = function () {
       if (request.readyState == 4) {
         if (request.status == 200) {
           self.log("---- got response")
           let documentElement = request.responseXML.documentElement;