# ***** 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 The Extension Update Service. # # The Initial Developer of the Original Code is # the Mozilla Foundation. # Portions created by the Initial Developer are Copyright (C) 2011 # the Initial Developer. All Rights Reserved. # # Contributor(s): # Dave Townsend # # 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 ***** "use strict"; Components.utils.import("resource://gre/modules/AddonManager.jsm"); Components.utils.import("resource://gre/modules/AddonRepository.jsm"); Components.utils.import("resource://gre/modules/Services.jsm"); const Cc = Components.classes; const Ci = Components.interfaces; var gView = null; function showView(aView) { gView = aView; gView.show(); // If the view's show method immediately showed a different view then don't // do anything else if (gView != aView) return; let viewNode = document.getElementById(gView.nodeID); viewNode.parentNode.selectedPanel = viewNode; // For testing dispatch an event when the view changes var event = document.createEvent("Events"); event.initEvent("ViewChanged", true, true); viewNode.dispatchEvent(event); } function showButtons(aCancel, aBack, aNext, aDone) { document.getElementById("cancel").hidden = !aCancel; document.getElementById("back").hidden = !aBack; document.getElementById("next").hidden = !aNext; document.getElementById("done").hidden = !aDone; } function isAddonDistroInstalled(aID) { let branch = Services.prefs.getBranch("extensions.installedDistroAddon."); if (!branch.prefHasUserValue(aID)) return false; return branch.getBoolPref(aID); } function orderForScope(aScope) { return aScope == AddonManager.SCOPE_PROFILE ? 1 : 0; } var gAddons = {}; var gChecking = { nodeID: "checking", _progress: null, _addonCount: 0, _completeCount: 0, show: function() { showButtons(true, false, false, false); this._progress = document.getElementById("checking-progress"); let self = this; AddonManager.getAllAddons(function(aAddons) { if (aAddons.length == 0) { window.close(); return; } aAddons = aAddons.filter(function(aAddon) { if (aAddon.type == "plugin") return false; if (aAddon.type == "theme") { // Don't show application shipped themes if (aAddon.scope == AddonManager.SCOPE_APPLICATION) return false; // Don't show already disabled themes if (aAddon.userDisabled) return false; } return true; }); self._addonCount = aAddons.length; self._progress.value = 0; self._progress.max = aAddons.length; self._progress.mode = "determined"; // Ensure compatibility overrides are up to date before checking for // individual addon updates. let ids = [addon.id for each (addon in aAddons)]; AddonRepository.repopulateCache(ids, function() { AddonManagerPrivate.updateAddonRepositoryData(function() { aAddons.forEach(function(aAddon) { // Ignore disabled themes if (aAddon.type != "theme" || !aAddon.userDisabled) { gAddons[aAddon.id] = { addon: aAddon, install: null, wasActive: aAddon.isActive } } aAddon.findUpdates(self, AddonManager.UPDATE_WHEN_NEW_APP_INSTALLED); }); }); }); }); }, onUpdateAvailable: function(aAddon, aInstall) { // If the add-on can be upgraded then remember the new version if (aAddon.permissions & AddonManager.PERM_CAN_UPGRADE) gAddons[aAddon.id].install = aInstall; }, onUpdateFinished: function(aAddon, aError) { this._completeCount++; this._progress.value = this._completeCount; if (this._completeCount < this._addonCount) return; var addons = [gAddons[id] for (id in gAddons)]; addons.sort(function(a, b) { let orderA = orderForScope(a.addon.scope); let orderB = orderForScope(b.addon.scope); if (orderA != orderB) return orderA - orderB; return String.localeCompare(a.addon.name, b.addon.name); }); let rows = document.getElementById("select-rows"); let lastAddon = null; addons.forEach(function(aEntry) { if (lastAddon && orderForScope(aEntry.addon.scope) != orderForScope(lastAddon.scope)) { let separator = document.createElement("separator"); rows.appendChild(separator); } let row = document.createElement("row"); row.setAttribute("id", aEntry.addon.id); row.setAttribute("class", "addon"); rows.appendChild(row); row.setAddon(aEntry.addon, aEntry.install, aEntry.wasActive, isAddonDistroInstalled(aEntry.addon.id)); if (aEntry.install) aEntry.install.addListener(gUpdate); lastAddon = aEntry.addon; }); showView(gSelect); } }; var gSelect = { nodeID: "select", show: function() { this.updateButtons(); }, updateButtons: function() { for (let row = document.getElementById("select-rows").firstChild; row; row = row.nextSibling) { if (row.localName == "separator") continue; if (row.action) { showButtons(false, false, true, false); return; } } showButtons(false, false, false, true); }, next: function() { showView(gConfirm); }, done: function() { window.close(); } }; var gConfirm = { nodeID: "confirm", show: function() { showButtons(false, true, false, true); let box = document.getElementById("confirm-scrollbox").firstChild; while (box) { box.hidden = true; while (box.lastChild != box.firstChild) box.removeChild(box.lastChild); box = box.nextSibling; } for (let row = document.getElementById("select-rows").firstChild; row; row = row.nextSibling) { if (row.localName == "separator") continue; let action = row.action; if (!action) continue; let list = document.getElementById(action + "-list"); list.hidden = false; let item = document.createElement("hbox"); item.setAttribute("id", row._addon.id); item.setAttribute("class", "addon"); item.setAttribute("type", row._addon.type); item.setAttribute("name", row._addon.name); if (action == "update" || action == "enable") item.setAttribute("active", "true"); list.appendChild(item); if (action == "update") showButtons(false, true, true, false); } }, back: function() { showView(gSelect); }, next: function() { showView(gUpdate); }, done: function() { for (let row = document.getElementById("select-rows").firstChild; row; row = row.nextSibling) { if (row.localName != "separator") row.apply(); } window.close(); } } var gUpdate = { nodeID: "update", _progress: null, _waitingCount: 0, _completeCount: 0, _errorCount: 0, show: function() { showButtons(true, false, false, false); this._progress = document.getElementById("update-progress"); for (let row = document.getElementById("select-rows").firstChild; row; row = row.nextSibling) { if (row.localName != "separator") row.apply(); } this._progress.mode = "determined"; this._progress.max = this._waitingCount; this._progress.value = this._completeCount; }, checkComplete: function() { this._progress.value = this._completeCount; if (this._completeCount < this._waitingCount) return; if (this._errorCount > 0) { showView(gErrors); return; } window.close(); }, onDownloadStarted: function(aInstall) { this._waitingCount++; }, onDownloadFailed: function(aInstall) { this._errorCount++; this._completeCount++; this.checkComplete(); }, onInstallFailed: function(aInstall) { this._errorCount++; this._completeCount++; this.checkComplete(); }, onInstallEnded: function(aInstall) { this._completeCount++; this.checkComplete(); } }; var gErrors = { nodeID: "errors", show: function() { showButtons(false, false, false, true); }, done: function() { window.close(); } }; window.addEventListener("load", function() { showView(gChecking); }, false); // When closing the window cancel any pending or in-progress installs window.addEventListener("unload", function() { for (let id in gAddons) { let entry = gAddons[id]; if (!entry.install) return; aEntry.install.removeListener(gUpdate); if (entry.install.state != AddonManager.STATE_INSTALLED && entry.install.state != AddonManager.STATE_DOWNLOAD_FAILED && entry.install.state != AddonManager.STATE_INSTALL_FAILED) { entry.install.cancel(); } } }, false);