зеркало из https://github.com/mozilla/gecko-dev.git
Bug 596343: Users should have exclusive control over selecting their add-ons. r=Unfocused
This commit is contained in:
Родитель
f3ee939112
Коммит
8e0e038bd5
|
@ -0,0 +1,45 @@
|
|||
<!ENTITY upgrade.style "width: 93ch; height: 448px;">
|
||||
|
||||
<!ENTITY checking.heading "Checking Your Add-ons">
|
||||
<!ENTITY checking.progress.label "Checking your add-ons for compatibility with this version of &brandShortName;.">
|
||||
|
||||
<!ENTITY select.heading "Select Your Add-ons">
|
||||
<!-- LOCALIZATION NOTE (select.description): The term used for "third parties"
|
||||
here should match the string source.other in selectAddons.properties. -->
|
||||
<!ENTITY select.description "Make &brandShortName; even faster by disabling add-ons you no longer use. Add-ons already installed by third parties will be disabled automatically unless you select them below.">
|
||||
<!ENTITY select.keep "Keep">
|
||||
<!-- LOCALIZATION NOTE (select.keep.style): Should be a width wide enough for
|
||||
the string in select.keep above. -->
|
||||
<!ENTITY select.keep.style "width: 6ch;">
|
||||
<!ENTITY select.action "Action">
|
||||
<!-- LOCALIZATION NOTE (select.action.style): Should be a width wide enough for
|
||||
the action strings in selectAddons.properties or brandShortName. -->
|
||||
<!ENTITY select.action.style "width: 35ch;">
|
||||
<!ENTITY select.source "Installed By">
|
||||
<!ENTITY select.name "Name">
|
||||
<!-- LOCALIZATION NOTE (select.name.style): Should be a width small enough so
|
||||
the source column still has enough room for the source strings in
|
||||
selectAddons.properties. -->
|
||||
<!ENTITY select.name.style "width: 33ch;">
|
||||
|
||||
<!ENTITY confirm.heading "Select Your Add-ons">
|
||||
<!-- LOCALIZATION NOTE (confirm.description): The term used for "third parties"
|
||||
here should match the string source.other in selectAddons.properties. -->
|
||||
<!ENTITY confirm.description "Make &brandShortName; even faster by disabling add-ons you no longer use. Add-ons already installed by third parties will be disabled automatically unless you select them below.">
|
||||
|
||||
<!ENTITY action.disable.heading "The following add-ons will be disabled:">
|
||||
<!ENTITY action.incompatible.heading "The following add-ons are disabled, but will be enabled as soon as they are compatible:">
|
||||
<!ENTITY action.update.heading "The following add-ons will be updated:">
|
||||
<!ENTITY action.enable.heading "The following add-ons will be enabled:">
|
||||
|
||||
<!ENTITY update.heading "Updating Your Add-ons">
|
||||
<!ENTITY update.progress.label "Downloading and installing updates for your selected add-ons.">
|
||||
|
||||
<!ENTITY errors.heading "&brandShortName; could not update some of your add-ons.">
|
||||
<!ENTITY errors.description "Installing updates for some of your add-ons failed. &brandShortName; will automatically try to update them again later.">
|
||||
|
||||
<!ENTITY footer.label "You can always change your add-ons by going to the Add-ons Manager.">
|
||||
<!ENTITY cancel.label "Cancel">
|
||||
<!ENTITY back.label "Back">
|
||||
<!ENTITY next.label "Next">
|
||||
<!ENTITY done.label "Done">
|
|
@ -0,0 +1,13 @@
|
|||
#LOCALIZATION NOTE (source.profile) add-ons installed by the user, this may be
|
||||
# translated as "You" or "User" depending on the locale
|
||||
source.profile=You
|
||||
#LOCALIZATION NOTE (source.other) add-ons installed by other applications
|
||||
# installed on the computer
|
||||
source.other=Third Party
|
||||
|
||||
action.enabled=Will be enabled
|
||||
action.disabled=Will be disabled
|
||||
action.autoupdate=Will be updated to be compatible
|
||||
action.incompatible=Will be enabled when compatible
|
||||
action.neededupdate=Update to make compatible
|
||||
action.unneededupdate=Optional update
|
|
@ -83,6 +83,8 @@
|
|||
locale/@AB_CD@/mozapps/extensions/extensions.properties (%chrome/mozapps/extensions/extensions.properties)
|
||||
locale/@AB_CD@/mozapps/extensions/blocklist.dtd (%chrome/mozapps/extensions/blocklist.dtd)
|
||||
locale/@AB_CD@/mozapps/extensions/about.dtd (%chrome/mozapps/extensions/about.dtd)
|
||||
locale/@AB_CD@/mozapps/extensions/selectAddons.dtd (%chrome/mozapps/extensions/selectAddons.dtd)
|
||||
locale/@AB_CD@/mozapps/extensions/selectAddons.properties (%chrome/mozapps/extensions/selectAddons.properties)
|
||||
locale/@AB_CD@/mozapps/extensions/update.dtd (%chrome/mozapps/extensions/update.dtd)
|
||||
locale/@AB_CD@/mozapps/extensions/update.properties (%chrome/mozapps/extensions/update.properties)
|
||||
locale/@AB_CD@/mozapps/extensions/newaddon.dtd (%chrome/mozapps/extensions/newaddon.dtd)
|
||||
|
|
|
@ -517,17 +517,6 @@ var AddonManagerInternal = {
|
|||
scope.AddonRepository.repopulateCache(ids, notifyComplete);
|
||||
|
||||
pendingUpdates += aAddons.length;
|
||||
var autoUpdateDefault = AddonManager.autoUpdateDefault;
|
||||
|
||||
function shouldAutoUpdate(aAddon) {
|
||||
if (!("applyBackgroundUpdates" in aAddon))
|
||||
return false;
|
||||
if (aAddon.applyBackgroundUpdates == AddonManager.AUTOUPDATE_ENABLE)
|
||||
return true;
|
||||
if (aAddon.applyBackgroundUpdates == AddonManager.AUTOUPDATE_DISABLE)
|
||||
return false;
|
||||
return autoUpdateDefault;
|
||||
}
|
||||
|
||||
aAddons.forEach(function BUC_forEachCallback(aAddon) {
|
||||
// Check all add-ons for updates so that any compatibility updates will
|
||||
|
@ -537,7 +526,7 @@ var AddonManagerInternal = {
|
|||
// Start installing updates when the add-on can be updated and
|
||||
// background updates should be applied.
|
||||
if (aAddon.permissions & AddonManager.PERM_CAN_UPGRADE &&
|
||||
shouldAutoUpdate(aAddon)) {
|
||||
AddonManager.shouldAutoUpdate(aAddon)) {
|
||||
aInstall.install();
|
||||
}
|
||||
},
|
||||
|
@ -1085,10 +1074,7 @@ var AddonManagerInternal = {
|
|||
},
|
||||
|
||||
get autoUpdateDefault() {
|
||||
try {
|
||||
return Services.prefs.getBoolPref(PREF_EM_AUTOUPDATE_DEFAULT);
|
||||
} catch(e) { }
|
||||
return true;
|
||||
return Services.prefs.getBoolPref(PREF_EM_AUTOUPDATE_DEFAULT);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1399,6 +1385,16 @@ var AddonManager = {
|
|||
|
||||
get autoUpdateDefault() {
|
||||
return AddonManagerInternal.autoUpdateDefault;
|
||||
},
|
||||
|
||||
shouldAutoUpdate: function AM_shouldAutoUpdate(aAddon) {
|
||||
if (!("applyBackgroundUpdates" in aAddon))
|
||||
return false;
|
||||
if (aAddon.applyBackgroundUpdates == AddonManager.AUTOUPDATE_ENABLE)
|
||||
return true;
|
||||
if (aAddon.applyBackgroundUpdates == AddonManager.AUTOUPDATE_DISABLE)
|
||||
return false;
|
||||
return this.autoUpdateDefault;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -78,7 +78,9 @@ const PREF_XPI_UNPACK = "extensions.alwaysUnpack";
|
|||
const PREF_INSTALL_REQUIREBUILTINCERTS = "extensions.install.requireBuiltInCerts";
|
||||
const PREF_INSTALL_DISTRO_ADDONS = "extensions.installDistroAddons";
|
||||
const PREF_BRANCH_INSTALLED_ADDON = "extensions.installedDistroAddon.";
|
||||
const PREF_SHOWN_SELECTION_UI = "extensions.shownSelectionUI";
|
||||
|
||||
const URI_EXTENSION_SELECT_DIALOG = "chrome://mozapps/content/extensions/selectAddons.xul";
|
||||
const URI_EXTENSION_UPDATE_DIALOG = "chrome://mozapps/content/extensions/update.xul";
|
||||
const URI_EXTENSION_STRINGS = "chrome://mozapps/locale/extensions/extensions.properties";
|
||||
|
||||
|
@ -1584,9 +1586,13 @@ var XPIProvider = {
|
|||
// information but only if the mismatch UI isn't disabled
|
||||
if (aAppChanged && !this.allAppGlobal &&
|
||||
Prefs.getBoolPref(PREF_EM_SHOW_MISMATCH_UI, true)) {
|
||||
this.showMismatchWindow();
|
||||
this.showUpgradeUI();
|
||||
flushCaches = true;
|
||||
}
|
||||
else if (aAppChanged === undefined) {
|
||||
// For new profiles we will never need to show the add-on selection UI
|
||||
Services.prefs.setBoolPref(PREF_SHOWN_SELECTION_UI, true);
|
||||
}
|
||||
|
||||
if (flushCaches) {
|
||||
flushStartupCache();
|
||||
|
@ -1701,16 +1707,24 @@ var XPIProvider = {
|
|||
/**
|
||||
* Shows the "Compatibility Updates" UI
|
||||
*/
|
||||
showMismatchWindow: function XPI_showMismatchWindow() {
|
||||
var variant = Cc["@mozilla.org/variant;1"].
|
||||
createInstance(Ci.nsIWritableVariant);
|
||||
variant.setFromVariant(this.inactiveAddonIDs);
|
||||
|
||||
// This *must* be modal as it has to block startup.
|
||||
var features = "chrome,centerscreen,dialog,titlebar,modal";
|
||||
var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
|
||||
getService(Ci.nsIWindowWatcher);
|
||||
ww.openWindow(null, URI_EXTENSION_UPDATE_DIALOG, "", features, variant);
|
||||
showUpgradeUI: function XPI_showUpgradeUI() {
|
||||
if (!Prefs.getBoolPref(PREF_SHOWN_SELECTION_UI, false)) {
|
||||
// This *must* be modal as it has to block startup.
|
||||
var features = "chrome,centerscreen,dialog,titlebar,modal";
|
||||
Services.ww.openWindow(null, URI_EXTENSION_SELECT_DIALOG, "", features, null);
|
||||
Services.prefs.setBoolPref(PREF_SHOWN_SELECTION_UI, true);
|
||||
}
|
||||
else {
|
||||
var variant = Cc["@mozilla.org/variant;1"].
|
||||
createInstance(Ci.nsIWritableVariant);
|
||||
variant.setFromVariant(this.inactiveAddonIDs);
|
||||
|
||||
// This *must* be modal as it has to block startup.
|
||||
var features = "chrome,centerscreen,dialog,titlebar,modal";
|
||||
var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"].
|
||||
getService(Ci.nsIWindowWatcher);
|
||||
ww.openWindow(null, URI_EXTENSION_UPDATE_DIALOG, "", features, variant);
|
||||
}
|
||||
|
||||
// Ensure any changes to the add-ons list are flushed to disk
|
||||
XPIDatabase.writeAddonsList([]);
|
||||
|
|
|
@ -815,7 +815,6 @@ var gViewController = {
|
|||
var numUpdated = 0;
|
||||
var numManualUpdates = 0;
|
||||
var restartNeeded = false;
|
||||
var autoUpdateDefault = AddonManager.autoUpdateDefault;
|
||||
var self = this;
|
||||
|
||||
function updateStatus() {
|
||||
|
@ -867,7 +866,7 @@ var gViewController = {
|
|||
onUpdateAvailable: function(aAddon, aInstall) {
|
||||
gEventManager.delegateAddonEvent("onUpdateAvailable",
|
||||
[aAddon, aInstall]);
|
||||
if (shouldAutoUpdate(aAddon, autoUpdateDefault)) {
|
||||
if (AddonManager.shouldAutoUpdate(aAddon)) {
|
||||
aInstall.addListener(updateInstallListener);
|
||||
aInstall.install();
|
||||
} else {
|
||||
|
@ -912,7 +911,7 @@ var gViewController = {
|
|||
onUpdateAvailable: function(aAddon, aInstall) {
|
||||
gEventManager.delegateAddonEvent("onUpdateAvailable",
|
||||
[aAddon, aInstall]);
|
||||
if (shouldAutoUpdate(aAddon))
|
||||
if (AddonManager.shouldAutoUpdate(aAddon))
|
||||
aInstall.install();
|
||||
},
|
||||
onNoUpdateAvailable: function(aAddon) {
|
||||
|
@ -1246,17 +1245,6 @@ function isInState(aInstall, aState) {
|
|||
return aInstall.state == state;
|
||||
}
|
||||
|
||||
|
||||
function shouldAutoUpdate(aAddon, aDefault) {
|
||||
if (!("applyBackgroundUpdates" in aAddon))
|
||||
return false;
|
||||
if (aAddon.applyBackgroundUpdates == AddonManager.AUTOUPDATE_ENABLE)
|
||||
return true;
|
||||
if (aAddon.applyBackgroundUpdates == AddonManager.AUTOUPDATE_DISABLE)
|
||||
return false;
|
||||
return aDefault !== undefined ? aDefault : AddonManager.autoUpdateDefault;
|
||||
}
|
||||
|
||||
function shouldShowVersionNumber(aAddon) {
|
||||
if (!aAddon.version)
|
||||
return false;
|
||||
|
@ -2675,7 +2663,7 @@ var gDetailView = {
|
|||
if ("applyBackgroundUpdates" in aAddon) {
|
||||
this._autoUpdate.hidden = false;
|
||||
this._autoUpdate.value = aAddon.applyBackgroundUpdates;
|
||||
let hideFindUpdates = shouldAutoUpdate(this._addon);
|
||||
let hideFindUpdates = AddonManager.shouldAutoUpdate(this._addon);
|
||||
document.getElementById("detail-findUpdates-btn").hidden = hideFindUpdates;
|
||||
} else {
|
||||
this._autoUpdate.hidden = true;
|
||||
|
@ -2940,7 +2928,7 @@ var gDetailView = {
|
|||
onPropertyChanged: function(aProperties) {
|
||||
if (aProperties.indexOf("applyBackgroundUpdates") != -1) {
|
||||
this._autoUpdate.value = this._addon.applyBackgroundUpdates;
|
||||
let hideFindUpdates = shouldAutoUpdate(this._addon);
|
||||
let hideFindUpdates = AddonManager.shouldAutoUpdate(this._addon);
|
||||
document.getElementById("detail-findUpdates-btn").hidden = hideFindUpdates;
|
||||
}
|
||||
},
|
||||
|
@ -2969,7 +2957,6 @@ var gUpdatesView = {
|
|||
_emptyNotice: null,
|
||||
_sorters: null,
|
||||
_updateSelected: null,
|
||||
_updatePrefs: null,
|
||||
_categoryItem: null,
|
||||
|
||||
initialize: function() {
|
||||
|
@ -2986,9 +2973,6 @@ var gUpdatesView = {
|
|||
gUpdatesView.installSelected();
|
||||
}, false);
|
||||
|
||||
this._updatePrefs = Services.prefs.getBranch("extensions.update.");
|
||||
this._updatePrefs.QueryInterface(Ci.nsIPrefBranch2);
|
||||
this._updatePrefs.addObserver("", this, false);
|
||||
this.updateAvailableCount(true);
|
||||
|
||||
AddonManager.addAddonListener(this);
|
||||
|
@ -2998,8 +2982,6 @@ var gUpdatesView = {
|
|||
shutdown: function() {
|
||||
AddonManager.removeAddonListener(this);
|
||||
AddonManager.removeInstallListener(this);
|
||||
this._updatePrefs.removeObserver("", this);
|
||||
delete this._updatePrefs;
|
||||
},
|
||||
|
||||
show: function(aType, aRequest) {
|
||||
|
@ -3106,17 +3088,12 @@ var gUpdatesView = {
|
|||
|
||||
isManualUpdate: function(aInstall, aOnlyAvailable) {
|
||||
var isManual = aInstall.existingAddon &&
|
||||
!shouldAutoUpdate(aInstall.existingAddon);
|
||||
!AddonManager.shouldAutoUpdate(aInstall.existingAddon);
|
||||
if (isManual && aOnlyAvailable)
|
||||
return isInState(aInstall, "available");
|
||||
return isManual;
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic != "nsPref:changed")
|
||||
return;
|
||||
},
|
||||
|
||||
maybeRefresh: function() {
|
||||
if (gViewController.currentViewId == "addons://updates/available")
|
||||
this._showAvailableUpdates(true);
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/* ***** 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 Manager UI.
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
#select .addon {
|
||||
-moz-binding: url("chrome://mozapps/content/extensions/selectAddons.xml#addon-select");
|
||||
}
|
||||
|
||||
#confirm .addon {
|
||||
-moz-binding: url("chrome://mozapps/content/extensions/selectAddons.xml#addon-confirm");
|
||||
}
|
||||
|
||||
#select-scrollbox,
|
||||
#confirm-scrollbox {
|
||||
overflow-y: auto;
|
||||
-moz-box-orient: vertical;
|
||||
}
|
||||
|
||||
.addon:not([optionalupdate]) .addon-action-update,
|
||||
.addon[optionalupdate] .addon-action-message {
|
||||
display: none;
|
||||
}
|
|
@ -0,0 +1,368 @@
|
|||
# ***** 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");
|
||||
|
||||
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 orderForScope(aScope) {
|
||||
switch (aScope) {
|
||||
case AddonManager.SCOPE_PROFILE:
|
||||
return 2;
|
||||
case AddonManager.SCOPE_APPLICATION:
|
||||
return 1;
|
||||
default:
|
||||
return 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";
|
||||
|
||||
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);
|
||||
|
||||
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);
|
|
@ -0,0 +1,269 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
# ***** 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 Manager.
|
||||
#
|
||||
# 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 *****
|
||||
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % updateDTD SYSTEM "chrome://mozapps/locale/extensions/selectAddons.dtd">
|
||||
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
|
||||
%updateDTD;
|
||||
%brandDTD;
|
||||
]>
|
||||
|
||||
<bindings xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl">
|
||||
|
||||
<binding id="addon-select">
|
||||
<content>
|
||||
<xul:hbox class="select-keep select-cell">
|
||||
<xul:checkbox class="addon-keep-checkbox" anonid="keep"
|
||||
oncommand="document.getBindingParent(this).keepChanged();"/>
|
||||
</xul:hbox>
|
||||
<xul:hbox class="select-icon select-cell">
|
||||
<xul:image class="addon-icon" xbl:inherits="type"/>
|
||||
</xul:hbox>
|
||||
<xul:hbox class="select-name select-cell">
|
||||
<xul:label class="addon-name" crop="end" style="&select.name.style;"
|
||||
xbl:inherits="xbl:text=name"/>
|
||||
</xul:hbox>
|
||||
<xul:hbox class="select-action select-cell">
|
||||
<xul:label class="addon-action-message" style="&select.action.style;"
|
||||
xbl:inherits="xbl:text=action"/>
|
||||
<xul:checkbox anonid="update" checked="true" class="addon-action-update"
|
||||
oncommand="document.getBindingParent(this).updateChanged();"
|
||||
style="&select.action.style;" xbl:inherits="label=action"/>
|
||||
</xul:hbox>
|
||||
<xul:hbox class="select-source select-cell">
|
||||
<xul:label class="addon-source" xbl:inherits="xbl:text=source"/>
|
||||
</xul:hbox>
|
||||
</content>
|
||||
|
||||
<implementation>
|
||||
<field name="_addon"/>
|
||||
<field name="_disabled"/>
|
||||
<field name="_install"/>
|
||||
<field name="_wasActive"/>
|
||||
<field name="_keep">document.getAnonymousElementByAttribute(this, "anonid", "keep");</field>
|
||||
<field name="_update">document.getAnonymousElementByAttribute(this, "anonid", "update");</field>
|
||||
<field name="_appStrings">document.getElementById("app-strings");</field>
|
||||
<field name="_strings">document.getElementById("strings");</field>
|
||||
|
||||
<property name="action" readonly="true">
|
||||
<getter><![CDATA[
|
||||
if (!this._keep.checked) {
|
||||
if (this._wasActive)
|
||||
return "disable";
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
if (this._addon.appDisabled && !this._install)
|
||||
return "incompatible";
|
||||
|
||||
if (this._install && (AddonManager.shouldAutoUpdate(this._addon) || this._update.checked))
|
||||
return "update";
|
||||
|
||||
if (this._addon.permissions & AddonManager.PERM_CAN_ENABLE)
|
||||
return "enable";
|
||||
|
||||
return null;
|
||||
]]></getter>
|
||||
</property>
|
||||
|
||||
<method name="setAddon">
|
||||
<parameter name="aAddon"/>
|
||||
<parameter name="aInstall"/>
|
||||
<parameter name="aWasActive"/>
|
||||
<body><![CDATA[
|
||||
this._addon = aAddon;
|
||||
this._install = aInstall;
|
||||
this._wasActive = aWasActive;
|
||||
|
||||
this.setAttribute("name", aAddon.name);
|
||||
this.setAttribute("type", aAddon.type);
|
||||
|
||||
// User and application installed add-ons default to staying enabled,
|
||||
// others default to disabled.
|
||||
switch (aAddon.scope) {
|
||||
case AddonManager.SCOPE_PROFILE:
|
||||
this._keep.checked = !aAddon.userDisabled;
|
||||
this.setAttribute("source", this._strings.getString("source.profile"));
|
||||
break;
|
||||
case AddonManager.SCOPE_APPLICATION:
|
||||
this._keep.checked = !aAddon.userDisabled;
|
||||
this.setAttribute("source", this._appStrings.getString("brandShortName"));
|
||||
break;
|
||||
default:
|
||||
this._keep.checked = false;
|
||||
this.setAttribute("source", this._strings.getString("source.other"));
|
||||
}
|
||||
|
||||
this.updateAction();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="setActionMessage">
|
||||
<body><![CDATA[
|
||||
if (!this._keep.checked) {
|
||||
// If the user no longer wants this add-on then it is either being
|
||||
// disabled or nothing is changing. Don't complicate matters by
|
||||
// talking about updates for this case
|
||||
|
||||
if (this._wasActive)
|
||||
this.setAttribute("action", this._strings.getString("action.disabled"));
|
||||
else
|
||||
this.setAttribute("action", "");
|
||||
|
||||
this.removeAttribute("optionalupdate");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._addon.appDisabled && !this._install) {
|
||||
// If the add-on is incompatible and there is no update available
|
||||
// then it will remain disabled
|
||||
|
||||
this.setAttribute("action", this._strings.getString("action.incompatible"));
|
||||
|
||||
this.removeAttribute("optionalupdate");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._install) {
|
||||
if (!AddonManager.shouldAutoUpdate(this._addon)) {
|
||||
this.setAttribute("optionalupdate", "true");
|
||||
|
||||
// If manual updating for the add-on then display the right
|
||||
// text depending on whether the update is required to make
|
||||
// the add-on work or not
|
||||
if (this._addon.appDisabled)
|
||||
this.setAttribute("action", this._strings.getString("action.neededupdate"));
|
||||
else
|
||||
this.setAttribute("action", this._strings.getString("action.unneededupdate"));
|
||||
return;
|
||||
}
|
||||
|
||||
this.removeAttribute("optionalupdate");
|
||||
|
||||
// If the update is needed to make the add-on compatible then
|
||||
// say so otherwise just say nothing about it
|
||||
if (this._addon.appDisabled) {
|
||||
this.setAttribute("action", this._strings.getString("action.autoupdate"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.removeAttribute("optionalupdate");
|
||||
}
|
||||
|
||||
// If the add-on didn't used to be active and it now is (via a
|
||||
// compatibility update) or it can be enabled then the action is to
|
||||
// enable the add-on
|
||||
if (!this._wasActive && (this._addon.isActive || this._addon.permissions & AddonManager.PERM_CAN_ENABLE)) {
|
||||
this.setAttribute("action", this._strings.getString("action.enabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
// In all other cases the add-on is simply remaining enabled
|
||||
this.setAttribute("action", "");
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="updateAction">
|
||||
<body><![CDATA[
|
||||
this.setActionMessage();
|
||||
let installingUpdate = this._install &&
|
||||
(AddonManager.shouldAutoUpdate(this._addon) ||
|
||||
this._update.checked);
|
||||
|
||||
if (this._keep.checked && (!this._addon.appDisabled || installingUpdate))
|
||||
this.setAttribute("active", "true");
|
||||
else
|
||||
this.removeAttribute("active");
|
||||
|
||||
gSelect.updateButtons();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="updateChanged">
|
||||
<body><![CDATA[
|
||||
this.updateAction();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="keepChanged">
|
||||
<body><![CDATA[
|
||||
this.updateAction();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="keep">
|
||||
<body><![CDATA[
|
||||
this._keep.checked = true;
|
||||
this.keepChanged();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="disable">
|
||||
<body><![CDATA[
|
||||
this._keep.checked = false;
|
||||
this.keepChanged();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="apply">
|
||||
<body><![CDATA[
|
||||
this._addon.userDisabled = !this._keep.checked;
|
||||
|
||||
if (!this._install || !this._keep.checked)
|
||||
return;
|
||||
|
||||
if (AddonManager.shouldAutoUpdate(this._addon) || this._update.checked)
|
||||
this._install.install();
|
||||
]]></body>
|
||||
</method>
|
||||
</implementation>
|
||||
</binding>
|
||||
|
||||
<binding id="addon-confirm">
|
||||
<content>
|
||||
<xul:image class="addon-icon" xbl:inherits="type"/>
|
||||
<xul:label class="addon-name" xbl:inherits="xbl:text=name"/>
|
||||
</content>
|
||||
</binding>
|
||||
</bindings>
|
|
@ -0,0 +1,159 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
# ***** 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 *****
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mozapps/content/extensions/selectAddons.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mozapps/skin/extensions/selectAddons.css" type="text/css"?>
|
||||
|
||||
<!DOCTYPE window [
|
||||
<!ENTITY % updateDTD SYSTEM "chrome://mozapps/locale/extensions/selectAddons.dtd">
|
||||
<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd">
|
||||
%updateDTD;
|
||||
%brandDTD;
|
||||
]>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
style="&upgrade.style;" id="select-window">
|
||||
|
||||
<script type="application/javascript" src="chrome://mozapps/content/extensions/selectAddons.js"/>
|
||||
<stringbundle id="app-strings" src="chrome://branding/locale/brand.properties"/>
|
||||
<stringbundle id="strings" src="chrome://mozapps/locale/extensions/selectAddons.properties"/>
|
||||
|
||||
<deck id="view-deck" flex="1" align="stretch" pack="stretch">
|
||||
<vbox id="checking" align="stretch">
|
||||
<vbox flex="1">
|
||||
<label id="checking-heading" class="heading">&checking.heading;</label>
|
||||
</vbox>
|
||||
<progressmeter id="checking-progress" class="progress" mode="undetermined"/>
|
||||
<vbox flex="1">
|
||||
<label id="checking-progress-label" class="progress-label">&checking.progress.label;</label>
|
||||
</vbox>
|
||||
</vbox>
|
||||
|
||||
<vbox id="select" align="stretch">
|
||||
<label id="select-heading" class="heading">&select.heading;</label>
|
||||
|
||||
<description id="select-description">&select.description;</description>
|
||||
|
||||
<vbox id="select-list" align="stretch" flex="1">
|
||||
<hbox id="select-header">
|
||||
<hbox class="select-keep select-cell" style="&select.keep.style;">
|
||||
<label value="&select.keep;"/>
|
||||
</hbox>
|
||||
<hbox class="select-icon select-cell"/>
|
||||
<hbox id="heading-name" class="select-name select-cell" style="&select.name.style;">
|
||||
<label value="&select.name;"/>
|
||||
</hbox>
|
||||
<hbox id="heading-action" class="select-action select-cell" style="&select.action.style;">
|
||||
<label value="&select.action;"/>
|
||||
</hbox>
|
||||
<hbox class="select-source select-cell" flex="1">
|
||||
<label value="&select.source;"/>
|
||||
</hbox>
|
||||
</hbox>
|
||||
|
||||
<scrollbox id="select-scrollbox" flex="1">
|
||||
<grid id="select-grid" flex="1">
|
||||
<columns>
|
||||
<column style="&select.keep.style;"/>
|
||||
<column/>
|
||||
<column id="column-name"/>
|
||||
<column id="column-action" class="select-action"/>
|
||||
<column class="select-source" flex="1"/>
|
||||
</columns>
|
||||
|
||||
<rows id="select-rows"/>
|
||||
</grid>
|
||||
</scrollbox>
|
||||
</vbox>
|
||||
</vbox>
|
||||
|
||||
<vbox id="confirm" align="stretch">
|
||||
<label id="confirm-heading" class="heading">&confirm.heading;</label>
|
||||
|
||||
<description id="confirm-description">&confirm.description;</description>
|
||||
|
||||
<scrollbox id="confirm-scrollbox" flex="1">
|
||||
<vbox id="disable-list" class="action-list" hidden="true">
|
||||
<label class="action-header">&action.disable.heading;</label>
|
||||
</vbox>
|
||||
|
||||
<vbox id="incompatible-list" class="action-list" hidden="true">
|
||||
<label class="action-header">&action.incompatible.heading;</label>
|
||||
</vbox>
|
||||
|
||||
<vbox id="update-list" class="action-list" hidden="true">
|
||||
<label class="action-header">&action.update.heading;</label>
|
||||
</vbox>
|
||||
|
||||
<vbox id="enable-list" class="action-list" hidden="true">
|
||||
<label class="action-header">&action.enable.heading;</label>
|
||||
</vbox>
|
||||
</scrollbox>
|
||||
</vbox>
|
||||
|
||||
<vbox id="update" align="stretch">
|
||||
<vbox flex="1">
|
||||
<label id="update-heading" class="heading">&update.heading;</label>
|
||||
</vbox>
|
||||
<progressmeter id="update-progress" class="progress" mode="undetermined"/>
|
||||
<vbox flex="1">
|
||||
<label id="update-progress-label" class="progress-label">&update.progress.label;</label>
|
||||
</vbox>
|
||||
</vbox>
|
||||
|
||||
<vbox id="errors">
|
||||
<vbox flex="1">
|
||||
<label id="errors-heading" class="heading">&errors.heading;</label>
|
||||
</vbox>
|
||||
<description id="errors-description" value="&errors.description;"/>
|
||||
<spacer flex="1"/>
|
||||
</vbox>
|
||||
</deck>
|
||||
|
||||
<hbox id="footer" align="center">
|
||||
<label id="footer-label">&footer.label;</label>
|
||||
<spacer flex="1"/>
|
||||
<button id="cancel" label="&cancel.label;" oncommand="window.close()"/>
|
||||
<button id="back" label="&back.label;" oncommand="gView.back()" hidden="true"/>
|
||||
<button id="next" label="&next.label;" oncommand="gView.next()" hidden="true"/>
|
||||
<button id="done" label="&done.label;" oncommand="gView.done()" hidden="true"/>
|
||||
</hbox>
|
||||
|
||||
</window>
|
|
@ -14,6 +14,10 @@ toolkit.jar:
|
|||
* content/mozapps/extensions/blocklist.js (content/blocklist.js)
|
||||
* content/mozapps/extensions/blocklist.css (content/blocklist.css)
|
||||
* content/mozapps/extensions/blocklist.xml (content/blocklist.xml)
|
||||
* content/mozapps/extensions/selectAddons.xul (content/selectAddons.xul)
|
||||
* content/mozapps/extensions/selectAddons.xml (content/selectAddons.xml)
|
||||
* content/mozapps/extensions/selectAddons.js (content/selectAddons.js)
|
||||
* content/mozapps/extensions/selectAddons.css (content/selectAddons.css)
|
||||
* content/mozapps/extensions/update.xul (content/update.xul)
|
||||
* content/mozapps/extensions/update.js (content/update.js)
|
||||
* content/mozapps/extensions/eula.xul (content/eula.xul)
|
||||
|
|
|
@ -99,6 +99,9 @@ _TEST_FILES = \
|
|||
browser_updatessl.js \
|
||||
browser_installssl.js \
|
||||
browser_newaddon.js \
|
||||
browser_select_selection.js \
|
||||
browser_select_confirm.js \
|
||||
browser_select_update.js \
|
||||
$(NULL)
|
||||
|
||||
_TEST_RESOURCES = \
|
||||
|
|
|
@ -0,0 +1,170 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// Tests the confirmation part of the post-app-update dialog
|
||||
|
||||
var gProvider;
|
||||
var gWin;
|
||||
|
||||
function waitForView(aView, aCallback) {
|
||||
var view = gWin.document.getElementById(aView);
|
||||
view.addEventListener("ViewChanged", function() {
|
||||
view.removeEventListener("ViewChanged", arguments.callee, false);
|
||||
try {
|
||||
aCallback();
|
||||
}
|
||||
catch (e) {
|
||||
ok(false, e);
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates 4 test add-ons. Two are disabled and two enabled.
|
||||
*
|
||||
* @param aAppDisabled
|
||||
* The appDisabled property for the test add-ons
|
||||
* @param aUpdateAvailable
|
||||
* True if the test add-ons should claim to have an update available
|
||||
*/
|
||||
function setupUI(aAppDisabled, aUpdateAvailable, aCallback) {
|
||||
if (gProvider)
|
||||
gProvider.unregister();
|
||||
|
||||
gProvider = new MockProvider();
|
||||
|
||||
for (var i = 1; i < 5; i++) {
|
||||
var addon = new MockAddon("test" + i + "@tests.mozilla.org",
|
||||
"Test Add-on " + i, "extension");
|
||||
addon.version = "1.0";
|
||||
addon.userDisabled = (i > 2);
|
||||
addon.appDisabled = aAppDisabled;
|
||||
addon.isActive = !addon.userDisabled && !addon.appDisabled;
|
||||
|
||||
addon.findUpdates = function(aListener, aReason, aAppVersion, aPlatformVersion) {
|
||||
if (aUpdateAvailable) {
|
||||
var newAddon = new MockAddon(this.id, this.name, "extension");
|
||||
newAddon.version = "2.0";
|
||||
var install = new MockInstall(this.name, this.type, newAddon);
|
||||
install.existingAddon = this;
|
||||
aListener.onUpdateAvailable(this, install);
|
||||
}
|
||||
|
||||
aListener.onUpdateFinished(this, AddonManager.UPDATE_STATUS_NO_ERROR);
|
||||
};
|
||||
|
||||
gProvider.addAddon(addon);
|
||||
}
|
||||
|
||||
gWin = Services.ww.openWindow(null,
|
||||
"chrome://mozapps/content/extensions/selectAddons.xul",
|
||||
"",
|
||||
"chrome,centerscreen,dialog,titlebar",
|
||||
null);
|
||||
waitForFocus(function() {
|
||||
waitForView("select", function() {
|
||||
var row = gWin.document.getElementById("select-rows").firstChild.nextSibling;
|
||||
while (row) {
|
||||
if (row.id == "test2@tests.mozilla.org" ||
|
||||
row.id == "test4@tests.mozilla.org") {
|
||||
row.disable();
|
||||
}
|
||||
else {
|
||||
row.keep();
|
||||
}
|
||||
row = row.nextSibling;
|
||||
}
|
||||
|
||||
waitForView("confirm", aCallback);
|
||||
EventUtils.synthesizeMouseAtCenter(gWin.document.getElementById("next"), {}, gWin);
|
||||
});
|
||||
}, gWin);
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function end_test() {
|
||||
finish();
|
||||
}
|
||||
|
||||
// Test for disabling
|
||||
add_test(function disabling_test() {
|
||||
setupUI(false, false, function() {
|
||||
ok(gWin.document.getElementById("incompatible-list").hidden, "Incompatible list should be hidden");
|
||||
ok(gWin.document.getElementById("update-list").hidden, "Update list should be hidden");
|
||||
|
||||
var list = gWin.document.getElementById("disable-list");
|
||||
ok(!list.hidden, "Disable list should be visible");
|
||||
is(list.childNodes.length, 2, "Should be one add-on getting disabled (plus the header)");
|
||||
is(list.childNodes[1].id, "test2@tests.mozilla.org", "Should be the right add-on ID");
|
||||
is(list.childNodes[1].getAttribute("name"), "Test Add-on 2", "Should be the right add-on name");
|
||||
|
||||
var list = gWin.document.getElementById("enable-list");
|
||||
ok(!list.hidden, "Enable list should be visible");
|
||||
is(list.childNodes.length, 2, "Should be one add-on getting disabled (plus the header)");
|
||||
is(list.childNodes[1].id, "test3@tests.mozilla.org", "Should be the right add-on ID");
|
||||
is(list.childNodes[1].getAttribute("name"), "Test Add-on 3", "Should be the right add-on name");
|
||||
|
||||
ok(gWin.document.getElementById("next").hidden, "Next button should be hidden");
|
||||
ok(!gWin.document.getElementById("done").hidden, "Done button should be visible");
|
||||
gWin.close();
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
|
||||
// Test for incompatible
|
||||
add_test(function incompatible_test() {
|
||||
setupUI(true, false, function() {
|
||||
ok(gWin.document.getElementById("update-list").hidden, "Update list should be hidden");
|
||||
ok(gWin.document.getElementById("disable-list").hidden, "Disable list should be hidden");
|
||||
ok(gWin.document.getElementById("enable-list").hidden, "Enable list should be hidden");
|
||||
|
||||
var list = gWin.document.getElementById("incompatible-list");
|
||||
ok(!list.hidden, "Incompatible list should be visible");
|
||||
is(list.childNodes.length, 3, "Should be two add-ons waiting to be compatible (plus the header)");
|
||||
is(list.childNodes[1].id, "test1@tests.mozilla.org", "Should be the right add-on ID");
|
||||
is(list.childNodes[1].getAttribute("name"), "Test Add-on 1", "Should be the right add-on name");
|
||||
is(list.childNodes[2].id, "test3@tests.mozilla.org", "Should be the right add-on ID");
|
||||
is(list.childNodes[2].getAttribute("name"), "Test Add-on 3", "Should be the right add-on name");
|
||||
|
||||
ok(gWin.document.getElementById("next").hidden, "Next button should be hidden");
|
||||
ok(!gWin.document.getElementById("done").hidden, "Done button should be visible");
|
||||
gWin.close();
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
});
|
||||
|
||||
// Test for updates
|
||||
add_test(function update_test() {
|
||||
setupUI(false, true, function() {
|
||||
ok(gWin.document.getElementById("incompatible-list").hidden, "Incompatible list should be hidden");
|
||||
ok(gWin.document.getElementById("enable-list").hidden, "Enable list should be hidden");
|
||||
|
||||
var list = gWin.document.getElementById("update-list");
|
||||
ok(!list.hidden, "Update list should be visible");
|
||||
is(list.childNodes.length, 3, "Should be two add-ons waiting to be updated (plus the header)");
|
||||
is(list.childNodes[1].id, "test1@tests.mozilla.org", "Should be the right add-on ID");
|
||||
is(list.childNodes[1].getAttribute("name"), "Test Add-on 1", "Should be the right add-on name");
|
||||
is(list.childNodes[2].id, "test3@tests.mozilla.org", "Should be the right add-on ID");
|
||||
is(list.childNodes[2].getAttribute("name"), "Test Add-on 3", "Should be the right add-on name");
|
||||
|
||||
list = gWin.document.getElementById("disable-list");
|
||||
ok(!list.hidden, "Disable list should be visible");
|
||||
is(list.childNodes.length, 2, "Should be one add-on getting disabled (plus the header)");
|
||||
is(list.childNodes[1].id, "test2@tests.mozilla.org", "Should be the right add-on ID");
|
||||
is(list.childNodes[1].getAttribute("name"), "Test Add-on 2", "Should be the right add-on name");
|
||||
|
||||
ok(!gWin.document.getElementById("next").hidden, "Next button should be visible");
|
||||
ok(gWin.document.getElementById("done").hidden, "Done button should be hidden");
|
||||
gWin.close();
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
});
|
|
@ -0,0 +1,233 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// Tests the selection part of the post-app-update dialog
|
||||
|
||||
var gProvider;
|
||||
var gWin;
|
||||
|
||||
const PROFILE = AddonManager.SCOPE_PROFILE;
|
||||
const USER = AddonManager.SCOPE_USER;
|
||||
const APP = AddonManager.SCOPE_APPLICATION;
|
||||
const SYSTEM = AddonManager.SCOPE_SYSTEM;
|
||||
|
||||
// The matrix of testcases for the selection part of the UI
|
||||
// Note that the isActive flag has the value it had when the previous version
|
||||
// of the application ran with this add-on.
|
||||
var ADDONS = [
|
||||
//userDisabled wasAppDisabled isAppDisabled isActive hasUpdate autoUpdate scope defaultKeep position keepString disableString
|
||||
[false, true, false, false, false, true, PROFILE, true, 72, "enabled", ""], // 0
|
||||
[false, true, false, false, true, true, PROFILE, true, 73, "enabled", ""], // 1
|
||||
[false, true, false, false, true, false, PROFILE, true, 82, "unneededupdate", ""], // 2
|
||||
[false, false, false, true, false, true, PROFILE, true, 83, "", "disabled"], // 3
|
||||
[false, false, false, true, true, true, PROFILE, true, 84, "", "disabled"], // 4
|
||||
[false, false, false, true, true, false, PROFILE, true, 85, "unneededupdate", "disabled"], // 5
|
||||
[false, true, true, false, false, true, PROFILE, true, 86, "incompatible", ""], // 6
|
||||
[false, true, true, false, true, true, PROFILE, true, 87, "autoupdate", ""], // 7
|
||||
[false, true, true, false, true, false, PROFILE, true, 88, "neededupdate", ""], // 8
|
||||
[false, false, true, true, false, true, PROFILE, true, 89, "incompatible", "disabled"], // 9
|
||||
[false, true, true, true, true, true, PROFILE, true, 74, "autoupdate", "disabled"], // 10
|
||||
[false, true, true, true, true, false, PROFILE, true, 75, "neededupdate", "disabled"], // 11
|
||||
[true, false, false, false, false, true, PROFILE, false, 76, "enabled", ""], // 12
|
||||
[true, false, false, false, true, true, PROFILE, false, 77, "enabled", ""], // 13
|
||||
[true, false, false, false, true, false, PROFILE, false, 78, "unneededupdate", ""], // 14
|
||||
|
||||
// userDisabled and isActive cannot be true on startup
|
||||
|
||||
[true, true, true, false, false, true, PROFILE, false, 79, "incompatible", ""], // 15
|
||||
[true, true, true, false, true, true, PROFILE, false, 80, "autoupdate", ""], // 16
|
||||
[true, true, true, false, true, false, PROFILE, false, 81, "neededupdate", ""], // 17
|
||||
|
||||
// userDisabled and isActive cannot be true on startup
|
||||
|
||||
// Being in a different scope should make little difference except no updates are possible so don't exhaustively test each
|
||||
[false, false, false, true, true, false, USER, false, 0, "", "disabled"], // 18
|
||||
[true, true, false, false, true, false, USER, false, 1, "enabled", ""], // 19
|
||||
[false, true, true, true, true, false, USER, false, 2, "incompatible", "disabled"], // 20
|
||||
[true, true, true, false, true, false, USER, false, 3, "incompatible", ""], // 21
|
||||
[false, false, false, true, true, false, SYSTEM, false, 4, "", "disabled"], // 22
|
||||
[true, true, false, false, true, false, SYSTEM, false, 5, "enabled", ""], // 23
|
||||
[false, true, true, true, true, false, SYSTEM, false, 6, "incompatible", "disabled"], // 24
|
||||
[true, true, true, false, true, false, SYSTEM, false, 7, "incompatible", ""], // 25
|
||||
[false, false, false, true, true, false, APP, true, 38, "", "disabled"], // 26
|
||||
[true, true, false, false, true, false, APP, false, 39, "enabled", ""], // 27
|
||||
[false, true, true, true, true, false, APP, true, 40, "incompatible", "disabled"], // 28
|
||||
[true, true, true, false, true, false, APP, false, 41, "incompatible", ""], // 29
|
||||
];
|
||||
|
||||
function waitForView(aView, aCallback) {
|
||||
var view = gWin.document.getElementById(aView);
|
||||
view.addEventListener("ViewChanged", function() {
|
||||
view.removeEventListener("ViewChanged", arguments.callee, false);
|
||||
aCallback();
|
||||
}, false);
|
||||
}
|
||||
|
||||
function getString(aName) {
|
||||
if (!aName)
|
||||
return "";
|
||||
|
||||
var strings = Services.strings.createBundle("chrome://mozapps/locale/extensions/selectAddons.properties");
|
||||
return strings.GetStringFromName("action." + aName);
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
gProvider = new MockProvider();
|
||||
|
||||
ADDONS.forEach(function(aAddon, aPos) {
|
||||
var addon = new MockAddon("test" + aPos + "@tests.mozilla.org",
|
||||
"Test Add-on " + aPos, "extension");
|
||||
addon.version = "1.0";
|
||||
addon.userDisabled = aAddon[0];
|
||||
addon.appDisabled = aAddon[1];
|
||||
addon.isActive = aAddon[3];
|
||||
addon.applyBackgroundUpdates = aAddon[5] ? AddonManager.AUTOUPDATE_ENABLE
|
||||
: AddonManager.AUTOUPDATE_DISABLE;
|
||||
addon.scope = aAddon[6];
|
||||
|
||||
// Remove the upgrade permission from non-profile add-ons
|
||||
if (addon.scope != AddonManager.SCOPE_PROFILE)
|
||||
addon._permissions -= AddonManager.PERM_CAN_UPGRADE;
|
||||
|
||||
addon.findUpdates = function(aListener, aReason, aAppVersion, aPlatformVersion) {
|
||||
addon.appDisabled = aAddon[2];
|
||||
addon.isActive = addon.shouldBeActive;
|
||||
|
||||
if (aAddon[4]) {
|
||||
var newAddon = new MockAddon(this.id, this.name, "extension");
|
||||
newAddon.version = "2.0";
|
||||
var install = new MockInstall(this.name, this.type, newAddon);
|
||||
install.existingAddon = this;
|
||||
aListener.onUpdateAvailable(this, install);
|
||||
}
|
||||
|
||||
aListener.onUpdateFinished(this, AddonManager.UPDATE_STATUS_NO_ERROR);
|
||||
};
|
||||
|
||||
gProvider.addAddon(addon);
|
||||
});
|
||||
|
||||
gWin = Services.ww.openWindow(null,
|
||||
"chrome://mozapps/content/extensions/selectAddons.xul",
|
||||
"",
|
||||
"chrome,centerscreen,dialog,titlebar",
|
||||
null);
|
||||
waitForFocus(function() {
|
||||
waitForView("select", run_next_test);
|
||||
}, gWin);
|
||||
}
|
||||
|
||||
function end_test() {
|
||||
gWin.close();
|
||||
finish();
|
||||
}
|
||||
|
||||
// Minimal test for the checking UI
|
||||
add_test(function checking_test() {
|
||||
// By the time we're here the progress bar should be full
|
||||
var progress = gWin.document.getElementById("checking-progress");
|
||||
is(progress.mode, "determined", "Should be a determined progress bar");
|
||||
is(progress.value, progress.max, "Should be at full progress");
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
// Tests that the selection UI behaves correctly
|
||||
add_test(function selection_test() {
|
||||
function check_state() {
|
||||
var str = addon[keep.checked ? 9 : 10];
|
||||
var expected = getString(str);
|
||||
var showCheckbox = str == "neededupdate" || str == "unneededupdate";
|
||||
is(action.textContent, expected, "Action message should have the right text");
|
||||
is(!is_hidden(update), showCheckbox, "Checkbox should have the right visibility");
|
||||
is(is_hidden(action), showCheckbox, "Message should have the right visibility");
|
||||
if (showCheckbox)
|
||||
ok(update.checked, "Optional update checkbox should be checked");
|
||||
|
||||
if (keep.checked) {
|
||||
is(row.hasAttribute("active"), !addon[2] || hasUpdate,
|
||||
"Add-on will be active if it isn't appDisabled or an update is available");
|
||||
|
||||
if (showCheckbox) {
|
||||
info("Flipping update checkbox");
|
||||
EventUtils.synthesizeMouseAtCenter(update, { }, gWin);
|
||||
is(row.hasAttribute("active"), str == "unneededupdate",
|
||||
"If the optional update isn't needed then the add-on will still be active");
|
||||
|
||||
info("Flipping update checkbox");
|
||||
EventUtils.synthesizeMouseAtCenter(update, { }, gWin);
|
||||
is(row.hasAttribute("active"), !addon[2] || hasUpdate,
|
||||
"Add-on will be active if it isn't appDisabled or an update is available");
|
||||
}
|
||||
}
|
||||
else {
|
||||
ok(!row.hasAttribute("active"), "Add-on won't be active when not keeping");
|
||||
|
||||
if (showCheckbox) {
|
||||
info("Flipping update checkbox");
|
||||
EventUtils.synthesizeMouseAtCenter(update, { }, gWin);
|
||||
ok(!row.hasAttribute("active"),
|
||||
"Unchecking the update checkbox shouldn't make the add-on active");
|
||||
|
||||
info("Flipping update checkbox");
|
||||
EventUtils.synthesizeMouseAtCenter(update, { }, gWin);
|
||||
ok(!row.hasAttribute("active"),
|
||||
"Re-checking the update checkbox shouldn't make the add-on active");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is(gWin.document.getElementById("view-deck").selectedPanel.id, "select",
|
||||
"Should be on the right view");
|
||||
|
||||
var pos = 0;
|
||||
var scrollbox = gWin.document.getElementById("select-scrollbox");
|
||||
var scrollBoxObject = scrollbox.boxObject.QueryInterface(Ci.nsIScrollBoxObject);
|
||||
for (var row = gWin.document.getElementById("select-rows").firstChild; row; row = row.nextSibling) {
|
||||
// Ignore separators but increase the position by a large amount so we
|
||||
// can verify they were in the right place
|
||||
if (row.localName == "separator") {
|
||||
pos += 30;
|
||||
continue;
|
||||
}
|
||||
|
||||
is(row._addon.type, "extension", "Should only be listing extensions");
|
||||
|
||||
// Ignore non-test add-ons that may be present
|
||||
if (row.id.substr(-18) != "@tests.mozilla.org")
|
||||
continue;
|
||||
|
||||
var id = parseInt(row.id.substring(4, row.id.length - 18));
|
||||
var addon = ADDONS[id];
|
||||
|
||||
info("Testing add-on " + id);
|
||||
scrollBoxObject.ensureElementIsVisible(row);
|
||||
var keep = gWin.document.getAnonymousElementByAttribute(row, "anonid", "keep");
|
||||
var action = gWin.document.getAnonymousElementByAttribute(row, "class", "addon-action-message");
|
||||
var update = gWin.document.getAnonymousElementByAttribute(row, "anonid", "update");
|
||||
|
||||
// Non-profile add-ons don't appear to have updates since we won't install
|
||||
// them
|
||||
var hasUpdate = addon[4] && addon[6] == PROFILE;
|
||||
|
||||
is(pos, addon[8], "Should have been in the right position");
|
||||
is(keep.checked, addon[7], "Keep checkbox should be in the right state");
|
||||
|
||||
check_state();
|
||||
|
||||
info("Flipping keep");
|
||||
EventUtils.synthesizeMouseAtCenter(keep, { }, gWin);
|
||||
is(keep.checked, !addon[7], "Keep checkbox should be in the right state");
|
||||
|
||||
check_state();
|
||||
|
||||
pos++;
|
||||
}
|
||||
|
||||
is(pos, 90, "Should have seen the right number of add-ons");
|
||||
|
||||
run_next_test();
|
||||
});
|
|
@ -0,0 +1,172 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// Tests the update part of the post-app-update dialog
|
||||
|
||||
var gProvider;
|
||||
var gWin;
|
||||
|
||||
function waitForView(aView, aCallback) {
|
||||
var view = gWin.document.getElementById(aView);
|
||||
view.addEventListener("ViewChanged", function() {
|
||||
view.removeEventListener("ViewChanged", arguments.callee, false);
|
||||
aCallback();
|
||||
}, false);
|
||||
}
|
||||
|
||||
function waitForClose(aCallback) {
|
||||
gWin.addEventListener("unload", function() {
|
||||
gWin.removeEventListener("unload", arguments.callee, false);
|
||||
|
||||
aCallback();
|
||||
}, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates 4 test add-ons. Two are disabled and two enabled.
|
||||
*/
|
||||
function setupUI(aFailDownloads, aFailInstalls, aCallback) {
|
||||
if (gProvider)
|
||||
gProvider.unregister();
|
||||
|
||||
gProvider = new MockProvider();
|
||||
|
||||
for (var i = 1; i < 5; i++) {
|
||||
var addon = new MockAddon("test" + i + "@tests.mozilla.org",
|
||||
"Test Add-on " + i, "extension");
|
||||
addon.version = "1.0";
|
||||
addon.userDisabled = (i > 2);
|
||||
addon.appDisabled = false;
|
||||
addon.isActive = !addon.userDisabled && !addon.appDisabled;
|
||||
|
||||
addon.findUpdates = function(aListener, aReason, aAppVersion, aPlatformVersion) {
|
||||
var newAddon = new MockAddon(this.id, this.name, "extension");
|
||||
newAddon.version = "2.0";
|
||||
var install = new MockInstall(this.name, this.type, newAddon);
|
||||
install.existingAddon = this;
|
||||
|
||||
install.install = function() {
|
||||
this.state = AddonManager.STATE_DOWNLOADING;
|
||||
this.callListeners("onDownloadStarted");
|
||||
|
||||
var self = this;
|
||||
executeSoon(function() {
|
||||
if (aFailDownloads) {
|
||||
self.state = AddonManager.STATE_DOWNLOAD_FAILED;
|
||||
self.callListeners("onDownloadFailed");
|
||||
return;
|
||||
}
|
||||
|
||||
self.type = self._type;
|
||||
self.addon = new MockAddon(self.existingAddon.id, self.name, self.type);
|
||||
self.addon.version = self.version;
|
||||
self.addon.pendingOperations = AddonManager.PENDING_INSTALL;
|
||||
self.addon.install = self;
|
||||
|
||||
self.existingAddon.pendingUpgrade = self.addon;
|
||||
self.existingAddon.pendingOperations |= AddonManager.PENDING_UPGRADE;
|
||||
|
||||
self.state = AddonManager.STATE_DOWNLOADED;
|
||||
self.callListeners("onDownloadEnded");
|
||||
|
||||
self.state = AddonManager.STATE_INSTALLING;
|
||||
self.callListeners("onInstallStarted");
|
||||
|
||||
if (aFailInstalls) {
|
||||
self.state = AddonManager.STATE_INSTALL_FAILED;
|
||||
self.callListeners("onInstallFailed");
|
||||
return;
|
||||
}
|
||||
|
||||
self.state = AddonManager.STATE_INSTALLED;
|
||||
self.callListeners("onInstallEnded");
|
||||
});
|
||||
}
|
||||
|
||||
aListener.onUpdateAvailable(this, install);
|
||||
|
||||
aListener.onUpdateFinished(this, AddonManager.UPDATE_STATUS_NO_ERROR);
|
||||
};
|
||||
|
||||
gProvider.addAddon(addon);
|
||||
}
|
||||
|
||||
gWin = Services.ww.openWindow(null,
|
||||
"chrome://mozapps/content/extensions/selectAddons.xul",
|
||||
"",
|
||||
"chrome,centerscreen,dialog,titlebar",
|
||||
null);
|
||||
waitForFocus(function() {
|
||||
waitForView("select", function() {
|
||||
var row = gWin.document.getElementById("select-rows").firstChild.nextSibling;
|
||||
while (row) {
|
||||
if (row.id == "test2@tests.mozilla.org" ||
|
||||
row.id == "test4@tests.mozilla.org") {
|
||||
row.disable();
|
||||
}
|
||||
else {
|
||||
row.keep();
|
||||
}
|
||||
row = row.nextSibling;
|
||||
}
|
||||
|
||||
waitForView("confirm", function() {
|
||||
waitForView("update", aCallback);
|
||||
EventUtils.synthesizeMouseAtCenter(gWin.document.getElementById("next"), {}, gWin);
|
||||
});
|
||||
EventUtils.synthesizeMouseAtCenter(gWin.document.getElementById("next"), {}, gWin);
|
||||
});
|
||||
}, gWin);
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
requestLongerTimeout(100);
|
||||
|
||||
run_next_test();
|
||||
}
|
||||
|
||||
function end_test() {
|
||||
finish();
|
||||
}
|
||||
|
||||
// Test for working updates
|
||||
add_test(function working_test() {
|
||||
setupUI(false, false, function() {
|
||||
waitForClose(function() {
|
||||
is(gWin.document.getElementById("update-progress").value, 2, "Should have finished 2 downloads");
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(gWin.document.getElementById("next"), {}, gWin);
|
||||
});
|
||||
});
|
||||
|
||||
// Test for failed updates
|
||||
add_test(function working_test() {
|
||||
setupUI(true, false, function() {
|
||||
waitForView("errors", function() {
|
||||
is(gWin.document.getElementById("update-progress").value, 2, "Should have finished 2 downloads");
|
||||
gWin.close();
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(gWin.document.getElementById("next"), {}, gWin);
|
||||
});
|
||||
});
|
||||
|
||||
// Test for failed updates
|
||||
add_test(function working_test() {
|
||||
setupUI(false, true, function() {
|
||||
waitForView("errors", function() {
|
||||
is(gWin.document.getElementById("update-progress").value, 2, "Should have finished 2 downloads");
|
||||
gWin.close();
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(gWin.document.getElementById("next"), {}, gWin);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,113 @@
|
|||
/* ***** 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 mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
*
|
||||
* 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 *****
|
||||
*/
|
||||
|
||||
const URI_EXTENSION_SELECT_DIALOG = "chrome://mozapps/content/extensions/selectAddons.xul";
|
||||
const URI_EXTENSION_UPDATE_DIALOG = "chrome://mozapps/content/extensions/update.xul";
|
||||
const PREF_EM_SHOW_MISMATCH_UI = "extensions.showMismatchUI";
|
||||
const PREF_SHOWN_SELECTION_UI = "extensions.shownSelectionUI";
|
||||
|
||||
const profileDir = gProfD.clone();
|
||||
profileDir.append("extensions");
|
||||
|
||||
var gExpectedURL = null;
|
||||
|
||||
// This will be called to show the any update dialog.
|
||||
var WindowWatcher = {
|
||||
openWindow: function(parent, url, name, features, arguments) {
|
||||
do_check_eq(url, gExpectedURL);
|
||||
gExpectedURL = null;
|
||||
},
|
||||
|
||||
QueryInterface: function(iid) {
|
||||
if (iid.equals(AM_Ci.nsIWindowWatcher)
|
||||
|| iid.equals(AM_Ci.nsISupports))
|
||||
return this;
|
||||
|
||||
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||
}
|
||||
}
|
||||
|
||||
var WindowWatcherFactory = {
|
||||
createInstance: function createInstance(outer, iid) {
|
||||
if (outer != null)
|
||||
throw Components.results.NS_ERROR_NO_AGGREGATION;
|
||||
return WindowWatcher.QueryInterface(iid);
|
||||
}
|
||||
};
|
||||
|
||||
var registrar = Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar);
|
||||
registrar.registerFactory(Components.ID("{1dfeb90a-2193-45d5-9cb8-864928b2af55}"),
|
||||
"Fake Window Watcher",
|
||||
"@mozilla.org/embedcomp/window-watcher;1", WindowWatcherFactory);
|
||||
|
||||
// Tests that the selection UI is displayed when upgrading an existing profile
|
||||
function run_test() {
|
||||
createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1");
|
||||
|
||||
Services.prefs.setBoolPref(PREF_EM_SHOW_MISMATCH_UI, true);
|
||||
|
||||
var dest = writeInstallRDFForExtension({
|
||||
id: "addon1@tests.mozilla.org",
|
||||
version: "1.0",
|
||||
targetApplications: [{
|
||||
id: "xpcshell@tests.mozilla.org",
|
||||
minVersion: "1",
|
||||
maxVersion: "1"
|
||||
}],
|
||||
name: "Test Addon 1",
|
||||
}, profileDir);
|
||||
|
||||
startupManager();
|
||||
|
||||
// For a new profile it should disable showing the selection UI in the future
|
||||
do_check_true(Services.prefs.getBoolPref(PREF_SHOWN_SELECTION_UI));
|
||||
Services.prefs.clearUserPref(PREF_SHOWN_SELECTION_UI);
|
||||
|
||||
gExpectedURL = URI_EXTENSION_SELECT_DIALOG;
|
||||
restartManager("2");
|
||||
|
||||
do_check_true(Services.prefs.getBoolPref(PREF_SHOWN_SELECTION_UI));
|
||||
do_check_eq(gExpectedURL, null);
|
||||
|
||||
gExpectedURL = URI_EXTENSION_UPDATE_DIALOG;
|
||||
|
||||
restartManager("3");
|
||||
|
||||
do_check_eq(gExpectedURL, null);
|
||||
}
|
|
@ -50,6 +50,7 @@ tail =
|
|||
[test_bug594058.js]
|
||||
[test_bug595081.js]
|
||||
[test_bug595573.js]
|
||||
[test_bug596343.js]
|
||||
[test_bug596607.js]
|
||||
[test_bug616841.js]
|
||||
[test_bug619730.js]
|
||||
|
|
|
@ -0,0 +1,187 @@
|
|||
/* ***** 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 Manager UI.
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
#view-deck {
|
||||
background: Window;
|
||||
}
|
||||
|
||||
.heading {
|
||||
font-size: 270%;
|
||||
text-align: center;
|
||||
margin: 0 100px;
|
||||
}
|
||||
|
||||
.progress {
|
||||
margin: 10px 128px;
|
||||
}
|
||||
|
||||
.progress-label,
|
||||
#errors-description {
|
||||
text-align: center;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
#checking-heading,
|
||||
#update-heading,
|
||||
#errors-heading {
|
||||
margin-top: 90px;
|
||||
}
|
||||
|
||||
#select-heading,
|
||||
#confirm-heading {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#select-description,
|
||||
#confirm-description {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
#select-list {
|
||||
border-top: 1px solid WindowFrame;
|
||||
background-color: Window;
|
||||
}
|
||||
|
||||
#select-grid column {
|
||||
-moz-box-align: center;
|
||||
}
|
||||
|
||||
#select-grid row {
|
||||
-moz-box-align: stretch;
|
||||
}
|
||||
|
||||
#select-grid row:nth-of-type(odd) {
|
||||
background-color: -moz-oddtreerow;
|
||||
}
|
||||
|
||||
#select-grid label,
|
||||
#select-grid checkbox {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.select-cell {
|
||||
-moz-box-align: center;
|
||||
-moz-box-pack: start;
|
||||
}
|
||||
|
||||
#select-header .select-cell {
|
||||
-moz-appearance: treeheadercell;
|
||||
-moz-box-sizing: border-box;
|
||||
}
|
||||
|
||||
.select-keep {
|
||||
-moz-box-pack: center;
|
||||
}
|
||||
|
||||
.select-keep .checkbox-label-box {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.select-icon {
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
#select-grid separator {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.addon-name,
|
||||
.addon-action-message,
|
||||
.addon-action-update {
|
||||
-moz-box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding-top: 1px;
|
||||
padding-bottom: 2px;
|
||||
-moz-padding-start: 6px;
|
||||
-moz-padding-end: 5px;
|
||||
}
|
||||
|
||||
.addon:not([active]) .addon-name,
|
||||
.addon:not([active]) .addon-action-message,
|
||||
.addon:not([active]) .addon-action-update {
|
||||
color: GrayText;
|
||||
}
|
||||
|
||||
.addon-icon {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
margin: 2px;
|
||||
list-style-image: url("chrome://mozapps/skin/extensions/extensionGeneric-16.png");
|
||||
}
|
||||
|
||||
.addon-icon[type="theme"] {
|
||||
list-style-image: url("chrome://mozapps/skin/extensions/themeGeneric-16.png");
|
||||
}
|
||||
|
||||
.addon-icon[type="plugin"] {
|
||||
list-style-image: url("chrome://mozapps/skin/plugins/pluginGeneric-16.png");
|
||||
}
|
||||
|
||||
.action-list {
|
||||
margin-top: 10px;
|
||||
-moz-margin-start: 5em;
|
||||
}
|
||||
|
||||
.action-header {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#confirm .addon {
|
||||
-moz-margin-start: 3em;
|
||||
-moz-box-align: center;
|
||||
}
|
||||
|
||||
.addon:not([active]) .addon-icon,
|
||||
#disable-list .addon-icon,
|
||||
#incompatible-list .addon-icon {
|
||||
filter: url("chrome://mozapps/skin/extensions/extensions.svg#greyscale");
|
||||
}
|
||||
|
||||
#footer {
|
||||
padding: 15px 12px;
|
||||
border-top: 2px solid;
|
||||
-moz-border-top-colors: ThreeDHighlight ThreeDLightShadow;
|
||||
}
|
||||
|
||||
.progress-label,
|
||||
#footer-label {
|
||||
font-style: italic;
|
||||
color: GrayText;
|
||||
}
|
|
@ -28,6 +28,7 @@ toolkit.jar:
|
|||
+ skin/classic/mozapps/extensions/stripes-info-positive.png (extensions/stripes-info-positive.png)
|
||||
+ skin/classic/mozapps/extensions/stripes-info-negative.png (extensions/stripes-info-negative.png)
|
||||
+ skin/classic/mozapps/extensions/newaddon.css (extensions/newaddon.css)
|
||||
+ skin/classic/mozapps/extensions/selectAddons.css (extensions/selectAddons.css)
|
||||
+ skin/classic/mozapps/passwordmgr/key.png (passwordmgr/key.png)
|
||||
+ skin/classic/mozapps/passwordmgr/key-16.png (passwordmgr/key-16.png)
|
||||
+ skin/classic/mozapps/passwordmgr/key-64.png (passwordmgr/key-64.png)
|
||||
|
|
|
@ -0,0 +1,192 @@
|
|||
/* ***** 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 Manager UI.
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
%include ../../global/shared.inc
|
||||
|
||||
.heading {
|
||||
font-size: 270%;
|
||||
text-align: center;
|
||||
margin: 0 120px;
|
||||
}
|
||||
|
||||
.progress {
|
||||
margin: 10px 128px;
|
||||
}
|
||||
|
||||
.progress-label,
|
||||
#errors-description {
|
||||
text-align: center;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
#checking-heading,
|
||||
#update-heading,
|
||||
#errors-heading {
|
||||
margin-top: 90px;
|
||||
}
|
||||
|
||||
#select-heading,
|
||||
#confirm-heading {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#select-description,
|
||||
#confirm-description {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
#select-list {
|
||||
border: 1px solid WindowFrame;
|
||||
background-color: Window;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
#select-grid column {
|
||||
-moz-box-align: center;
|
||||
}
|
||||
|
||||
#select-grid row {
|
||||
-moz-box-align: stretch;
|
||||
}
|
||||
|
||||
#select-grid row:nth-of-type(odd) {
|
||||
background-color: -moz-oddtreerow;
|
||||
}
|
||||
|
||||
#select-grid label,
|
||||
#select-grid checkbox {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.select-cell {
|
||||
-moz-box-align: center;
|
||||
-moz-box-pack: start;
|
||||
-moz-box-sizing: border-box;
|
||||
}
|
||||
|
||||
#select-header {
|
||||
background-color: Window !important;
|
||||
}
|
||||
|
||||
#select-header .select-cell {
|
||||
-moz-appearance: treeheadercell;
|
||||
border: 2px solid;
|
||||
-moz-border-top-colors: ThreeDHighlight ThreeDLightShadow;
|
||||
-moz-border-right-colors: ThreeDDarkShadow ThreeDShadow;
|
||||
-moz-border-bottom-colors: ThreeDDarkShadow ThreeDShadow;
|
||||
-moz-border-left-colors: ThreeDHighlight ThreeDLightShadow;
|
||||
background-color: -moz-Dialog;
|
||||
color: -moz-DialogText;
|
||||
}
|
||||
|
||||
.select-keep {
|
||||
-moz-box-pack: center;
|
||||
}
|
||||
|
||||
.select-icon {
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
#select-grid separator {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.addon-name,
|
||||
.addon-action-message,
|
||||
.addon-action-update {
|
||||
-moz-box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 2px 6px;
|
||||
}
|
||||
|
||||
.addon:not([active]) .addon-name,
|
||||
.addon:not([active]) .addon-action-message,
|
||||
.addon:not([active]) .addon-action-update {
|
||||
color: GrayText;
|
||||
}
|
||||
|
||||
.addon-icon {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
margin: 2px;
|
||||
list-style-image: url("chrome://mozapps/skin/extensions/extensionGeneric-16.png");
|
||||
}
|
||||
|
||||
.addon-icon[type="theme"] {
|
||||
list-style-image: url("chrome://mozapps/skin/extensions/themeGeneric-16.png");
|
||||
}
|
||||
|
||||
.addon-icon[type="plugin"] {
|
||||
list-style-image: url("chrome://mozapps/skin/plugins/pluginGeneric-16.png");
|
||||
}
|
||||
|
||||
.action-list {
|
||||
margin-top: 10px;
|
||||
-moz-margin-start: 5em;
|
||||
}
|
||||
|
||||
.action-header {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#confirm .addon {
|
||||
-moz-margin-start: 3em;
|
||||
-moz-box-align: center;
|
||||
}
|
||||
|
||||
.addon:not([active]) .addon-icon,
|
||||
#disable-list .addon-icon,
|
||||
#incompatible-list .addon-icon {
|
||||
filter: url("chrome://mozapps/skin/extensions/extensions.svg#greyscale");
|
||||
}
|
||||
|
||||
#footer {
|
||||
padding: 15px 12px;
|
||||
-moz-binding: url("chrome://global/content/bindings/general.xml#windowdragbox");
|
||||
-moz-appearance: statusbar;
|
||||
}
|
||||
|
||||
button {
|
||||
-moz-appearance: toolbarbutton;
|
||||
min-height: 22px;
|
||||
margin: 0 6px;
|
||||
padding: 0;
|
||||
text-shadow: @loweredShadow@;
|
||||
}
|
|
@ -39,6 +39,7 @@ toolkit.jar:
|
|||
skin/classic/mozapps/extensions/about.css (extensions/about.css)
|
||||
* skin/classic/mozapps/extensions/extensions.css (extensions/extensions.css)
|
||||
skin/classic/mozapps/extensions/extensions.svg (extensions/extensions.svg)
|
||||
* skin/classic/mozapps/extensions/selectAddons.css (extensions/selectAddons.css)
|
||||
skin/classic/mozapps/extensions/update.css (extensions/update.css)
|
||||
skin/classic/mozapps/extensions/eula.css (extensions/eula.css)
|
||||
skin/classic/mozapps/extensions/blocklist.css (extensions/blocklist.css)
|
||||
|
|
|
@ -0,0 +1,199 @@
|
|||
/* ***** 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 Manager UI.
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
#view-deck {
|
||||
background: Window;
|
||||
}
|
||||
|
||||
.heading {
|
||||
font-size: 270%;
|
||||
text-align: center;
|
||||
margin: 0 120px;
|
||||
}
|
||||
|
||||
.progress {
|
||||
margin: 10px 128px;
|
||||
}
|
||||
|
||||
.progress-label,
|
||||
#errors-description {
|
||||
text-align: center;
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
#checking-heading,
|
||||
#update-heading,
|
||||
#errors-heading {
|
||||
margin-top: 90px;
|
||||
}
|
||||
|
||||
#select-heading,
|
||||
#confirm-heading {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#select-description,
|
||||
#confirm-description {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
#select-list {
|
||||
border-top: 1px solid #D6E5F5;
|
||||
background-color: Window;
|
||||
}
|
||||
|
||||
#select-grid column {
|
||||
-moz-box-align: center;
|
||||
}
|
||||
|
||||
#select-grid row {
|
||||
-moz-box-align: stretch;
|
||||
}
|
||||
|
||||
#select-grid label {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.select-cell {
|
||||
-moz-box-align: center;
|
||||
-moz-box-pack: start;
|
||||
}
|
||||
|
||||
#select-header .select-cell {
|
||||
-moz-box-sizing: border-box;
|
||||
}
|
||||
|
||||
#select-header .select-keep,
|
||||
#select-header .select-icon,
|
||||
#select-header .select-name,
|
||||
#select-header .select-action {
|
||||
background-image: -moz-linear-gradient(top, #D6E5F5 0%, Window 100%);
|
||||
background-size: 1px 100%;
|
||||
background-position: right;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.select-keep {
|
||||
-moz-box-pack: center;
|
||||
}
|
||||
|
||||
.select-icon {
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.select-keep .addon-keep-checkbox {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 13px;
|
||||
}
|
||||
|
||||
.select-keep .checkbox-label-box {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.addon-name,
|
||||
.addon-action-message,
|
||||
.addon-action-update {
|
||||
-moz-box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding-top: 1px;
|
||||
padding-bottom: 2px;
|
||||
-moz-padding-start: 6px;
|
||||
-moz-padding-end: 5px;
|
||||
}
|
||||
|
||||
#select-grid separator {
|
||||
border-top: 1px solid #D6E5F5;
|
||||
height: 0;
|
||||
margin-top: 0.4em;
|
||||
margin-bottom: 0.4em;
|
||||
}
|
||||
|
||||
.addon:not([active]) .addon-name,
|
||||
.addon:not([active]) .addon-action-message,
|
||||
.addon:not([active]) .addon-action-update {
|
||||
color: GrayText;
|
||||
}
|
||||
|
||||
.addon-icon {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
list-style-image: url("chrome://mozapps/skin/extensions/extensionGeneric-16.png");
|
||||
}
|
||||
|
||||
.addon-icon[type="theme"] {
|
||||
list-style-image: url("chrome://mozapps/skin/extensions/themeGeneric-16.png");
|
||||
}
|
||||
|
||||
.addon-icon[type="plugin"] {
|
||||
list-style-image: url("chrome://mozapps/skin/plugins/pluginGeneric-16.png");
|
||||
}
|
||||
|
||||
.action-list {
|
||||
margin-top: 10px;
|
||||
-moz-margin-start: 5em;
|
||||
}
|
||||
|
||||
.action-header {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
#confirm .addon {
|
||||
-moz-margin-start: 3em;
|
||||
-moz-box-align: center;
|
||||
}
|
||||
|
||||
.addon:not([active]) .addon-icon,
|
||||
#disable-list .addon-icon,
|
||||
#incompatible-list .addon-icon {
|
||||
filter: url("chrome://mozapps/skin/extensions/extensions.svg#greyscale");
|
||||
}
|
||||
|
||||
#footer {
|
||||
padding: 15px 12px;
|
||||
background-color: #f1f5fb;
|
||||
box-shadow: 0px 1px 2px rgb(204,214,234) inset;
|
||||
}
|
||||
|
||||
.progress-label,
|
||||
#footer-label {
|
||||
font-style: italic;
|
||||
color: GrayText;
|
||||
}
|
|
@ -10,6 +10,7 @@ toolkit.jar:
|
|||
skin/classic/mozapps/extensions/about.css (extensions/about.css)
|
||||
skin/classic/mozapps/extensions/blocklist.css (extensions/blocklist.css)
|
||||
* skin/classic/mozapps/extensions/extensions.css (extensions/extensions.css)
|
||||
* skin/classic/mozapps/extensions/selectAddons.css (extensions/selectAddons.css)
|
||||
skin/classic/mozapps/extensions/update.css (extensions/update.css)
|
||||
skin/classic/mozapps/extensions/extensions.svg (extensions/extensions.svg)
|
||||
skin/classic/mozapps/extensions/category-search.png (extensions/category-search.png)
|
||||
|
@ -85,6 +86,7 @@ toolkit.jar:
|
|||
skin/classic/aero/mozapps/extensions/about.css (extensions/about.css)
|
||||
skin/classic/aero/mozapps/extensions/blocklist.css (extensions/blocklist.css)
|
||||
* skin/classic/aero/mozapps/extensions/extensions.css (extensions/extensions-aero.css)
|
||||
* skin/classic/aero/mozapps/extensions/selectAddons.css (extensions/selectAddons.css)
|
||||
skin/classic/aero/mozapps/extensions/update.css (extensions/update.css)
|
||||
skin/classic/aero/mozapps/extensions/extensions.svg (extensions/extensions.svg)
|
||||
skin/classic/aero/mozapps/extensions/themeGeneric.png (extensions/themeGeneric-aero.png)
|
||||
|
|
Загрузка…
Ссылка в новой задаче