Bug 596343: Users should have exclusive control over selecting their add-ons. r=Unfocused

This commit is contained in:
Dave Townsend 2011-08-12 16:55:34 -07:00
Родитель f3ee939112
Коммит 8e0e038bd5
23 изменённых файлов: 2231 добавлений и 55 удалений

Просмотреть файл

@ -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)