зеркало из https://github.com/mozilla/pjs.git
Bug 562622 - Implementation of the automatic vs. manual update design mockups. r=dtownsend, a=blocking2.0-beta3
This commit is contained in:
Родитель
96bb9a2ce3
Коммит
148aadce27
|
@ -2,6 +2,9 @@
|
|||
<!ENTITY search.placeholder "Search all add-ons">
|
||||
<!ENTITY loading.label "Loading…">
|
||||
<!ENTITY listEmpty.installed.label "You don't have any add-ons of this type installed">
|
||||
<!ENTITY listEmpty.availableUpdates.label "No updates found">
|
||||
<!ENTITY listEmpty.recentUpdates.label "You haven't recently updated any add-ons">
|
||||
<!ENTITY listEmpty.findUpdates.label "Check For Updates">
|
||||
<!ENTITY listEmpty.search.label "Could not find any matching add-ons">
|
||||
<!ENTITY listEmpty.button.label "Learn more about add-ons">
|
||||
|
||||
|
@ -15,14 +18,22 @@
|
|||
<!ENTITY view.features.label "Extensions">
|
||||
<!ENTITY view.appearance.label "Themes">
|
||||
<!ENTITY view.plugins.label "Plugins">
|
||||
<!ENTITY view.recentUpdates.label "Recent Updates">
|
||||
<!ENTITY view.availableUpdates.label "Available Updates">
|
||||
|
||||
<!-- addon updates -->
|
||||
<!ENTITY updates.updateNow.label "Update add-ons">
|
||||
<!ENTITY updates.updateAddonsNow.label "Update Add-ons Now">
|
||||
<!ENTITY updates.updateAddonsNow.accesskey "U">
|
||||
<!ENTITY updates.viewUpdates.label "View Recent Updates">
|
||||
<!ENTITY updates.viewUpdates.accesskey "V">
|
||||
<!ENTITY updates.backgroudUpdateCheck.label "Check for Updates Automatically">
|
||||
<!ENTITY updates.backgroudUpdateCheck.accesskey "C">
|
||||
<!ENTITY updates.updating.label "Updating add-ons">
|
||||
<!ENTITY updates.installed.label "Your add-ons have been updated.">
|
||||
<!ENTITY updates.downloaded.label "Your add-on updates have been downloaded.">
|
||||
<!ENTITY updates.restart.label "Restart now to complete installation">
|
||||
<!ENTITY updates.noneFound.label "No updates found">
|
||||
<!ENTITY updates.manualUpdatesFound.label "View Available Updates">
|
||||
|
||||
<!-- addon actions -->
|
||||
<!ENTITY cmd.showDetails.label "Show more information">
|
||||
|
@ -46,6 +57,10 @@
|
|||
<!ENTITY cmd.contribute.accesskey "C">
|
||||
<!ENTITY cmd.contribute.tooltip "Contribute to the development of this add-on">
|
||||
|
||||
<!ENTITY cmd.showReleaseNotes.label "Show Release Notes">
|
||||
<!ENTITY cmd.showReleaseNotes.tooltip "Show the release notes for this update">
|
||||
<!ENTITY cmd.hideReleaseNotes.label "Hide Release Notes">
|
||||
<!ENTITY cmd.hideReleaseNotes.tooltip "Hide the release notes for this update">
|
||||
|
||||
<!-- detail view -->
|
||||
<!ENTITY detail.version.label "Version">
|
||||
|
@ -96,6 +111,7 @@
|
|||
<!ENTITY addon.homepage "Homepage">
|
||||
<!ENTITY addon.unknownDate "Unknown">
|
||||
<!ENTITY addon.disabled.postfix "(disabled)">
|
||||
<!ENTITY addon.update.postfix "Update">
|
||||
<!ENTITY addon.undo.label "Undo?">
|
||||
<!ENTITY addon.undo.tooltip "Undo this action">
|
||||
<!ENTITY addon.undoUninstall.label "Undo?">
|
||||
|
@ -104,6 +120,11 @@
|
|||
<!ENTITY addon.restartNow.tooltip "Restart now to complete installation">
|
||||
<!ENTITY addon.install.label "Install">
|
||||
<!ENTITY addon.install.tooltip "Install this add-on">
|
||||
<!ENTITY addon.updateNow.label "Update Now">
|
||||
<!ENTITY addon.updateNow.tooltip "Install the update for this add-on">
|
||||
<!ENTITY addon.checkingForUpdates.label "Checking for updates…">
|
||||
<!ENTITY addon.releaseNotes.label "Release Notes:">
|
||||
<!ENTITY addon.loadingReleaseNotes.label "Loading…">
|
||||
<!ENTITY addon.errorLoadingReleaseNotes.label "Sorry, but there was an error loading the release notes.">
|
||||
|
||||
<!ENTITY addon.createdBy.label "By ">
|
||||
|
|
|
@ -14,6 +14,8 @@ header-searchengine=Search Engines
|
|||
header-extension=Extensions
|
||||
header-theme=Themes
|
||||
header-plugin=Plugins
|
||||
header-recentUpdates=Recent Updates
|
||||
header-availableUpdates=Available Updates
|
||||
|
||||
#LOCALIZATION NOTE (header-goBack) %S is the name of the pane to go back to
|
||||
header-goBack=Back to %S
|
||||
|
|
|
@ -92,6 +92,14 @@
|
|||
visibility: collapse;
|
||||
}
|
||||
|
||||
.addon:not([upgrade="true"]) .update-postfix {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#detail-view[loading] > .detail-view-container {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.view-pane:not(#updates-view) .addon .relnotes-toggle {
|
||||
display: none;
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ Cu.import("resource://gre/modules/AddonRepository.jsm");
|
|||
|
||||
const PREF_DISCOVERURL = "extensions.webservice.discoverURL";
|
||||
const PREF_MAXRESULTS = "extensions.getAddons.maxResults";
|
||||
const PREF_BACKGROUND_UPDATE = "extensions.update.enabled";
|
||||
|
||||
const LOADING_MSG_DELAY = 100;
|
||||
|
||||
|
@ -61,6 +62,11 @@ const SEARCH_SCORE_MATCH_WHOLEWORD = 10;
|
|||
const SEARCH_SCORE_MATCH_WORDBOUNDRY = 6;
|
||||
const SEARCH_SCORE_MATCH_SUBSTRING = 3;
|
||||
|
||||
const UPDATES_RECENT_TIMESPAN = 2 * 24 * 3600000; // 2 days (in milliseconds)
|
||||
const UPDATES_RELEASENOTES_TRANSFORMFILE = "chrome://mozapps/content/extensions/updateinfo.xsl";
|
||||
|
||||
const XMLURI_PARSE_ERROR = "http://www.mozilla.org/newlayout/xml/parsererror.xml"
|
||||
|
||||
const VIEW_DEFAULT = "addons://list/extension";
|
||||
|
||||
const INTEGER_FIELDS = ["dateUpdated", "size", "relevancescore"];
|
||||
|
@ -145,8 +151,8 @@ var gEventManager = {
|
|||
var self = this;
|
||||
["onEnabling", "onEnabled", "onDisabling", "onDisabled", "onUninstalling",
|
||||
"onUninstalled", "onInstalled", "onOperationCancelled",
|
||||
"onUpdateAvailable", "onUpdateFinished",
|
||||
"onCompatibilityUpdateAvailable"].forEach(function(aEvent) {
|
||||
"onUpdateAvailable", "onUpdateFinished", "onCompatibilityUpdateAvailable",
|
||||
"onPropertyChanged"].forEach(function(aEvent) {
|
||||
self[aEvent] = function() {
|
||||
self.delegateAddonEvent(aEvent, Array.splice(arguments, 0));
|
||||
};
|
||||
|
@ -262,6 +268,7 @@ var gViewController = {
|
|||
this.viewObjects["discover"] = gDiscoverView;
|
||||
this.viewObjects["list"] = gListView;
|
||||
this.viewObjects["detail"] = gDetailView;
|
||||
this.viewObjects["updates"] = gUpdatesView;
|
||||
|
||||
for each (let view in this.viewObjects)
|
||||
view.initialize();
|
||||
|
@ -273,6 +280,17 @@ var gViewController = {
|
|||
if (this.currentViewObj)
|
||||
this.currentViewObj.hide();
|
||||
this.currentViewRequest = 0;
|
||||
|
||||
for each(let view in this.viewObjects) {
|
||||
if ("shutdown" in view) {
|
||||
try {
|
||||
view.shutdown();
|
||||
} catch(e) {
|
||||
// this shouldn't be fatal
|
||||
Cu.reportError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
parseViewId: function(aViewId) {
|
||||
|
@ -352,6 +370,28 @@ var gViewController = {
|
|||
}
|
||||
},
|
||||
|
||||
cmd_goToRecentUpdates: {
|
||||
isEnabled: function() true,
|
||||
doCommand: function() {
|
||||
gViewController.loadView("addons://updates/recent");
|
||||
}
|
||||
},
|
||||
|
||||
cmd_goToAvailableUpdates: {
|
||||
isEnabled: function() true,
|
||||
doCommand: function() {
|
||||
gViewController.loadView("addons://updates/available");
|
||||
}
|
||||
},
|
||||
|
||||
cmd_toggleBackgroundUpdateCheck: {
|
||||
isEnabled: function() true,
|
||||
doCommand: function() {
|
||||
var enabled = !Services.prefs.getBoolPref(PREF_BACKGROUND_UPDATE);
|
||||
Services.prefs.setBoolPref(PREF_BACKGROUND_UPDATE, enabled);
|
||||
}
|
||||
},
|
||||
|
||||
cmd_showItemDetails: {
|
||||
isEnabled: function(aAddon) {
|
||||
return !!aAddon;
|
||||
|
@ -363,23 +403,36 @@ var gViewController = {
|
|||
},
|
||||
|
||||
cmd_findAllUpdates: {
|
||||
isEnabled: function() true,
|
||||
inProgress: false,
|
||||
isEnabled: function() !this.inProgress,
|
||||
doCommand: function() {
|
||||
document.getElementById("updates-checkNow").hidden = true;
|
||||
this.inProgress = true;
|
||||
gViewController.updateCommand("cmd_findAllUpdates");
|
||||
document.getElementById("updates-noneFound").hidden = true;
|
||||
document.getElementById("updates-progress").hidden = false;
|
||||
document.getElementById("updates-manualUpdatesFound").hidden = true;
|
||||
|
||||
var pendingChecks = 0;
|
||||
var numUpdated = 0;
|
||||
var numManualUpdates = 0;
|
||||
var restartNeeded = false;
|
||||
var self = this;
|
||||
|
||||
function updateStatus() {
|
||||
if (pendingChecks > 0)
|
||||
return;
|
||||
|
||||
self.inProgress = false;
|
||||
gViewController.updateCommand("cmd_findAllUpdates");
|
||||
document.getElementById("updates-progress").hidden = true;
|
||||
gUpdatesView.maybeRefresh();
|
||||
|
||||
if (numManualUpdates > 0 && numUpdated == 0) {
|
||||
document.getElementById("updates-manualUpdatesFound").hidden = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (numUpdated == 0) {
|
||||
document.getElementById("updates-checkNow").hidden = false;
|
||||
document.getElementById("updates-noneFound").hidden = false;
|
||||
return;
|
||||
}
|
||||
|
@ -414,8 +467,14 @@ var gViewController = {
|
|||
onUpdateAvailable: function(aAddon, aInstall) {
|
||||
gEventManager.delegateAddonEvent("onUpdateAvailable",
|
||||
[aAddon, aInstall]);
|
||||
aInstall.addListener(updateInstallListener);
|
||||
aInstall.install();
|
||||
if (aAddon.applyBackgroundUpdates !== false) {
|
||||
aInstall.addListener(updateInstallListener);
|
||||
aInstall.install();
|
||||
} else {
|
||||
pendingChecks--;
|
||||
numManualUpdates++;
|
||||
updateStatus();
|
||||
}
|
||||
},
|
||||
onNoUpdateAvailable: function(aAddon) {
|
||||
pendingChecks--;
|
||||
|
@ -453,7 +512,8 @@ var gViewController = {
|
|||
onUpdateAvailable: function(aAddon, aInstall) {
|
||||
gEventManager.delegateAddonEvent("onUpdateAvailable",
|
||||
[aAddon, aInstall]);
|
||||
aInstall.install();
|
||||
if (aAddon.applyBackgroundUpdates !== false)
|
||||
aInstall.install();
|
||||
},
|
||||
onNoUpdateAvailable: function(aAddon) {
|
||||
gEventManager.delegateAddonEvent("onNoUpdateAvailable",
|
||||
|
@ -596,17 +656,22 @@ var gViewController = {
|
|||
if (!this.currentViewObj)
|
||||
return;
|
||||
var addon = this.currentViewObj.getSelectedAddon();
|
||||
for (let commandId in this.commands) {
|
||||
let cmd = this.commands[commandId];
|
||||
let cmdElt = document.getElementById(commandId);
|
||||
cmdElt.setAttribute("disabled", !cmd.isEnabled(addon));
|
||||
if ("getTooltip" in cmd) {
|
||||
let tooltip = cmd.getTooltip(addon);
|
||||
if (tooltip)
|
||||
cmdElt.setAttribute("tooltiptext", tooltip);
|
||||
else
|
||||
cmdElt.removeAttribute("tooltiptext");
|
||||
}
|
||||
for (let commandId in this.commands)
|
||||
this.updateCommand(commandId, addon);
|
||||
},
|
||||
|
||||
updateCommand: function(aCommandId, aAddon) {
|
||||
if (typeof aAddon == "undefined")
|
||||
aAddon = this.currentViewObj.getSelectedAddon();
|
||||
var cmd = this.commands[aCommandId];
|
||||
var cmdElt = document.getElementById(aCommandId);
|
||||
cmdElt.setAttribute("disabled", !cmd.isEnabled(aAddon));
|
||||
if ("getTooltip" in cmd) {
|
||||
let tooltip = cmd.getTooltip(aAddon);
|
||||
if (tooltip)
|
||||
cmdElt.setAttribute("tooltiptext", tooltip);
|
||||
else
|
||||
cmdElt.removeAttribute("tooltiptext");
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -648,6 +713,11 @@ function isPending(aAddon, aAction) {
|
|||
return !!(aAddon.pendingOperations & action);
|
||||
}
|
||||
|
||||
function isInState(aInstall, aState) {
|
||||
var state = AddonManager["STATE_" + aState.toUpperCase()];
|
||||
return aInstall.state == state;
|
||||
}
|
||||
|
||||
|
||||
function createItem(aObj, aIsInstall, aRequiresRestart, aIsRemote) {
|
||||
let item = document.createElement("richlistitem");
|
||||
|
@ -807,6 +877,7 @@ var gCategories = {
|
|||
|
||||
if (item) {
|
||||
item.hidden = false;
|
||||
item.disabled = false;
|
||||
this.node.suppressOnSelect = true;
|
||||
this.node.selectedItem = item;
|
||||
this.node.suppressOnSelect = false;
|
||||
|
@ -1355,12 +1426,14 @@ var gDetailView = {
|
|||
|
||||
_notificationContainer: null,
|
||||
_notificationText: null,
|
||||
_autoUpdate: null,
|
||||
|
||||
initialize: function() {
|
||||
this.node = document.getElementById("detail-view");
|
||||
|
||||
this._notificationContainer = document.getElementById("detail-notification");
|
||||
this._notificationText = document.getElementById("detail-notification-text");
|
||||
this._autoUpdate = document.getElementById("detail-autoUpdate");
|
||||
|
||||
var self = this;
|
||||
var autoUpdate = document.getElementById("detail-autoUpdate");
|
||||
|
@ -1414,9 +1487,9 @@ var gDetailView = {
|
|||
desc.textContent = aAddon.fullDescription ? aAddon.fullDescription
|
||||
: aAddon.description;
|
||||
|
||||
document.getElementById("detail-autoUpdate").checked = aAddon.applyBackgroundUpdates;
|
||||
self._autoUpdate.checked = aAddon.applyBackgroundUpdates;
|
||||
var canUpdate = hasPermission(aAddon, "upgrade");
|
||||
document.getElementById("detail-autoUpdate").hidden = !canUpdate;
|
||||
self._autoUpdate.hidden = !canUpdate;
|
||||
document.getElementById("detail-findUpdates").hidden = !canUpdate;
|
||||
document.getElementById("detail-prefs").hidden = !aAddon.optionsURL;
|
||||
|
||||
|
@ -1504,6 +1577,277 @@ var gDetailView = {
|
|||
|
||||
onOperationCancelled: function() {
|
||||
this.updateState();
|
||||
},
|
||||
|
||||
onPropertyChanged: function(aProperties) {
|
||||
if (aProperties.indexOf("applyBackgroundUpdates") != -1) {
|
||||
this._autoUpdate.checked = this._addon.applyBackgroundUpdates;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
var gUpdatesView = {
|
||||
node: null,
|
||||
_listBox: null,
|
||||
_emptyNotice: null,
|
||||
_sorters: null,
|
||||
_updatePrefs: null,
|
||||
_backgroundUpdateCheck: null,
|
||||
_categoryItem: null,
|
||||
_numManualUpdaters: 0,
|
||||
|
||||
initialize: function() {
|
||||
this.node = document.getElementById("updates-view");
|
||||
this._listBox = document.getElementById("updates-list");
|
||||
this._emptyNotice = document.getElementById("updates-list-empty");
|
||||
this._sorters = document.getElementById("updates-sorters");
|
||||
this._sorters.handler = this;
|
||||
|
||||
this._backgroundUpdateCheck = document.getElementById("utils-backgroudUpdateCheck");
|
||||
this._categoryItem = gCategories.get("addons://updates/available");
|
||||
|
||||
this._updatePrefs = Services.prefs.getBranch("extensions.update.");
|
||||
this._updatePrefs.QueryInterface(Ci.nsIPrefBranch2);
|
||||
this._updatePrefs.addObserver("", this, false);
|
||||
this.updateBackgroundCheck();
|
||||
this.updateManualUpdatersCount(true);
|
||||
this.updateAvailableCount(true);
|
||||
|
||||
AddonManager.addAddonListener(this);
|
||||
AddonManager.addInstallListener(this);
|
||||
},
|
||||
|
||||
shutdown: function() {
|
||||
AddonManager.removeAddonListener(this);
|
||||
AddonManager.removeInstallListener(this);
|
||||
this._updatePrefs.removeObserver("", this);
|
||||
delete this._updatePrefs;
|
||||
},
|
||||
|
||||
show: function(aType, aRequest) {
|
||||
gHeader.setName(gStrings.ext.GetStringFromName("header-" + aType + "Updates"));
|
||||
|
||||
document.getElementById("empty-availableUpdates-msg").hidden = aType != "available";
|
||||
document.getElementById("empty-recentUpdates-msg").hidden = aType != "recent";
|
||||
this.showEmptyNotice(false);
|
||||
|
||||
while (this._listBox.itemCount > 0)
|
||||
this._listBox.removeItemAt(0);
|
||||
|
||||
if (aType == "recent")
|
||||
this._showRecentUpdates(aRequest);
|
||||
else
|
||||
this._showAvailableUpdates(false, aRequest);
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
// do nothing
|
||||
},
|
||||
|
||||
_showRecentUpdates: function(aRequest) {
|
||||
var self = this;
|
||||
AddonManager.getAllAddons(function(aAddonsList) {
|
||||
if (gViewController && aRequest != gViewController.currentViewRequest)
|
||||
return;
|
||||
|
||||
let threshold = Date.now() - UPDATES_RECENT_TIMESPAN;
|
||||
aAddonsList.forEach(function(aAddon) {
|
||||
if (!aAddon.updateDate || aAddon.updateDate.getTime() < threshold)
|
||||
return;
|
||||
|
||||
let item = createItem(aAddon);
|
||||
self._listBox.appendChild(item);
|
||||
});
|
||||
|
||||
if (self._listBox.itemCount > 0)
|
||||
self.onSortChanged(self._sorters.sortBy, self._sorters.ascending);
|
||||
else
|
||||
self.showEmptyNotice(true);
|
||||
|
||||
gViewController.notifyViewChanged();
|
||||
});
|
||||
},
|
||||
|
||||
_showAvailableUpdates: function(aIsRefresh, aRequest) {
|
||||
var self = this;
|
||||
AddonManager.getAllInstalls(function(aInstallsList) {
|
||||
if (!aIsRefresh && gViewController && aRequest != gViewController.currentViewRequest)
|
||||
return;
|
||||
|
||||
if (aIsRefresh) {
|
||||
while (self._listBox.itemCount > 0)
|
||||
self._listBox.removeItemAt(0);
|
||||
}
|
||||
|
||||
aInstallsList.forEach(function(aInstall) {
|
||||
if (!self.isManualUpdate(aInstall))
|
||||
return;
|
||||
|
||||
let item = createItem(aInstall.existingAddon);
|
||||
item.setAttribute("upgrade", true);
|
||||
self._listBox.appendChild(item);
|
||||
});
|
||||
|
||||
if (self._listBox.itemCount > 0)
|
||||
self.onSortChanged(self._sorters.sortBy, self._sorters.ascending);
|
||||
else
|
||||
self.showEmptyNotice(true);
|
||||
|
||||
// ensure badge count is in sync
|
||||
self._categoryItem.badgeCount = self._listBox.itemCount;
|
||||
|
||||
if (!aIsRefresh)
|
||||
gViewController.notifyViewChanged();
|
||||
});
|
||||
},
|
||||
|
||||
getSelectedAddon: function() {
|
||||
return null;
|
||||
},
|
||||
|
||||
showEmptyNotice: function(aShow) {
|
||||
this._emptyNotice.hidden = !aShow;
|
||||
},
|
||||
|
||||
isManualUpdate: function(aInstall, aOnlyAvailable) {
|
||||
var isManual = aInstall.existingAddon &&
|
||||
aInstall.existingAddon.applyBackgroundUpdates === false;
|
||||
if (isManual && aOnlyAvailable)
|
||||
return isInState(aInstall, "available");
|
||||
return isManual;
|
||||
},
|
||||
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aTopic == "nsPref:changed" && aData == "enabled")
|
||||
this.updateBackgroundCheck();
|
||||
},
|
||||
|
||||
updateBackgroundCheck: function() {
|
||||
let isEnabled = this._updatePrefs.getBoolPref("enabled");
|
||||
this._backgroundUpdateCheck.setAttribute("checked", isEnabled);
|
||||
},
|
||||
|
||||
maybeRefresh: function() {
|
||||
if (gViewController.currentViewId == "addons://updates/available") {
|
||||
this._showAvailableUpdates(true);
|
||||
} else {
|
||||
this.updateManualUpdatersCount();
|
||||
this.updateAvailableCount();
|
||||
}
|
||||
},
|
||||
|
||||
maybeShowCategory: function() {
|
||||
var hide = this._numManualUpdaters == 0;
|
||||
if (this._categoryItem.disabled != hide) {
|
||||
this._categoryItem.disabled = hide;
|
||||
var event = document.createEvent("Events");
|
||||
event.initEvent("CategoryVisible", true, true);
|
||||
this._categoryItem.dispatchEvent(event);
|
||||
}
|
||||
},
|
||||
|
||||
updateManualUpdatersCount: function(aInitializing) {
|
||||
if (aInitializing)
|
||||
gPendingInitializations++;
|
||||
var self = this;
|
||||
AddonManager.getAllAddons(function(aAddonList) {
|
||||
var manualUpdaters = aAddonList.filter(function(aAddon) {
|
||||
return aAddon.applyBackgroundUpdates === false;
|
||||
});
|
||||
self._numManualUpdaters = manualUpdaters.length;
|
||||
self.maybeShowCategory();
|
||||
if (aInitializing)
|
||||
notifyInitialized();
|
||||
});
|
||||
},
|
||||
|
||||
updateAvailableCount: function(aInitializing) {
|
||||
if (aInitializing)
|
||||
gPendingInitializations++;
|
||||
var self = this;
|
||||
AddonManager.getAllInstalls(function(aInstallsList) {
|
||||
var count = aInstallsList.filter(function(aInstall) {
|
||||
return self.isManualUpdate(aInstall, true);
|
||||
}).length;
|
||||
self._categoryItem.badgeCount = count;
|
||||
if (aInitializing)
|
||||
notifyInitialized();
|
||||
});
|
||||
},
|
||||
|
||||
getSelectedAddon: function() {
|
||||
var item = this._listBox.selectedItem;
|
||||
if (item)
|
||||
return item.mAddon;
|
||||
return null;
|
||||
},
|
||||
|
||||
getListItemForID: function(aId) {
|
||||
var listitem = this._listBox.firstChild;
|
||||
while (listitem) {
|
||||
if (listitem.mAddon.id == aId)
|
||||
return listitem;
|
||||
listitem = listitem.nextSibling;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
onSortChanged: function(aSortBy, aAscending) {
|
||||
var hints = aAscending ? "ascending" : "descending";
|
||||
if (INTEGER_FIELDS.indexOf(aSortBy) >= 0)
|
||||
hints += " integer";
|
||||
|
||||
var sortService = Cc["@mozilla.org/xul/xul-sort-service;1"].
|
||||
getService(Ci.nsIXULSortService);
|
||||
sortService.sort(this._listBox, aSortBy, hints);
|
||||
},
|
||||
|
||||
onNewInstall: function(aInstall) {
|
||||
if (!this.isManualUpdate(aInstall))
|
||||
return;
|
||||
this.maybeRefresh();
|
||||
},
|
||||
|
||||
onExternalInstall: function(aAddon) {
|
||||
if (aAddon.applyBackgroundUpdates === false) {
|
||||
this._numManualUpdaters++;
|
||||
this.maybeShowCategory();
|
||||
}
|
||||
},
|
||||
|
||||
onDownloadStarted: function(aInstall) {
|
||||
if (!this.isManualUpdate(aInstall))
|
||||
return;
|
||||
this.maybeRefresh();
|
||||
},
|
||||
|
||||
onInstallStarted: function(aInstall) {
|
||||
if (!this.isManualUpdate(aInstall))
|
||||
return;
|
||||
this.maybeRefresh();
|
||||
},
|
||||
|
||||
onInstallEnded: function(aAddon) {
|
||||
if (aAddon.applyBackgroundUpdates === false) {
|
||||
this._numManualUpdaters++;
|
||||
this.maybeShowCategory();
|
||||
}
|
||||
},
|
||||
|
||||
onApplyBackgroundUpdatesChanged: function(aAddon) {
|
||||
if (!("applyBackgroundUpdates" in aAddon))
|
||||
return;
|
||||
if (aAddon.applyBackgroundUpdates)
|
||||
this._numManualUpdaters--;
|
||||
else
|
||||
this._numManualUpdaters++;
|
||||
this.maybeShowCategory();
|
||||
},
|
||||
|
||||
onPropertyChanged: function(aAddon, aProperties) {
|
||||
if (aProperties.indexOf("applyBackgroundUpdates") != -1)
|
||||
this.onApplyBackgroundUpdatesChanged(aAddon);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -399,7 +399,13 @@
|
|||
return this.getAttribute("count");
|
||||
]]></getter>
|
||||
<setter><![CDATA[
|
||||
this.setAttribute("count", aCount);
|
||||
if (this.getAttribute("count") == val)
|
||||
return;
|
||||
|
||||
this.setAttribute("count", val);
|
||||
var event = document.createEvent("Events");
|
||||
event.initEvent("CategoryBadgeUpdated", true, true);
|
||||
this.dispatchEvent(event);
|
||||
]]></setter>
|
||||
</property>
|
||||
</implementation>
|
||||
|
@ -736,7 +742,7 @@
|
|||
</binding>
|
||||
|
||||
|
||||
<!-- Addon - generic - A normal addon item -->
|
||||
<!-- Addon - generic - A normal addon item, or an update to one -->
|
||||
<binding id="addon-generic"
|
||||
extends="chrome://mozapps/content/extensions/extensions.xml#addon-base">
|
||||
<content>
|
||||
|
@ -744,14 +750,30 @@
|
|||
<xul:image anonid="icon" class="icon"/>
|
||||
<xul:spacer flex="1"/>
|
||||
</xul:vbox>
|
||||
<xul:vbox flex="1" class="fade">
|
||||
<xul:vbox flex="1" class="basicinfo-container fade">
|
||||
<xul:hbox class="name-container">
|
||||
<xul:label anonid="name" class="name" xbl:inherits="value=name"/>
|
||||
<xul:label anonid="version" class="version"/>
|
||||
<xul:label class="disabled-postfix" value="&addon.disabled.postfix;"/>
|
||||
<xul:label class="update-postfix" value="&addon.update.postfix;"/>
|
||||
</xul:hbox>
|
||||
<xul:label anonid="creator" class="creator"/>
|
||||
<xul:description anonid="description" class="description" flex="1"/>
|
||||
<xul:vbox anonid="relnotes-container" class="relnotes-container">
|
||||
<xul:label class="relnotes-header" value="&addon.releaseNotes.label;"/>
|
||||
<xul:label anonid="relnotes-loading" value="&addon.loadingReleaseNotes.label;"/>
|
||||
<xul:label anonid="relnotes-error" hidden="true"
|
||||
value="&addon.errorLoadingReleaseNotes.label;"/>
|
||||
<xul:vbox anonid="relnotes"/>
|
||||
</xul:vbox>
|
||||
<xul:button anonid="relnotes-toggle" class="relnotes-toggle"
|
||||
hidden="true" label="&cmd.showReleaseNotes.label;"
|
||||
tooltiptext="&cmd.showReleaseNotes.tooltip;"
|
||||
showlabel="&cmd.showReleaseNotes.label;"
|
||||
showtooltip="&cmd.showReleaseNotes.tooltip;"
|
||||
hidelabel="&cmd.hideReleaseNotes.label;"
|
||||
hidetooltip="&cmd.hideReleaseNotes.tooltip;"
|
||||
oncommand="document.getBindingParent(this).toggleReleaseNotes();"/>
|
||||
</xul:vbox>
|
||||
<xul:vbox align="end">
|
||||
<xul:vbox class="details-container fade">
|
||||
|
@ -803,6 +825,13 @@
|
|||
<xul:image class="spinner"/>
|
||||
<xul:label value="&addon.checkingForUpdates.label;"/>
|
||||
</xul:hbox>
|
||||
<xul:hbox anonid="update-available" hidden="true">
|
||||
<xul:label value="An update is available"/>
|
||||
<xul:button anonid="update-btn" class="addon-control"
|
||||
label="&addon.updateNow.label;"
|
||||
tooltiptext="&addon.updateNow.tooltip;"
|
||||
oncommand="document.getBindingParent(this).upgrade();"/>
|
||||
</xul:hbox>
|
||||
<xul:hbox anonid="install-status" class="install-status"
|
||||
hidden="true"/>
|
||||
</xul:hbox>
|
||||
|
@ -853,6 +882,20 @@
|
|||
if (numExtraDetails == 0)
|
||||
this._toggleMore.hidden = true;
|
||||
|
||||
if (!this.mAddon.applyBackgroundUpdates) {
|
||||
var self = this;
|
||||
AddonManager.getAllInstalls(function(aInstallsList) {
|
||||
for (let i = 0; i < aInstallsList.length; i++) {
|
||||
let install = aInstallsList[i];
|
||||
if (install.existingAddon &&
|
||||
install.existingAddon.id == self.mAddon.id &&
|
||||
install.state == AddonManager.STATE_AVAILABLE) {
|
||||
self.onNewInstall(install);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
gEventManager.registerAddonListener(this, this.mAddon.id);
|
||||
]]></constructor>
|
||||
|
||||
|
@ -918,6 +961,10 @@
|
|||
document.getAnonymousElementByAttribute(this, "anonid",
|
||||
"remove-btn");
|
||||
</field>
|
||||
<field name="_updateBtn">
|
||||
document.getAnonymousElementByAttribute(this, "anonid",
|
||||
"update-btn");
|
||||
</field>
|
||||
<field name="_controlContainer">
|
||||
document.getAnonymousElementByAttribute(this, "anonid",
|
||||
"control-container");
|
||||
|
@ -930,6 +977,31 @@
|
|||
document.getAnonymousElementByAttribute(this, "anonid",
|
||||
"checking-update");
|
||||
</field>
|
||||
<field name="_updateAvailable">
|
||||
document.getAnonymousElementByAttribute(this, "anonid",
|
||||
"update-available");
|
||||
</field>
|
||||
<field name="_relNotesLoaded">false</field>
|
||||
<field name="_relNotesToggle">
|
||||
document.getAnonymousElementByAttribute(this, "anonid",
|
||||
"relnotes-toggle");
|
||||
</field>
|
||||
<field name="_relNotesLoading">
|
||||
document.getAnonymousElementByAttribute(this, "anonid",
|
||||
"relnotes-loading");
|
||||
</field>
|
||||
<field name="_relNotesError">
|
||||
document.getAnonymousElementByAttribute(this, "anonid",
|
||||
"relnotes-error");
|
||||
</field>
|
||||
<field name="_relNotesContainer">
|
||||
document.getAnonymousElementByAttribute(this, "anonid",
|
||||
"relnotes-container");
|
||||
</field>
|
||||
<field name="_relNotes">
|
||||
document.getAnonymousElementByAttribute(this, "anonid",
|
||||
"relnotes");
|
||||
</field>
|
||||
|
||||
<property name="userDisabled">
|
||||
<getter><![CDATA[
|
||||
|
@ -972,11 +1044,17 @@
|
|||
<method name="_showStatus">
|
||||
<parameter name="aType"/>
|
||||
<body><![CDATA[
|
||||
this._controlContainer.hidden = aType != "none";
|
||||
this._controlContainer.hidden = aType != "none" &&
|
||||
!(aType == "update-available" && !this.hasAttribute("upgrade"));
|
||||
|
||||
this._installStatus.hidden = aType != "progress";
|
||||
if (aType == "progress")
|
||||
this._installStatus.refreshState();
|
||||
this._checkingUpdate.hidden = aType != "checking-update";
|
||||
this._updateAvailable.hidden = aType != "update-available";
|
||||
this._relNotesToggle.hidden = !(this.mManualUpdate ?
|
||||
this.mManualUpdate.releaseNotesURI :
|
||||
this.mAddon.releaseNotesURI);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
|
@ -1064,6 +1142,128 @@
|
|||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="_updateUpgradeInfo">
|
||||
<body><![CDATA[
|
||||
this._version.value = this.mManualUpdate.version;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="_fetchReleaseNotes">
|
||||
<parameter name="aURI"/>
|
||||
<body><![CDATA[
|
||||
var self = this;
|
||||
if (!aURI || this._relNotesLoaded) {
|
||||
sendToggleEvent();
|
||||
return;
|
||||
}
|
||||
|
||||
var relNotesData = null, transformData = null;
|
||||
|
||||
this._relNotesLoaded = true;
|
||||
this._relNotesLoading.hidden = false;
|
||||
this._relNotesError.hidden = true;
|
||||
|
||||
function sendToggleEvent() {
|
||||
var event = document.createEvent("Events");
|
||||
event.initEvent("RelNotesToggle", true, true);
|
||||
self.dispatchEvent(event);
|
||||
}
|
||||
|
||||
function showRelNotes() {
|
||||
if (!relNotesData || !transformData)
|
||||
return;
|
||||
|
||||
self._relNotesLoading.hidden = true;
|
||||
|
||||
var processor = Components.classes["@mozilla.org/document-transformer;1?type=xslt"]
|
||||
.createInstance(Components.interfaces.nsIXSLTProcessor);
|
||||
processor.flags |= Components.interfaces.nsIXSLTProcessorPrivate.DISABLE_ALL_LOADS;
|
||||
|
||||
processor.importStylesheet(transformData);
|
||||
var fragment = processor.transformToFragment(relNotesData, document);
|
||||
self._relNotes.appendChild(fragment);
|
||||
if (self.hasAttribute("show-relnotes")) {
|
||||
var container = self._relNotesContainer;
|
||||
container.style.height = container.scrollHeight + "px";
|
||||
}
|
||||
sendToggleEvent();
|
||||
}
|
||||
|
||||
function handleError() {
|
||||
dataReq.abort();
|
||||
styleReq.abort();
|
||||
self._relNotesLoading.hidden = true;
|
||||
self._relNotesError.hidden = false;
|
||||
self._relNotesLoaded = false; // allow loading to be re-tried
|
||||
sendToggleEvent();
|
||||
}
|
||||
|
||||
function handleResponse(aEvent) {
|
||||
var req = aEvent.target;
|
||||
if (req.responseXML &&
|
||||
req.responseXML.documentElement.namespaceURI != XMLURI_PARSE_ERROR) {
|
||||
if (req == dataReq)
|
||||
relNotesData = req.responseXML;
|
||||
else
|
||||
transformData = req.responseXML;
|
||||
showRelNotes();
|
||||
} else {
|
||||
handleError();
|
||||
}
|
||||
}
|
||||
|
||||
var dataReq = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
|
||||
.createInstance(Components.interfaces.nsIXMLHttpRequest);
|
||||
dataReq.open("GET", aURI.spec, true);
|
||||
dataReq.addEventListener("load", handleResponse, false);
|
||||
dataReq.addEventListener("error", handleError, false);
|
||||
dataReq.send(null);
|
||||
|
||||
var styleReq = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
|
||||
.createInstance(Components.interfaces.nsIXMLHttpRequest);
|
||||
styleReq.open("GET", UPDATES_RELEASENOTES_TRANSFORMFILE, true);
|
||||
styleReq.addEventListener("load", handleResponse, false);
|
||||
styleReq.addEventListener("error", handleError, false);
|
||||
styleReq.send(null);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="toggleReleaseNotes">
|
||||
<body><![CDATA[
|
||||
if (this.hasAttribute("show-relnotes")) {
|
||||
this._relNotesContainer.style.height = "0px";
|
||||
this.removeAttribute("show-relnotes");
|
||||
this._relNotesToggle.setAttribute(
|
||||
"label",
|
||||
this._relNotesToggle.getAttribute("showlabel")
|
||||
);
|
||||
this._relNotesToggle.setAttribute(
|
||||
"tooltiptext",
|
||||
this._relNotesToggle.getAttribute("showtooltip")
|
||||
);
|
||||
var event = document.createEvent("Events");
|
||||
event.initEvent("RelNotesToggle", true, true);
|
||||
this.dispatchEvent(event);
|
||||
} else {
|
||||
this._relNotesContainer.style.height = this._relNotesContainer.scrollHeight +
|
||||
"px";
|
||||
this.setAttribute("show-relnotes", true);
|
||||
this._relNotesToggle.setAttribute(
|
||||
"label",
|
||||
this._relNotesToggle.getAttribute("hidelabel")
|
||||
);
|
||||
this._relNotesToggle.setAttribute(
|
||||
"tooltiptext",
|
||||
this._relNotesToggle.getAttribute("hidetooltip")
|
||||
);
|
||||
var uri = this.mManualUpdate ?
|
||||
this.mManualUpdate.releaseNotesURI :
|
||||
this.mAddon.releaseNotesURI;
|
||||
this._fetchReleaseNotes(uri);
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="uninstall">
|
||||
<body><![CDATA[
|
||||
// If uninstalling does not require a restart then just disable it
|
||||
|
@ -1086,6 +1286,14 @@
|
|||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="upgrade">
|
||||
<body><![CDATA[
|
||||
var install = this.mManualUpdate;
|
||||
delete this.mManualUpdate;
|
||||
install.install();
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="showInDetailView">
|
||||
<body><![CDATA[
|
||||
gViewController.loadView("addons://detail/" +
|
||||
|
@ -1150,6 +1358,25 @@
|
|||
</method>
|
||||
|
||||
<method name="onNewInstall">
|
||||
<parameter name="aInstall"/>
|
||||
<body><![CDATA[
|
||||
if (!this.mAddon.applyBackgroundUpdates) {
|
||||
this.mManualUpdate = aInstall;
|
||||
this._showStatus("update-available");
|
||||
this._updateUpgradeInfo();
|
||||
}
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="onDownloadStarted">
|
||||
<parameter name="aInstall"/>
|
||||
<body><![CDATA[
|
||||
this._showStatus("progress");
|
||||
this._installStatus.initWithInstall(aInstall);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<method name="onInstallStarted">
|
||||
<parameter name="aInstall"/>
|
||||
<body><![CDATA[
|
||||
this._showStatus("progress");
|
||||
|
@ -1291,7 +1518,8 @@
|
|||
<body><![CDATA[
|
||||
this.mAddon = this.mAddon || this.mInstall.addon;
|
||||
if (this.mAddon) {
|
||||
this._icon.src = this.mAddon.iconURL || this.mInstall.iconURL;
|
||||
this._icon.src = this.mAddon.iconURL ||
|
||||
(this.mInstall ? this.mInstall.iconURL : "");
|
||||
this._name.value = this.mAddon.name;
|
||||
} else {
|
||||
this._icon.src = this.mInstall.iconURL;
|
||||
|
|
|
@ -80,6 +80,9 @@
|
|||
<command id="cmd_findAllUpdates"/>
|
||||
<command id="cmd_restartApp"/>
|
||||
<command id="cmd_goToDiscoverPane"/>
|
||||
<command id="cmd_goToRecentUpdates"/>
|
||||
<command id="cmd_goToAvailableUpdates"/>
|
||||
<command id="cmd_toggleBackgroundUpdateCheck"/>
|
||||
</commandset>
|
||||
|
||||
<!-- view commands - these act on the selected addon -->
|
||||
|
@ -125,6 +128,12 @@
|
|||
<richlistitem id="category-plugins" value="addons://list/plugin"
|
||||
class="category"
|
||||
name="&view.plugins.label;"/>
|
||||
<richlistitem id="category-availableUpdates" value="addons://updates/available"
|
||||
class="category"
|
||||
name="&view.availableUpdates.label;" disabled="true"/>
|
||||
<richlistitem id="category-recentUpdates" value="addons://updates/recent"
|
||||
class="category"
|
||||
name="&view.recentUpdates.label;" disabled="true"/>
|
||||
</richlistbox>
|
||||
|
||||
</vbox>
|
||||
|
@ -143,9 +152,9 @@
|
|||
<image class="spinner"/>
|
||||
<label id="updates-noneFound" hidden="true"
|
||||
value="&updates.noneFound.label;"/>
|
||||
<button id="updates-checkNow" class="button-link"
|
||||
label="&updates.updateNow.label;"
|
||||
command="cmd_findAllUpdates"/>
|
||||
<button id="updates-manualUpdatesFound" class="button-link"
|
||||
hidden="true" label="&updates.manualUpdatesFound.label;"
|
||||
command="cmd_goToAvailableUpdates"/>
|
||||
<label id="updates-progress" hidden="true"
|
||||
value="&updates.updating.label;"/>
|
||||
<label id="updates-installed" hidden="true"
|
||||
|
@ -156,6 +165,24 @@
|
|||
label="&updates.restart.label;"
|
||||
command="cmd_restartApp"/>
|
||||
</hbox>
|
||||
<button id="header-utils-btn" type="menu">
|
||||
<menupopup id="utils-menu">
|
||||
<menuitem id="utils-updateNow"
|
||||
label="&updates.updateAddonsNow.label;"
|
||||
accesskey="&updates.updateAddonsNow.accesskey;"
|
||||
command="cmd_findAllUpdates"/>
|
||||
<menuitem id="utils-viewUpdates"
|
||||
label="&updates.viewUpdates.label;"
|
||||
accesskey="&updates.viewUpdates.accesskey;"
|
||||
command="cmd_goToRecentUpdates"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="utils-backgroudUpdateCheck"
|
||||
label="&updates.backgroudUpdateCheck.label;"
|
||||
accesskey="&updates.backgroudUpdateCheck.accesskey;"
|
||||
type="checkbox" autocheck="false"
|
||||
command="cmd_toggleBackgroundUpdateCheck"/>
|
||||
</menupopup>
|
||||
</button>
|
||||
<textbox id="header-search" type="search" searchbutton="true"
|
||||
placeholder="&search.placeholder;"/>
|
||||
<image id="header-searching"/>
|
||||
|
@ -216,6 +243,27 @@
|
|||
<richlistbox id="addon-list" class="list" flex="1"/>
|
||||
</vbox>
|
||||
|
||||
<!-- updates view -->
|
||||
<vbox id="updates-view" flex="1" class="view-pane">
|
||||
<hbox class="view-header" pack="end">
|
||||
<hbox id="updates-sorters" class="sort-controls" sortby="dateUpdated"
|
||||
ascending="false"/>
|
||||
</hbox>
|
||||
<vbox id="updates-list-empty" class="empty-list-notice"
|
||||
flex="1" hidden="true">
|
||||
<spacer flex="1"/>
|
||||
<label id="empty-availableUpdates-msg" value="&listEmpty.availableUpdates.label;"/>
|
||||
<label id="empty-recentUpdates-msg" value="&listEmpty.recentUpdates.label;"/>
|
||||
<button label="&listEmpty.findUpdates.label;" class="addon-control"
|
||||
command="cmd_findAllUpdates"/>
|
||||
<spacer flex="3"/>
|
||||
</vbox>
|
||||
<hbox id="update-all-container" hidden="true">
|
||||
<button label="Update these add-ons" class="addon-control"/>
|
||||
</hbox>
|
||||
<richlistbox id="updates-list" class="list" flex="1"/>
|
||||
</vbox>
|
||||
|
||||
<!-- detail view -->
|
||||
<hbox id="detail-view" flex="1" class="view-pane">
|
||||
<spacer flex="1"/>
|
||||
|
|
|
@ -61,7 +61,11 @@ _TEST_FILES = \
|
|||
browser_updatessl.js \
|
||||
browser_updatessl.rdf \
|
||||
browser_installssl.js \
|
||||
browser_backgroundupdate_menuitem.js \
|
||||
browser_recentupdates.js \
|
||||
browser_manualupdates.js \
|
||||
redirect.sjs \
|
||||
releaseNotes.xhtml \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// Tests the menuitem for the background update check
|
||||
|
||||
var gManagerWindow;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
open_manager(null, function(aWindow) {
|
||||
gManagerWindow = aWindow;
|
||||
run_next_test();
|
||||
});
|
||||
}
|
||||
|
||||
function end_test() {
|
||||
close_manager(gManagerWindow, function() {
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
||||
add_test(function() {
|
||||
var menuitem = gManagerWindow.document.getElementById("utils-backgroudUpdateCheck");
|
||||
|
||||
function is_backgroundcheck_insync(aExpected) {
|
||||
var enabled = Services.prefs.getBoolPref("extensions.update.enabled");
|
||||
var checked = menuitem.getAttribute("checked") == "true";
|
||||
is(enabled, aExpected, "Background check should be " + (aExpected ? "enabled" : "disabled"));
|
||||
is(checked, enabled, "Background check menuitem should be in sync with preference");
|
||||
}
|
||||
|
||||
is_backgroundcheck_insync(true);
|
||||
info("Setting background check pref to true");
|
||||
Services.prefs.setBoolPref("extensions.update.enabled", false);
|
||||
is_backgroundcheck_insync(false);
|
||||
info("Setting background check pref to false");
|
||||
Services.prefs.setBoolPref("extensions.update.enabled", true);
|
||||
is_backgroundcheck_insync(true);
|
||||
|
||||
info("Clicking on background check menuitem - setting to unchecked");
|
||||
var utilsBtn = gManagerWindow.document.getElementById("header-utils-btn");
|
||||
utilsBtn.addEventListener("popupshown", function() {
|
||||
EventUtils.synthesizeMouse(menuitem, 2, 2, { }, gManagerWindow);
|
||||
executeSoon(function() {
|
||||
is_backgroundcheck_insync(false);
|
||||
info("Manually invoking command to toggle background update check on");
|
||||
gManagerWindow.gViewController.doCommand("cmd_toggleBackgroundUpdateCheck");
|
||||
is_backgroundcheck_insync(true);
|
||||
run_next_test();
|
||||
});
|
||||
}, false);
|
||||
EventUtils.synthesizeMouse(utilsBtn, 2, 2, { }, gManagerWindow);
|
||||
});
|
|
@ -0,0 +1,165 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// Tests manual updates, including the Available Updates pane
|
||||
|
||||
var gProvider;
|
||||
var gManagerWindow;
|
||||
var gCategoryUtilities;
|
||||
var gAvailableCategory;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
gProvider = new MockProvider();
|
||||
|
||||
gProvider.createAddons([{
|
||||
id: "addon1@tests.mozilla.org",
|
||||
name: "auto updating addon",
|
||||
version: "1.0",
|
||||
applyBackgroundUpdates: true
|
||||
}]);
|
||||
|
||||
open_manager(null, function(aWindow) {
|
||||
gManagerWindow = aWindow;
|
||||
gCategoryUtilities = new CategoryUtilities(gManagerWindow);
|
||||
run_next_test();
|
||||
});
|
||||
}
|
||||
|
||||
function end_test() {
|
||||
close_manager(gManagerWindow, function() {
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
add_test(function() {
|
||||
gAvailableCategory = gManagerWindow.gCategories.get("addons://updates/available");
|
||||
is(gCategoryUtilities.isVisible(gAvailableCategory), false, "Available Updates category should initially be hidden");
|
||||
|
||||
gProvider.createAddons([{
|
||||
id: "addon2@tests.mozilla.org",
|
||||
name: "manually updating addon",
|
||||
version: "1.0",
|
||||
applyBackgroundUpdates: false
|
||||
}]);
|
||||
|
||||
is(gCategoryUtilities.isVisible(gAvailableCategory), true, "Available Updates category should now be visible");
|
||||
|
||||
gAvailableCategory.addEventListener("CategoryVisible", function() {
|
||||
gAvailableCategory.removeEventListener("CategoryVisible", arguments.callee, false);
|
||||
is(gCategoryUtilities.isVisible(gAvailableCategory), false, "Available Updates category should not be visible");
|
||||
gAvailableCategory.addEventListener("CategoryVisible", function() {
|
||||
gAvailableCategory.removeEventListener("CategoryVisible", arguments.callee, false);
|
||||
is(gCategoryUtilities.isVisible(gAvailableCategory), true, "Available Updates category should be visible");
|
||||
run_next_test();
|
||||
}, false);
|
||||
gProvider.addons[1].applyBackgroundUpdates = false;
|
||||
}, false);
|
||||
gProvider.addons[1].applyBackgroundUpdates = true;
|
||||
});
|
||||
|
||||
|
||||
add_test(function() {
|
||||
gAvailableCategory.addEventListener("CategoryBadgeUpdated", function() {
|
||||
gAvailableCategory.removeEventListener("CategoryBadgeUpdated", arguments.callee, false);
|
||||
is(gAvailableCategory.badgeCount, 1, "Badge for Available Updates should now be 1");
|
||||
run_next_test();
|
||||
}, false);
|
||||
|
||||
gProvider.createInstalls([{
|
||||
name: "manually updating addon (new and improved!)",
|
||||
existingAddon: gProvider.addons[1],
|
||||
version: "1.1",
|
||||
releaseNotesURI: Services.io.newURI(TESTROOT + "thereIsNoFileHere.xhtml", null, null)
|
||||
}]);
|
||||
});
|
||||
|
||||
|
||||
add_test(function() {
|
||||
wait_for_view_load(gManagerWindow, function() {
|
||||
is(gManagerWindow.document.getElementById("categories").selectedItem.value, "addons://updates/available", "Available Updates category should now be selected");
|
||||
is(gManagerWindow.gViewController.currentViewId, "addons://updates/available", "Available Updates view should be the current view");
|
||||
run_next_test();
|
||||
}, true);
|
||||
EventUtils.synthesizeMouse(gAvailableCategory, 0, 0, { }, gManagerWindow);
|
||||
});
|
||||
|
||||
|
||||
add_test(function() {
|
||||
var list = gManagerWindow.document.getElementById("updates-list");
|
||||
is(list.itemCount, 1, "Should be 1 available update listed");
|
||||
var item = list.firstChild;
|
||||
is(item.mAddon.id, "addon2@tests.mozilla.org", "Update item should be for the manually updating addon");
|
||||
setTimeout(function() {
|
||||
// this updates asynchronously
|
||||
is(item._version.value, "1.1", "Update item should have version number of the update");
|
||||
var postfix = gManagerWindow.document.getAnonymousElementByAttribute(item, "class", "update-postfix");
|
||||
is_element_visible(gManagerWindow, postfix, true, "'Update' postfix should be visible");
|
||||
is_element_visible(gManagerWindow, item._updateAvailable, true, "");
|
||||
is_element_visible(gManagerWindow, item._relNotesToggle, true, "Release notes toggle should be visible");
|
||||
|
||||
info("Opening release notes");
|
||||
item.addEventListener("RelNotesToggle", function() {
|
||||
item.removeEventListener("RelNotesToggle", arguments.callee, false);
|
||||
info("Release notes now open");
|
||||
|
||||
is_element_visible(gManagerWindow, item._relNotesLoading, false, "Release notes loading message should be hidden");
|
||||
is_element_visible(gManagerWindow, item._relNotesError, true, "Release notes error message should be visible");
|
||||
is(item._relNotes.childElementCount, 0, "Release notes should be empty");
|
||||
|
||||
info("Closing release notes");
|
||||
item.addEventListener("RelNotesToggle", function() {
|
||||
item.removeEventListener("RelNotesToggle", arguments.callee, false);
|
||||
info("Release notes now closed");
|
||||
info("Setting Release notes URI to something that should load");
|
||||
gProvider.installs[0].releaseNotesURI = Services.io.newURI(TESTROOT + "releaseNotes.xhtml", null, null)
|
||||
|
||||
info("Re-opening release notes");
|
||||
item.addEventListener("RelNotesToggle", function() {
|
||||
item.removeEventListener("RelNotesToggle", arguments.callee, false);
|
||||
info("Release notes now open");
|
||||
|
||||
is_element_visible(gManagerWindow, item._relNotesLoading, false, "Release notes loading message should be hidden");
|
||||
is_element_visible(gManagerWindow, item._relNotesError, false, "Release notes error message should be hidden");
|
||||
isnot(item._relNotes.childElementCount, 0, "Release notes should have been inserted into container");
|
||||
run_next_test();
|
||||
|
||||
}, false);
|
||||
EventUtils.synthesizeMouse(item._relNotesToggle, 2, 2, { }, gManagerWindow);
|
||||
is_element_visible(gManagerWindow, item._relNotesLoading, true, "Release notes loading message should be visible");
|
||||
|
||||
}, false);
|
||||
EventUtils.synthesizeMouse(item._relNotesToggle, 2, 2, { }, gManagerWindow);
|
||||
|
||||
}, false);
|
||||
EventUtils.synthesizeMouse(item._relNotesToggle, 2, 2, { }, gManagerWindow);
|
||||
is_element_visible(gManagerWindow, item._relNotesLoading, true, "Release notes loading message should be visible");
|
||||
}, 100);
|
||||
});
|
||||
|
||||
|
||||
add_test(function() {
|
||||
var list = gManagerWindow.document.getElementById("updates-list");
|
||||
var item = list.firstChild;
|
||||
var updateBtn = item._updateBtn;
|
||||
is_element_visible(gManagerWindow, updateBtn, true, "Update button should be visible");
|
||||
|
||||
var install = gProvider.installs[0];
|
||||
var listener = {
|
||||
onInstallStarted: function() {
|
||||
info("Install started");
|
||||
is_element_visible(gManagerWindow, item._installStatus, true, "Install progress widget should be visible");
|
||||
},
|
||||
onInstallEnded: function() {
|
||||
install.removeTestListener(this);
|
||||
info("install ended");
|
||||
is_element_visible(gManagerWindow, item._installStatus, false, "Install progress widget should be hidden");
|
||||
run_next_test();
|
||||
}
|
||||
};
|
||||
install.addTestListener(listener);
|
||||
EventUtils.synthesizeMouse(updateBtn, 2, 2, { }, gManagerWindow);
|
||||
});
|
|
@ -0,0 +1,86 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
// Tests the recent updates pane
|
||||
|
||||
var gProvider;
|
||||
var gManagerWindow;
|
||||
var gCategoryUtilities;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
gProvider = new MockProvider();
|
||||
|
||||
gProvider.createAddons([{
|
||||
id: "addon1@tests.mozilla.org",
|
||||
name: "updated 6 hours ago",
|
||||
version: "1.0",
|
||||
updateDate: new Date(Date.now() - (1000 * 60 * 60 * 6)),
|
||||
releaseNotesURI: Services.io.newURI(TESTROOT + "releaseNotes.xhtml", null, null)
|
||||
}, {
|
||||
id: "addon2@tests.mozilla.org",
|
||||
name: "updated 5 seconds ago",
|
||||
version: "1.0",
|
||||
updateDate: new Date(Date.now() - (1000 * 5))
|
||||
}, {
|
||||
id: "addon3@tests.mozilla.org",
|
||||
name: "updated 1 month ago",
|
||||
version: "1.0",
|
||||
updateDate: new Date(Date.now() - (1000 * 60 * 60 * 25 * 30))
|
||||
}]);
|
||||
|
||||
open_manager(null, function(aWindow) {
|
||||
gManagerWindow = aWindow;
|
||||
gCategoryUtilities = new CategoryUtilities(gManagerWindow);
|
||||
run_next_test();
|
||||
});
|
||||
}
|
||||
|
||||
function end_test() {
|
||||
close_manager(gManagerWindow, function() {
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
add_test(function() {
|
||||
info("Checking menuitem for Recent Updates opens that pane");
|
||||
var recentCat = gManagerWindow.gCategories.get("addons://updates/recent");
|
||||
is(gCategoryUtilities.isVisible(recentCat), false, "Recent Updates category should initially be hidden");
|
||||
|
||||
var utilsBtn = gManagerWindow.document.getElementById("header-utils-btn");
|
||||
utilsBtn.addEventListener("popupshown", function() {
|
||||
wait_for_view_load(gManagerWindow, function() {
|
||||
is(gCategoryUtilities.isVisible(recentCat), true, "Recent Updates category should now be visible");
|
||||
is(gManagerWindow.document.getElementById("categories").selectedItem.value, "addons://updates/recent", "Recent Updates category should now be selected");
|
||||
is(gManagerWindow.gViewController.currentViewId, "addons://updates/recent", "Recent Updates view should be the current view");
|
||||
run_next_test();
|
||||
}, true);
|
||||
var menuitem = gManagerWindow.document.getElementById("utils-viewUpdates");
|
||||
EventUtils.synthesizeMouse(menuitem, 2, 2, { }, gManagerWindow);
|
||||
}, false);
|
||||
EventUtils.synthesizeMouse(utilsBtn, 2, 2, { }, gManagerWindow);
|
||||
});
|
||||
|
||||
|
||||
add_test(function() {
|
||||
var updatesList = gManagerWindow.document.getElementById("updates-list");
|
||||
var items = updatesList.getElementsByTagName("richlistitem");
|
||||
var possible = ["addon1@tests.mozilla.org", "addon2@tests.mozilla.org", "addon2@tests.mozilla.org"];
|
||||
var expected = ["addon2@tests.mozilla.org", "addon1@tests.mozilla.org"];
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
let item = items[i];
|
||||
let itemId = item.mAddon.id;
|
||||
if (possible.indexOf(itemId) == -1)
|
||||
continue; // skip over any other addons, such as shipped addons that would update on every build
|
||||
isnot(expected.length, 0, "Should be expecting more items");
|
||||
is(itemId, expected.shift(), "Should get expected item based on recenty of update");
|
||||
if (itemId == "addon1@tests.mozilla.org")
|
||||
is_element_visible(gManagerWindow, item._relNotesToggle, true, "Release notes toggle should be visible for addon with release notes");
|
||||
else
|
||||
is_element_visible(gManagerWindow, item._relNotesToggle, false, "Release notes toggle should be hidden for addon with no release notes");
|
||||
}
|
||||
run_next_test();
|
||||
});
|
|
@ -48,8 +48,8 @@ function get_addon_file_url(aFilename) {
|
|||
return fileurl.QueryInterface(Ci.nsIFileURL);
|
||||
}
|
||||
|
||||
function wait_for_view_load(aManagerWindow, aCallback) {
|
||||
if (!aManagerWindow.gViewController.isLoading) {
|
||||
function wait_for_view_load(aManagerWindow, aCallback, aForceWait) {
|
||||
if (!aForceWait && !aManagerWindow.gViewController.isLoading) {
|
||||
aCallback(aManagerWindow);
|
||||
return;
|
||||
}
|
||||
|
@ -114,6 +114,13 @@ function restart_manager(aManagerWindow, aView, aCallback) {
|
|||
close_manager(aManagerWindow, function() { open_manager(aView, aCallback); });
|
||||
}
|
||||
|
||||
function is_element_visible(aWindow, aElement, aExpected, aMsg) {
|
||||
isnot(aElement, null, "Element should not be null, when checking visibility");
|
||||
var style = aWindow.getComputedStyle(aElement, "");
|
||||
var visible = style.display != "none" && style.visibility == "visible";
|
||||
is(visible, aExpected, aMsg);
|
||||
}
|
||||
|
||||
function CategoryUtilities(aManagerWindow) {
|
||||
this.window = aManagerWindow;
|
||||
|
||||
|
@ -346,6 +353,10 @@ MockProvider.prototype = {
|
|||
for (var prop in aAddonProp) {
|
||||
if (prop == "id")
|
||||
continue;
|
||||
if (prop == "applyBackgroundUpdates") {
|
||||
addon._applyBackgroundUpdates = aAddonProp[prop];
|
||||
continue;
|
||||
}
|
||||
addon[prop] = aAddonProp[prop];
|
||||
}
|
||||
this.addAddon(addon);
|
||||
|
@ -612,6 +623,7 @@ function MockAddon(aId, aName, aType, aOperationsRequiringRestart) {
|
|||
this.blocklistState = 0;
|
||||
this.appDisabled = false;
|
||||
this._userDisabled = false;
|
||||
this._applyBackgroundUpdates = true;
|
||||
this.scope = AddonManager.SCOPE_PROFILE;
|
||||
this.isActive = true;
|
||||
this.creator = "";
|
||||
|
@ -647,6 +659,15 @@ MockAddon.prototype = {
|
|||
|
||||
return val;
|
||||
},
|
||||
|
||||
get applyBackgroundUpdates() {
|
||||
return this._applyBackgroundUpdates;
|
||||
},
|
||||
|
||||
set applyBackgroundUpdates(val) {
|
||||
this._applyBackgroundUpdates = val;
|
||||
AddonManagerPrivate.callAddonListeners("onPropertyChanged", this, ["applyBackgroundUpdates"]);
|
||||
},
|
||||
|
||||
isCompatibleWith: function(aAppVersion, aPlatformVersion) {
|
||||
return true;
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html lang="en-US" dir="ltr" xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<title></title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>OMG, an update!!!!</h1>
|
||||
<ul>
|
||||
<li>Made everything more awesome</li>
|
||||
<li>Added hot sauce</li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
|
@ -130,6 +130,12 @@
|
|||
#category-plugins > .category-icon {
|
||||
list-style-image: url("chrome://mozapps/skin/extensions/category-plugins.png");
|
||||
}
|
||||
#category-availableUpdates > .category-icon {
|
||||
list-style-image: url("chrome://mozapps/skin/extensions/category-available.png");
|
||||
}
|
||||
#category-recentUpdates > .category-icon {
|
||||
list-style-image: url("chrome://mozapps/skin/extensions/category-recent.png");
|
||||
}
|
||||
|
||||
|
||||
/*** header ***/
|
||||
|
@ -168,6 +174,35 @@
|
|||
list-style-image: url("chrome://global/skin/icons/loading_16.png");
|
||||
}
|
||||
|
||||
#header-utils-btn {
|
||||
-moz-appearance: none;
|
||||
min-width: 4.5em;
|
||||
border-width: 1px;
|
||||
-moz-border-top-colors: #999;
|
||||
-moz-border-bottom-colors: #999;
|
||||
-moz-border-left-colors: #999;
|
||||
-moz-border-right-colors: #999;
|
||||
-moz-border-radius: 8px;
|
||||
background-image: -moz-linear-gradient(#FFF, #BBB);
|
||||
list-style-image: url("chrome://mozapps/skin/extensions/utilities.png");
|
||||
}
|
||||
|
||||
#header-utils-btn:hover,
|
||||
#header-utils-btn[open="true"] {
|
||||
-moz-border-top-colors: #777;
|
||||
-moz-border-bottom-colors: #777;
|
||||
-moz-border-left-colors: #777;
|
||||
-moz-border-right-colors: #777;
|
||||
}
|
||||
|
||||
#header-utils-btn[open="true"] {
|
||||
-moz-box-shadow: inset 3px 3px 8px #555;
|
||||
}
|
||||
|
||||
#header-utils-btn:-moz-focusring > .button-box {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.view-header {
|
||||
background: -moz-linear-gradient(top, #FFF, #E8E8E8 50%, #FFF);
|
||||
padding: 4px;
|
||||
|
@ -337,7 +372,8 @@
|
|||
}
|
||||
|
||||
.addon .name,
|
||||
.addon .version {
|
||||
.addon .version,
|
||||
.addon .update-postfix {
|
||||
font-size: 150%;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
@ -365,6 +401,10 @@
|
|||
opacity: 1;
|
||||
}
|
||||
|
||||
.addon .basicinfo-container {
|
||||
-moz-box-align: start;
|
||||
}
|
||||
|
||||
.addon .details-container {
|
||||
-moz-box-align: end;
|
||||
-moz-margin-start: 20px;
|
||||
|
@ -380,6 +420,44 @@
|
|||
border-color: #AAA;
|
||||
}
|
||||
|
||||
.addon .relnotes-container {
|
||||
-moz-box-align: start;
|
||||
height: 0px;
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
-moz-transition-property: height, opacity;
|
||||
-moz-transition-duration: 0.5s, 0.5s;
|
||||
}
|
||||
|
||||
.addon[show-relnotes] .relnotes-container {
|
||||
opacity: 1;
|
||||
-moz-transition-property: height, opacity;
|
||||
-moz-transition-duration: 0.5s, 0.5s;
|
||||
}
|
||||
|
||||
.addon .relnotes-header {
|
||||
font-weight: bold;
|
||||
margin: 10px 0px;
|
||||
}
|
||||
|
||||
.addon .relnotes-toggle {
|
||||
-moz-appearance: none;
|
||||
border: none;
|
||||
background: transparent;
|
||||
font-weight: bold;
|
||||
-moz-box-direction: reverse;
|
||||
cursor: pointer;
|
||||
list-style-image: url("chrome://global/skin/arrow/arrow-dn.gif");
|
||||
}
|
||||
|
||||
.addon .relnotes-toggle > .button-box > .button-icon {
|
||||
-moz-padding-start: 4px;
|
||||
}
|
||||
|
||||
.addon[show-relnotes] .relnotes-toggle {
|
||||
list-style-image: url("chrome://global/skin/arrow/arrow-up.gif");
|
||||
}
|
||||
|
||||
|
||||
/*** item - uninstalled ***/
|
||||
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 3.1 KiB |
|
@ -23,6 +23,7 @@ toolkit.jar:
|
|||
+ skin/classic/mozapps/extensions/rating-unrated.png (extensions/rating-unrated.png)
|
||||
+ skin/classic/mozapps/extensions/cancel.png (extensions/cancel.png)
|
||||
+ skin/classic/mozapps/extensions/pause.png (extensions/pause.png)
|
||||
+ skin/classic/mozapps/extensions/utilities.png (extensions/utilities.png)
|
||||
+ skin/classic/mozapps/passwordmgr/key.png (passwordmgr/key.png)
|
||||
+ skin/classic/mozapps/plugins/notifyPluginBlocked.png (plugins/pluginBlocked-16.png)
|
||||
+ skin/classic/mozapps/plugins/notifyPluginCrashed.png (plugins/pluginGeneric-16.png)
|
||||
|
|
|
@ -130,6 +130,12 @@
|
|||
#category-plugins > .category-icon {
|
||||
list-style-image: url("chrome://mozapps/skin/extensions/category-plugins.png");
|
||||
}
|
||||
#category-availableUpdates > .category-icon {
|
||||
list-style-image: url("chrome://mozapps/skin/extensions/category-available.png");
|
||||
}
|
||||
#category-recentUpdates > .category-icon {
|
||||
list-style-image: url("chrome://mozapps/skin/extensions/category-recent.png");
|
||||
}
|
||||
|
||||
|
||||
/*** header ***/
|
||||
|
@ -168,6 +174,35 @@
|
|||
list-style-image: url("chrome://global/skin/icons/loading_16.png");
|
||||
}
|
||||
|
||||
#header-utils-btn {
|
||||
-moz-appearance: none;
|
||||
min-width: 4.5em;
|
||||
border-width: 1px;
|
||||
-moz-border-top-colors: #999;
|
||||
-moz-border-bottom-colors: #999;
|
||||
-moz-border-left-colors: #999;
|
||||
-moz-border-right-colors: #999;
|
||||
-moz-border-radius: 8px;
|
||||
background-image: -moz-linear-gradient(#FFF, #BBB);
|
||||
list-style-image: url("chrome://mozapps/skin/extensions/utilities.png");
|
||||
}
|
||||
|
||||
#header-utils-btn:hover,
|
||||
#header-utils-btn[open="true"] {
|
||||
-moz-border-top-colors: #777;
|
||||
-moz-border-bottom-colors: #777;
|
||||
-moz-border-left-colors: #777;
|
||||
-moz-border-right-colors: #777;
|
||||
}
|
||||
|
||||
#header-utils-btn[open="true"] {
|
||||
-moz-box-shadow: inset 3px 3px 8px #555;
|
||||
}
|
||||
|
||||
#header-utils-btn:-moz-focusring > .button-box {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.view-header {
|
||||
background: -moz-linear-gradient(top, #FFF, #E8E8E8 50%, #FFF);
|
||||
padding: 4px;
|
||||
|
@ -337,7 +372,8 @@
|
|||
}
|
||||
|
||||
.addon .name,
|
||||
.addon .version {
|
||||
.addon .version,
|
||||
.addon .update-postfix {
|
||||
font-size: 150%;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
@ -365,6 +401,10 @@
|
|||
opacity: 1;
|
||||
}
|
||||
|
||||
.addon .basicinfo-container {
|
||||
-moz-box-align: start;
|
||||
}
|
||||
|
||||
.addon .details-container {
|
||||
-moz-box-align: end;
|
||||
-moz-margin-start: 20px;
|
||||
|
@ -380,6 +420,44 @@
|
|||
border-color: #AAA;
|
||||
}
|
||||
|
||||
.addon .relnotes-container {
|
||||
-moz-box-align: start;
|
||||
height: 0px;
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
-moz-transition-property: height, opacity;
|
||||
-moz-transition-duration: 0.5s, 0.5s;
|
||||
}
|
||||
|
||||
.addon[show-relnotes] .relnotes-container {
|
||||
opacity: 1;
|
||||
-moz-transition-property: height, opacity;
|
||||
-moz-transition-duration: 0.5s, 0.5s;
|
||||
}
|
||||
|
||||
.addon .relnotes-header {
|
||||
font-weight: bold;
|
||||
margin: 10px 0px;
|
||||
}
|
||||
|
||||
.addon .relnotes-toggle {
|
||||
-moz-appearance: none;
|
||||
border: none;
|
||||
background: transparent;
|
||||
font-weight: bold;
|
||||
-moz-box-direction: reverse;
|
||||
cursor: pointer;
|
||||
list-style-image: url("chrome://global/skin/arrow/arrow-dn.gif");
|
||||
}
|
||||
|
||||
.addon .relnotes-toggle > .button-box > .button-icon {
|
||||
-moz-padding-start: 4px;
|
||||
}
|
||||
|
||||
.addon[show-relnotes] .relnotes-toggle {
|
||||
list-style-image: url("chrome://global/skin/arrow/arrow-up.gif");
|
||||
}
|
||||
|
||||
|
||||
/*** item - uninstalled ***/
|
||||
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 3.1 KiB |
|
@ -25,6 +25,7 @@ toolkit.jar:
|
|||
skin/classic/mozapps/extensions/rating-unrated.png (extensions/rating-unrated.png)
|
||||
skin/classic/mozapps/extensions/cancel.png (extensions/cancel.png)
|
||||
skin/classic/mozapps/extensions/pause.png (extensions/pause.png)
|
||||
skin/classic/mozapps/extensions/utilities.png (extensions/utilities.png)
|
||||
skin/classic/mozapps/extensions/about.css (extensions/about.css)
|
||||
skin/classic/mozapps/extensions/extensions.css (extensions/extensions.css)
|
||||
skin/classic/mozapps/extensions/update.css (extensions/update.css)
|
||||
|
|
|
@ -130,6 +130,12 @@
|
|||
#category-plugins > .category-icon {
|
||||
list-style-image: url("chrome://mozapps/skin/extensions/category-plugins.png");
|
||||
}
|
||||
#category-availableUpdates > .category-icon {
|
||||
list-style-image: url("chrome://mozapps/skin/extensions/category-available.png");
|
||||
}
|
||||
#category-recentUpdates > .category-icon {
|
||||
list-style-image: url("chrome://mozapps/skin/extensions/category-recent.png");
|
||||
}
|
||||
|
||||
|
||||
/*** header ***/
|
||||
|
@ -168,6 +174,35 @@
|
|||
list-style-image: url("chrome://global/skin/icons/loading_16.png");
|
||||
}
|
||||
|
||||
#header-utils-btn {
|
||||
-moz-appearance: none;
|
||||
min-width: 4.5em;
|
||||
border-width: 1px;
|
||||
-moz-border-top-colors: #999;
|
||||
-moz-border-bottom-colors: #999;
|
||||
-moz-border-left-colors: #999;
|
||||
-moz-border-right-colors: #999;
|
||||
-moz-border-radius: 8px;
|
||||
background-image: -moz-linear-gradient(#FFF, #BBB);
|
||||
list-style-image: url("chrome://mozapps/skin/extensions/utilities.png");
|
||||
}
|
||||
|
||||
#header-utils-btn:hover,
|
||||
#header-utils-btn[open="true"] {
|
||||
-moz-border-top-colors: #777;
|
||||
-moz-border-bottom-colors: #777;
|
||||
-moz-border-left-colors: #777;
|
||||
-moz-border-right-colors: #777;
|
||||
}
|
||||
|
||||
#header-utils-btn[open="true"] {
|
||||
-moz-box-shadow: inset 3px 3px 8px #555;
|
||||
}
|
||||
|
||||
#header-utils-btn:-moz-focusring > .button-box {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.view-header {
|
||||
background: -moz-linear-gradient(top, #FFF, #E8E8E8 50%, #FFF);
|
||||
padding: 4px;
|
||||
|
@ -337,7 +372,8 @@
|
|||
}
|
||||
|
||||
.addon .name,
|
||||
.addon .version {
|
||||
.addon .version,
|
||||
.addon .update-postfix {
|
||||
font-size: 150%;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
@ -365,6 +401,10 @@
|
|||
opacity: 1;
|
||||
}
|
||||
|
||||
.addon .basicinfo-container {
|
||||
-moz-box-align: start;
|
||||
}
|
||||
|
||||
.addon .details-container {
|
||||
-moz-box-align: end;
|
||||
-moz-margin-start: 20px;
|
||||
|
@ -380,6 +420,44 @@
|
|||
border-color: #AAA;
|
||||
}
|
||||
|
||||
.addon .relnotes-container {
|
||||
-moz-box-align: start;
|
||||
height: 0px;
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
-moz-transition-property: height, opacity;
|
||||
-moz-transition-duration: 0.5s, 0.5s;
|
||||
}
|
||||
|
||||
.addon[show-relnotes] .relnotes-container {
|
||||
opacity: 1;
|
||||
-moz-transition-property: height, opacity;
|
||||
-moz-transition-duration: 0.5s, 0.5s;
|
||||
}
|
||||
|
||||
.addon .relnotes-header {
|
||||
font-weight: bold;
|
||||
margin: 10px 0px;
|
||||
}
|
||||
|
||||
.addon .relnotes-toggle {
|
||||
-moz-appearance: none;
|
||||
border: none;
|
||||
background: transparent;
|
||||
font-weight: bold;
|
||||
-moz-box-direction: reverse;
|
||||
cursor: pointer;
|
||||
list-style-image: url("chrome://global/skin/arrow/arrow-dn.gif");
|
||||
}
|
||||
|
||||
.addon .relnotes-toggle > .button-box > .button-icon {
|
||||
-moz-padding-start: 4px;
|
||||
}
|
||||
|
||||
.addon[show-relnotes] .relnotes-toggle {
|
||||
list-style-image: url("chrome://global/skin/arrow/arrow-up.gif");
|
||||
}
|
||||
|
||||
|
||||
/*** item - uninstalled ***/
|
||||
|
||||
|
|
Двоичный файл не отображается.
После Ширина: | Высота: | Размер: 3.1 KiB |
|
@ -31,6 +31,7 @@ toolkit.jar:
|
|||
skin/classic/mozapps/extensions/rating-unrated.png (extensions/rating-unrated.png)
|
||||
skin/classic/mozapps/extensions/cancel.png (extensions/cancel.png)
|
||||
skin/classic/mozapps/extensions/pause.png (extensions/pause.png)
|
||||
skin/classic/mozapps/extensions/utilities.png (extensions/utilities.png)
|
||||
skin/classic/mozapps/extensions/eula.css (extensions/eula.css)
|
||||
skin/classic/mozapps/handling/handling.css (handling/handling.css)
|
||||
skin/classic/mozapps/passwordmgr/key.png (passwordmgr/key.png)
|
||||
|
@ -93,6 +94,7 @@ toolkit.jar:
|
|||
skin/classic/aero/mozapps/extensions/rating-unrated.png (extensions/rating-unrated.png)
|
||||
skin/classic/aero/mozapps/extensions/cancel.png (extensions/cancel.png)
|
||||
skin/classic/aero/mozapps/extensions/pause.png (extensions/pause.png)
|
||||
skin/classic/aero/mozapps/extensions/utilities.png (extensions/utilities.png)
|
||||
skin/classic/aero/mozapps/extensions/eula.css (extensions/eula.css)
|
||||
skin/classic/aero/mozapps/handling/handling.css (handling/handling.css)
|
||||
skin/classic/aero/mozapps/passwordmgr/key.png (passwordmgr/key-aero.png)
|
||||
|
|
Загрузка…
Ссылка в новой задаче