gecko/toolkit/mozapps/extensions/content/selectAddons.js

381 lines
10 KiB
JavaScript

# ***** 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 <dtownsend@oxymoronical.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 *****
"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);