copy from mobile/android/components/UpdatePrompt.js
copy to b2g/components/UpdatePrompt.js
--- a/mobile/android/components/UpdatePrompt.js
+++ b/b2g/components/UpdatePrompt.js
@@ -1,349 +1,65 @@
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is Update Prompt.
- *
- * The Initial Developer of the Original Code is Mozilla Foundation.
- * Portions created by the Initial Developer are Copyright (C) 2010
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Mark Finkle <mfinkle@mozilla.com>
- * Alex Pakhotin <alexp@mozilla.com>
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * 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 ***** */
+/* -*- Mode: Java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=8 et :
+ */
+/* 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/. */
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
-const UPDATE_NOTIFICATION_NAME = "update-app";
-const UPDATE_NOTIFICATION_ICON = "drawable://alert_download_progress";
-
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/Services.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "gUpdateBundle", function aus_gUpdateBundle() {
- return Services.strings.createBundle("chrome://mozapps/locale/update/updates.properties");
-});
-
-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;
-}
-
-function sendMessageToJava(aMsg) {
- let data = Cc["@mozilla.org/android/bridge;1"].getService(Ci.nsIAndroidBridge).handleGeckoMessage(JSON.stringify(aMsg));
- return JSON.parse(data);
-}
-
-// -----------------------------------------------------------------------
-// Update Prompt
-// -----------------------------------------------------------------------
+const VERBOSE = 1;
+let log =
+ VERBOSE ?
+ function log_dump(msg) { dump("UpdatePrompt: "+ msg +"\n"); } :
+ function log_noop(msg) { };
function UpdatePrompt() { }
UpdatePrompt.prototype = {
classID: Components.ID("{88b3eb21-d072-4e3b-886d-f89d8c49fe59}"),
- QueryInterface: XPCOMUtils.generateQI([Ci.nsIUpdatePrompt, Ci.nsIRequestObserver, Ci.nsIProgressEventSink]),
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsIUpdatePrompt]),
+
+ // nsIUpdatePrompt
- get _enabled() {
- return !getPref("getBoolPref", "app.update.silent", false);
- },
+ // FIXME/bug 737601: we should have users opt-in to downloading
+ // updates when on a billed pipe. Initially, opt-in for 3g, but
+ // that doesn't cover all cases.
+ checkForUpdates: function UP_checkForUpdates() { },
+ showUpdateAvailable: function UP_showUpdateAvailable(aUpdate) { },
- _showNotification: function UP__showNotif(aUpdate, aTitle, aText, aImageUrl, aMode) {
- let observer = {
- updatePrompt: this,
- observe: function (aSubject, aTopic, aData) {
- switch (aTopic) {
- case "alertclickcallback":
- this.updatePrompt._handleUpdate(aUpdate, aMode);
- break;
- }
- }
- };
+ showUpdateDownloaded: function UP_showUpdateDownloaded(aUpdate, aBackground) {
+ // FIXME/bug 737598: we should let the user request that the
+ // update be applied later, e.g. if they're in the middle of a
+ // phone call ;).
+
+ log("Update downloaded, restarting to apply it");
- let notifier = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);
- notifier.showAlertNotification(aImageUrl, aTitle, aText, true, "", observer, UPDATE_NOTIFICATION_NAME);
+ let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"].getService(Ci.nsIAppStartup);
+ // NB: on Gonk, we rely on the system process manager to restart
+ // us. Trying to restart here would conflict with the process
+ // manager. We should be using a runtime check to detect Gonk
+ // instead of this gross ifdef, but the ifdef works for now.
+ appStartup.quit(appStartup.eForceQuit
+#ifndef ANDROID
+ | appStartup.eRestart
+#endif
+ );
},
- _handleUpdate: function UP__handleUpdate(aUpdate, aMode) {
- if (aMode == "available") {
- let window = Services.wm.getMostRecentWindow("navigator:browser");
- let title = gUpdateBundle.GetStringFromName("updatesfound_" + aUpdate.type + ".title");
- let brandName = gBrandBundle.GetStringFromName("brandShortName");
-
- // Unconditionally use the "major" type here as for now it is always a new version
- // without additional description required for a minor update message
- let message = gUpdateBundle.formatStringFromName("intro_major", [brandName, aUpdate.displayVersion], 2);
- let button0 = gUpdateBundle.GetStringFromName("okButton");
- let button1 = gUpdateBundle.GetStringFromName("askLaterButton");
- let prompt = Services.prompt;
- let flags = prompt.BUTTON_POS_0 * prompt.BUTTON_TITLE_IS_STRING + prompt.BUTTON_POS_1 * prompt.BUTTON_TITLE_IS_STRING;
+ showUpdateInstalled: function UP_showUpdateInstalled() { },
- let download = (prompt.confirmEx(window, title, message, flags, button0, button1, null, null, {value: false}) == 0);
- if (download) {
- // Start downloading the update in the background
- let aus = Cc["@mozilla.org/updates/update-service;1"].getService(Ci.nsIApplicationUpdateService);
- if (aus.downloadUpdate(aUpdate, true) != "failed") {
- let title = gBrowserBundle.formatStringFromName("alertDownloadsStart", [aUpdate.name], 1);
- this._showNotification(aUpdate, title, "", UPDATE_NOTIFICATION_ICON, "download");
-
- // Add this UI as a listener for active downloads
- aus.addDownloadListener(this);
- }
- }
- } else if(aMode == "downloaded") {
- // Notify all windows that an application quit has been requested
- let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool);
- Services.obs.notifyObservers(cancelQuit, "quit-application-requested", "restart");
-
- // If nothing aborted, restart the app
- if (cancelQuit.data == false) {
- sendMessageToJava({
- gecko: {
- type: "Update:Restart"
- }
- });
- }
+ showUpdateError: function UP_showUpdateError(aUpdate) {
+ if (aUpdate.state == "failed") {
+ log("Failed to download update");
}
},
- _updateDownloadProgress: function UP__updateDownloadProgress(aProgress, aTotal) {
- let alertsService = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);
- let progressListener = alertsService.QueryInterface(Ci.nsIAlertsProgressListener);
- if (progressListener)
- progressListener.onProgress(UPDATE_NOTIFICATION_NAME, aProgress, aTotal);
- },
-
- // -------------------------
- // nsIUpdatePrompt interface
- // -------------------------
-
- // Right now this is used only to check for updates in progress
- checkForUpdates: function UP_checkForUpdates() {
- if (!this._enabled)
- return;
-
- let aus = Cc["@mozilla.org/updates/update-service;1"].getService(Ci.nsIApplicationUpdateService);
- if (!aus.isDownloading)
- return;
-
- let updateManager = Cc["@mozilla.org/updates/update-manager;1"].getService(Ci.nsIUpdateManager);
-
- let updateName = updateManager.activeUpdate ? updateManager.activeUpdate.name : gBrandBundle.GetStringFromName("brandShortName");
- let title = gBrowserBundle.formatStringFromName("alertDownloadsStart", [updateName], 1);
-
- this._showNotification(updateManager.activeUpdate, title, "", UPDATE_NOTIFICATION_ICON, "downloading");
-
- aus.removeDownloadListener(this); // just in case it's already added
- aus.addDownloadListener(this);
- },
-
- showUpdateAvailable: function UP_showUpdateAvailable(aUpdate) {
- if (!this._enabled)
- return;
-
- const PREF_APP_UPDATE_SKIPNOTIFICATION = "app.update.skipNotification";
-
- if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_SKIPNOTIFICATION) &&
- Services.prefs.getBoolPref(PREF_APP_UPDATE_SKIPNOTIFICATION)) {
- Services.prefs.setBoolPref(PREF_APP_UPDATE_SKIPNOTIFICATION, false);
-
- // Notification was already displayed and clicked, so jump to the next step:
- // ask the user about downloading update
- this._handleUpdate(aUpdate, "available");
- return;
- }
-
- let stringsPrefix = "updateAvailable_" + 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, "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);
- // store the buildid of these locales so that we can disable locales when the
- // user updates through a non-updater channel
- Services.prefs.setCharPref("extensions.compatability.locales.buildid", aUpdate.buildID);
- }).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");
- },
-
- showUpdateError: function UP_showUpdateError(aUpdate) {
- if (!this._enabled)
- return;
-
- if (aUpdate.state == "failed") {
- var title = gBrandBundle.GetStringFromName("brandShortName");
- let text = gUpdateBundle.GetStringFromName("updaterIOErrorTitle");
- let imageUrl = "";
- this._showNotification(aUpdate, title, text, imageUrl, "error");
- }
- },
-
- showUpdateHistory: function UP_showUpdateHistory(aParent) {
- // NOT IMPL
- },
-
- // ----------------------------
- // nsIRequestObserver interface
- // ----------------------------
-
- // When the data transfer begins
- onStartRequest: function(request, context) {
- // NOT IMPL
- },
-
- // When the data transfer ends
- onStopRequest: function(request, context, status) {
- let alertsService = Cc["@mozilla.org/alerts-service;1"].getService(Ci.nsIAlertsService);
- let progressListener = alertsService.QueryInterface(Ci.nsIAlertsProgressListener);
- if (progressListener)
- progressListener.onCancel(UPDATE_NOTIFICATION_NAME);
-
-
- let aus = Cc["@mozilla.org/updates/update-service;1"].getService(Ci.nsIApplicationUpdateService);
- aus.removeDownloadListener(this);
- },
-
- // ------------------------------
- // nsIProgressEventSink interface
- // ------------------------------
-
- // 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);
- }
- }
- }
-
+ showUpdateHistory: function UP_showUpdateHistory(aParent) { },
};
const NSGetFactory = XPCOMUtils.generateNSGetFactory([UpdatePrompt]);