Diff
checker
Testo
Testo
Immagini
Documenti
Excel
Cartelle
Legal
Enterprise
Applicazione per desktop
Prezzi
Accedi
Scarica Diffchecker Desktop
Confronta il testo
Trova la differenza tra due file di testo
Strumenti
Cronologia
Editor live
Comprimi invariate
Senza a capo
Layout
Diviso
Unificato
Livello di dettaglio
Intelligente
Parola
Carattere
Evidenziazione sintassi
Scegli sintassi
Ignora
Trasforma testo
Vai alla prima modifica
Modifica input
Diffchecker Desktop
Il modo più sicuro per usare Diffchecker. Ottieni l'app Diffchecker Desktop: i tuoi diff non lasciano mai il tuo computer!
Ottieni Desktop
Untitled diff
Creato
11 anni fa
Il diff non scade mai
Eliminare
Esporta
Condividere
Spiegare
37 rimozioni
Linee
Totale
Rimosso
Caratteri
Totale
Rimosso
Per continuare a utilizzare questa funzione, aggiorna a
Diff
checker
Pro
Visualizza prezzi
592 linee
Copia tutti
47 aggiunte
Linee
Totale
Aggiunto
Caratteri
Totale
Aggiunto
Per continuare a utilizzare questa funzione, aggiorna a
Diff
checker
Pro
Visualizza prezzi
601 linee
Copia tutti
Components.utils.import("resource://gre/modules/AddonManager.jsm");
Components.utils.import("resource://gre/modules/AddonManager.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
var doAlphaSort = null; // for pref (alphabetical vs by-state sorting)
var doAlphaSort = null; // for pref (alphabetical vs by-state sorting)
var updatedSort = false; // for pref (sort by last updated)
var updatedSort = false; // for pref (sort by last updated)
var dontSort = false; // ignore sort pref in category-userstyles (provides own sorting)
var dontSort = false; // ignore sort pref in category-userstyles (provides own sorting)
var restore = null; // for pref (restore hilite after closing AoM)
var restore = null; // for pref (restore hilite after closing AoM)
var showUI = null; // for pref (whether to create/display ac menu)
var showUI = null; // for pref (whether to create/display ac menu)
var UIwidth = null; // for pref (ac menu size)
var UIwidth = null; // for pref (ac menu size)
var showVersionNumber = null; // for pref (whether to show version number in ac menu)
var showVersionNumber = null; // for pref (whether to show version number in ac menu)
var spacer = " ";
var spacer = " ";
var UIextra = null; // for restore-on-demand hidden pref
var UIextra = null; // for restore-on-demand hidden pref
var extraRows = null;
var extraRows = null;
var extArray = null;
var extArray = null;
var themeArray = null;
var themeArray = null;
var pluginArray = null;
var pluginArray = null;
var userstyleArray = null;
var userstyleArray = null;
var serviceArray = null;
var serviceArray = null;
var userscriptArray = null;
var userscriptArray = null;
Copia
Copiato
Copia
Copiato
var scriptishArray = null;
var custombuttonsArray = null;
var dictionaryArray = null;
var localeArray = null;
var savedAddonName = null;
var savedAddonName = null;
var displayDropdown = null; // used for Seamonkey & Tbird workaround
var displayDropdown = null; // used for Seamonkey & Tbird workaround
const LISTVIEW = 2;
const LISTVIEW = 2;
const DETAILVIEW = 4;
const DETAILVIEW = 4;
var supportedCats = [ "category-extension", "category-theme", "category-plugin", "category-userstyle",
var supportedCats = [ "category-extension", "category-theme", "category-plugin", "category-userstyle",
Copia
Copiato
Copia
Copiato
"category-service", "category-greasemonkey-user-script"
];
"category-service", "category-greasemonkey-user-script"
, "category-userscript",
"category-custombuttons", "category-dictionary", "category-locale"
];
// from http://erikvold.com/blog/index.cfm/2011/6/14/restartless-firefox-addons-part-6-better-includes
// from http://erikvold.com/blog/index.cfm/2011/6/14/restartless-firefox-addons-part-6-better-includes
// Thanks, Erik!
// Thanks, Erik!
(function(global) {
(function(global) {
global.include = function include(src) {
global.include = function include(src) {
var o = {};
var o = {};
Components.utils.import("resource://gre/modules/Services.jsm", o);
Components.utils.import("resource://gre/modules/Services.jsm", o);
var uri = o.Services.io.newURI(src, null, o.Services.io.newURI(__SCRIPT_URI_SPEC__, null, null));
var uri = o.Services.io.newURI(src, null, o.Services.io.newURI(__SCRIPT_URI_SPEC__, null, null));
o.Services.scriptloader.loadSubScript(uri.spec, global);
o.Services.scriptloader.loadSubScript(uri.spec, global);
};
};
})(this);
})(this);
include("components/addonList_autocomplete.js");
include("components/addonList_autocomplete.js");
function startup(data, reason) {
function startup(data, reason) {
Services.obs.addObserver(ChromeDocObserver, "chrome-document-global-created", false);
Services.obs.addObserver(ChromeDocObserver, "chrome-document-global-created", false);
var defPrefs = Services.prefs.getDefaultBranch("extensions.addonsmgrhilte@cfl.");
var defPrefs = Services.prefs.getDefaultBranch("extensions.addonsmgrhilte@cfl.");
defPrefs.setBoolPref("restore", true);
defPrefs.setBoolPref("restore", true);
defPrefs.setBoolPref("alphaSort", false);
defPrefs.setBoolPref("alphaSort", false);
defPrefs.setBoolPref("updatedSort", false);
defPrefs.setBoolPref("updatedSort", false);
defPrefs.setBoolPref("extraRows", false);
defPrefs.setBoolPref("extraRows", false);
defPrefs.setBoolPref("showUI", true); // should we default this to true now??????
defPrefs.setBoolPref("showUI", true); // should we default this to true now??????
defPrefs.setIntPref("listboxSize", 18);
defPrefs.setIntPref("listboxSize", 18);
defPrefs.setBoolPref("UIextra", false);
defPrefs.setBoolPref("UIextra", false);
defPrefs.setBoolPref("showVersion", false);
defPrefs.setBoolPref("showVersion", false);
// register our custom autocomplete component
// register our custom autocomplete component
Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar).registerFactory(CLASS_ID,
Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar).registerFactory(CLASS_ID,
CLASS_NAME, CONTRACT_ID, NSGetFactory(CLASS_ID));
CLASS_NAME, CONTRACT_ID, NSGetFactory(CLASS_ID));
if (reason == ADDON_ENABLE || reason == ADDON_INSTALL) {
if (reason == ADDON_ENABLE || reason == ADDON_INSTALL) {
var mgrs = findAddonsMgrs();
var mgrs = findAddonsMgrs();
var i;
var i;
for (i = 0; i < mgrs.length; i++) {
for (i = 0; i < mgrs.length; i++) {
mgrs[i].location.reload();
mgrs[i].location.reload();
}
}
}
}
}
}
function shutdown(data, reason) {
function shutdown(data, reason) {
Services.obs.removeObserver(ChromeDocObserver, "chrome-document-global-created");
Services.obs.removeObserver(ChromeDocObserver, "chrome-document-global-created");
// call flush due to the bundle service cache (for aomhilite.properties string bundle)
// call flush due to the bundle service cache (for aomhilite.properties string bundle)
Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService)
Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService)
.flushBundles();
.flushBundles();
// unregister our custom autocomplete component
// unregister our custom autocomplete component
Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar).unregisterFactory(CLASS_ID,
Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar).unregisterFactory(CLASS_ID,
NSGetFactory(CLASS_ID));
NSGetFactory(CLASS_ID));
// remove stylesheets
// remove stylesheets
removeStylesheet("chrome://aomhilite/content/aomhilite.css");
removeStylesheet("chrome://aomhilite/content/aomhilite.css");
removeStylesheet("chrome://aomhilite/content/aomhiliteLG.css");
removeStylesheet("chrome://aomhilite/content/aomhiliteLG.css");
removeStylesheet("chrome://aomhilite/content/aomhiliteOSX.css");
removeStylesheet("chrome://aomhilite/content/aomhiliteOSX.css");
if (reason == ADDON_DISABLE) {
if (reason == ADDON_DISABLE) {
// remove any UI from any open Add-ons Manager tabs and revert to default sorting
// remove any UI from any open Add-ons Manager tabs and revert to default sorting
var mgrs = findAddonsMgrs();
var mgrs = findAddonsMgrs();
var i;
var i;
for (i = 0; i < mgrs.length; i++) {
for (i = 0; i < mgrs.length; i++) {
AddonsMgrOnUnload.call(mgrs[i]);
AddonsMgrOnUnload.call(mgrs[i]);
// reverts to default sort;
// reverts to default sort;
// also allows aomhilite.xml to be removed from memory w/o waiting for user to close AoM
// also allows aomhilite.xml to be removed from memory w/o waiting for user to close AoM
mgrs[i].location.reload();
mgrs[i].location.reload();
}
}
}
}
}
}
function install(data, reason) {
function install(data, reason) {
}
}
function uninstall(data, reason) {
function uninstall(data, reason) {
// don't remove user's selection when updating ext (as opposed to actual uninstall)
// don't remove user's selection when updating ext (as opposed to actual uninstall)
if (reason != "ADDON_UNINSTALL") {
if (reason != "ADDON_UNINSTALL") {
return;
return;
}
}
var RDF = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService);
var RDF = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService);
var localstore = RDF.GetDataSource('rdf:local-store');
var localstore = RDF.GetDataSource('rdf:local-store');
var subj = RDF.GetResource('about:addons#addon-list');
var subj = RDF.GetResource('about:addons#addon-list');
var pred = RDF.GetResource('aomhilite');
var pred = RDF.GetResource('aomhilite');
var target = localstore.GetTarget(subj, pred, true);
var target = localstore.GetTarget(subj, pred, true);
if (target == null) {
if (target == null) {
return;
return;
} // if it's an empty string we want to remove it's entry
} // if it's an empty string we want to remove it's entry
target = target.QueryInterface(Components.interfaces.nsIRDFLiteral);
target = target.QueryInterface(Components.interfaces.nsIRDFLiteral);
var obj = RDF.GetLiteral(target.Value);
var obj = RDF.GetLiteral(target.Value);
localstore.Unassert(subj, pred, obj, true);
localstore.Unassert(subj, pred, obj, true);
}
}
function ChromeDocObserver(aSubject, aTopic, aData) {
function ChromeDocObserver(aSubject, aTopic, aData) {
try {
try {
if (aTopic != "chrome-document-global-created") {
if (aTopic != "chrome-document-global-created") {
return;
return;
}
}
var win = aSubject;
var win = aSubject;
var uri = win.document.documentURI;
var uri = win.document.documentURI;
// if Add-ons Manager Dialog Returns add-on is installed, uri will be about:blank until loaded
// if Add-ons Manager Dialog Returns add-on is installed, uri will be about:blank until loaded
if (uri == "about:addons" || uri == "about:blank") {
if (uri == "about:addons" || uri == "about:blank") {
win.addEventListener("load", AddonsMgrOnload, false);
win.addEventListener("load", AddonsMgrOnload, false);
}
}
} catch (e) {
} catch (e) {
Services.console.logStringMessage("Exception in ChromeDocObserver");
Services.console.logStringMessage("Exception in ChromeDocObserver");
}
}
}
}
function AddonsMgrOnload() {
function AddonsMgrOnload() {
// removing this load listener is req'd to prevent mem leak
// removing this load listener is req'd to prevent mem leak
// if we're at about:blank we need to do that *now*
// if we're at about:blank we need to do that *now*
// might as well do them all here
// might as well do them all here
// listener no longer needed since if the mgr is reloaded via F5,
// listener no longer needed since if the mgr is reloaded via F5,
// unload is called, then ChromeDocObserver re-adds the listener
// unload is called, then ChromeDocObserver re-adds the listener
this.removeEventListener("load", AddonsMgrOnload, false);
this.removeEventListener("load", AddonsMgrOnload, false);
if (this.document.documentURI != "about:addons") { return; }
if (this.document.documentURI != "about:addons") { return; }
this.addEventListener("unload", AddonsMgrOnUnload, false);
this.addEventListener("unload", AddonsMgrOnUnload, false);
var AMdoc = this.document; // document obj of Addons Mgr window
var AMdoc = this.document; // document obj of Addons Mgr window
var addonList = AMdoc.getElementById("addon-list");
var addonList = AMdoc.getElementById("addon-list");
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService);
.getService(Components.interfaces.nsIPrefService);
prefs = prefs.getBranch("extensions.addonsmgrhilte@cfl.");
prefs = prefs.getBranch("extensions.addonsmgrhilte@cfl.");
doAlphaSort = prefs.getBoolPref("alphaSort");
doAlphaSort = prefs.getBoolPref("alphaSort");
updatedSort = prefs.getBoolPref("updatedSort");
updatedSort = prefs.getBoolPref("updatedSort");
restore = prefs.getBoolPref("restore");
restore = prefs.getBoolPref("restore");
UIextra = prefs.getBoolPref("UIextra");
UIextra = prefs.getBoolPref("UIextra");
showUI = prefs.getBoolPref("showUI");
showUI = prefs.getBoolPref("showUI");
extraRows = prefs.getBoolPref("extraRows");
extraRows = prefs.getBoolPref("extraRows");
// restore-on-demand useless if already auto-restored, or the UI not even visible
// restore-on-demand useless if already auto-restored, or the UI not even visible
if (restore || !showUI) {
if (restore || !showUI) {
UIextra = false;
UIextra = false;
}
}
UIwidth = prefs.getIntPref("listboxSize");
UIwidth = prefs.getIntPref("listboxSize");
UIwidth = (UIwidth > 50) ? 50 : UIwidth;
UIwidth = (UIwidth > 50) ? 50 : UIwidth;
UIwidth = (UIwidth < 10) ? 10 : UIwidth;
UIwidth = (UIwidth < 10) ? 10 : UIwidth;
if (!restore) {
if (!restore) {
addonList.setAttribute('aomhilite', "");
addonList.setAttribute('aomhilite', "");
}
}
this.addEventListener("ViewChanged", onViewChange, false);
this.addEventListener("ViewChanged", onViewChange, false);
var cat = AMdoc.getElementById("categories");
var cat = AMdoc.getElementById("categories");
if (!cat || !addonList) {
if (!cat || !addonList) {
return;
return;
}
}
var attr = addonList.getAttribute("persist"); // 'persist' enables this info to survive a restart of fx
var attr = addonList.getAttribute("persist"); // 'persist' enables this info to survive a restart of fx
if (!attr) {
if (!attr) {
addonList.setAttribute("persist", "aomhilite");
addonList.setAttribute("persist", "aomhilite");
} else if (attr.indexOf("aomhilite") < 0) {
} else if (attr.indexOf("aomhilite") < 0) {
addonList.setAttribute("persist", attr + " aomhilite");
addonList.setAttribute("persist", attr + " aomhilite");
}
}
addonList.addEventListener("select", onSelect, false);
addonList.addEventListener("select", onSelect, false);
// let AoM finish loading list, before attempting potential resort
// let AoM finish loading list, before attempting potential resort
this.setTimeout(function() {initAddonList(AMdoc);}, 0);
this.setTimeout(function() {initAddonList(AMdoc);}, 0);
if (showUI) { this.setTimeout(function() {initUI(AMdoc);}, 100); }
if (showUI) { this.setTimeout(function() {initUI(AMdoc);}, 100); }
}
}
function initAddonList (AMdoc) {
function initAddonList (AMdoc) {
//Services.console.logStringMessage("initAddonList called");
//Services.console.logStringMessage("initAddonList called");
// check if we're in list view of a supported category; sort and hilite
// check if we're in list view of a supported category; sort and hilite
var cat = AMdoc.getElementById("categories");
var cat = AMdoc.getElementById("categories");
var selCat = cat.selectedItem.id;
var selCat = cat.selectedItem.id;
var view = AMdoc.getElementById('view-port');
var view = AMdoc.getElementById('view-port');
if ((supportedCats.indexOf(selCat) != -1) && view.getAttribute('selectedIndex') == LISTVIEW) {
if ((supportedCats.indexOf(selCat) != -1) && view.getAttribute('selectedIndex') == LISTVIEW) {
if (selCat == "category-userstyle" || selCat == "category-greasemonkey-user-script") {
if (selCat == "category-userstyle" || selCat == "category-greasemonkey-user-script") {
dontSort = true;
dontSort = true;
}
}
if (doAlphaSort || updatedSort) {
if (doAlphaSort || updatedSort) {
resort(AMdoc);
resort(AMdoc);
}
}
restoreHilite(AMdoc);
restoreHilite(AMdoc);
}
}
}
}
var addonListener = {
var addonListener = {
onInstalled : function(addon) {
onInstalled : function(addon) {
updateListboxContents(addon, "add");
updateListboxContents(addon, "add");
updateAllListboxes();
updateAllListboxes();
},
},
/*
/*
* due to the 'undo' option remaining available until aom closed/reopened, this won't get called until current
* due to the 'undo' option remaining available until aom closed/reopened, this won't get called until current
* instance (tab) is closed, because that's when the actual uninstall occurs (and when we should remove item from
* instance (tab) is closed, because that's when the actual uninstall occurs (and when we should remove item from
* dropdown list)
* dropdown list)
*/
*/
onUninstalled : function(addon) {
onUninstalled : function(addon) {
updateListboxContents(addon, "remove");
updateListboxContents(addon, "remove");
updateAllListboxes();
updateAllListboxes();
}
}
};
};
function initUI(AMdoc) {
function initUI(AMdoc) {
var acListboxStyle = "margin-left: 1em; margin-right: 1em; width: " + UIwidth + "em;";
var acListboxStyle = "margin-left: 1em; margin-right: 1em; width: " + UIwidth + "em;";
var acAddonList = AMdoc.createElement("textbox");
var acAddonList = AMdoc.createElement("textbox");
acAddonList.setAttribute("id", "aomhilite_ac_menu");
acAddonList.setAttribute("id", "aomhilite_ac_menu");
acAddonList.setAttribute("style", acListboxStyle);
acAddonList.setAttribute("style", acListboxStyle);
acAddonList.setAttribute("type", "autocomplete");
acAddonList.setAttribute("type", "autocomplete");
// acAddonList.setAttribute("size", 24); // seems to have no effect; set via css width instead
// acAddonList.setAttribute("size", 24); // seems to have no effect; set via css width instead
acAddonList.setAttribute("autocompletesearch", "addonList_autocomplete");
acAddonList.setAttribute("autocompletesearch", "addonList_autocomplete");
acAddonList.setAttribute("enablehistory", true);
acAddonList.setAttribute("enablehistory", true);
// acAddonList.setAttribute("completedefaultindex", true);
// acAddonList.setAttribute("completedefaultindex", true);
acAddonList.setAttribute("forcecomplete", true); // ensures selection is valid
acAddonList.setAttribute("forcecomplete", true); // ensures selection is valid
// only applies to typing in box; see aomhilite.xml
// only applies to typing in box; see aomhilite.xml
acAddonList.setAttribute("maxrows", 10); // default is about 6
acAddonList.setAttribute("maxrows", 10); // default is about 6
var notifyListbox = "var evt = document.createEvent('Events'); " + "evt.initEvent('textentered', true, true); " +
var notifyListbox = "var evt = document.createEvent('Events'); " + "evt.initEvent('textentered', true, true); " +
"this.dispatchEvent(evt);";
"this.dispatchEvent(evt);";
acAddonList.setAttribute("ontextentered", notifyListbox);
acAddonList.setAttribute("ontextentered", notifyListbox);
var strbundle = Components.classes["@mozilla.org/intl/stringbundle;1"].getService(
var strbundle = Components.classes["@mozilla.org/intl/stringbundle;1"].getService(
Components.interfaces.nsIStringBundleService).createBundle("chrome://aomhilite/locale/aomhilite.properties");
Components.interfaces.nsIStringBundleService).createBundle("chrome://aomhilite/locale/aomhilite.properties");
var selectaddon = strbundle.GetStringFromName("placeholderString");
var selectaddon = strbundle.GetStringFromName("placeholderString");
acAddonList.setAttribute("placeholder", selectaddon);
acAddonList.setAttribute("placeholder", selectaddon);
/* set up stylesheets */
/* set up stylesheets */
var osString = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULRuntime).OS;
var osString = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULRuntime).OS;
addStylesheet("chrome://aomhilite/content/aomhilite.css");
addStylesheet("chrome://aomhilite/content/aomhilite.css");
if (osString == "Darwin") {
if (osString == "Darwin") {
addStylesheet("chrome://aomhilite/content/aomhiliteOSX.css");
addStylesheet("chrome://aomhilite/content/aomhiliteOSX.css");
}
}
var updateBtn = AMdoc.getElementById("header-utils-btn");
var updateBtn = AMdoc.getElementById("header-utils-btn");
var head = AMdoc.getElementById("header");
var head = AMdoc.getElementById("header");
head.insertBefore(acAddonList, updateBtn);
head.insertBefore(acAddonList, updateBtn);
// prevents "Extension cannot be installed because Nightly cannot modify the needed file"
// prevents "Extension cannot be installed because Nightly cannot modify the needed file"
// error when updating this ext (bug 719180)
// error when updating this ext (bug 719180)
// although 71980 is fixed in fx 19+, using (tested on fx 21.0a1):
// although 71980 is fixed in fx 19+, using (tested on fx 21.0a1):
// acAddonList.style.MozBinding = "url(chrome://aomhilite/content/aomhilite.xml#ac_menu_aomhilite)";
// acAddonList.style.MozBinding = "url(chrome://aomhilite/content/aomhilite.xml#ac_menu_aomhilite)";
// leaves the aomhilite.xml file in memory even when AoM is closed and aomhilite is disabled!
// leaves the aomhilite.xml file in memory even when AoM is closed and aomhilite is disabled!
var chromeReg = Components.classes["@mozilla.org/chrome/chrome-registry;1"]
var chromeReg = Components.classes["@mozilla.org/chrome/chrome-registry;1"]
.getService(Components.interfaces.nsIChromeRegistry);
.getService(Components.interfaces.nsIChromeRegistry);
var ioService = Components.classes["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
var ioService = Components.classes["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
var bindingUri;
var bindingUri;
if (extraRows) {
if (extraRows) {
bindingUri = ioService.newURI("chrome://aomhilite/content/aomhiliteLG.xml#ac_menu_aomhilite", null, null);
bindingUri = ioService.newURI("chrome://aomhilite/content/aomhiliteLG.xml#ac_menu_aomhilite", null, null);
} else {
} else {
bindingUri = ioService.newURI("chrome://aomhilite/content/aomhilite.xml#ac_menu_aomhilite", null, null);
bindingUri = ioService.newURI("chrome://aomhilite/content/aomhilite.xml#ac_menu_aomhilite", null, null);
}
}
var convertedBindingUri = chromeReg.convertChromeURL(bindingUri);
var convertedBindingUri = chromeReg.convertChromeURL(bindingUri);
acAddonList.style.MozBinding = 'url("' + convertedBindingUri.spec + '")';
acAddonList.style.MozBinding = 'url("' + convertedBindingUri.spec + '")';
const FIREFOX_ID = "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}";
const FIREFOX_ID = "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}";
var appInfo = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULAppInfo);
var appInfo = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULAppInfo);
if (appInfo.ID != FIREFOX_ID) { // workaround - Seamonkey/Tbird (bug 708520) aren't opening popup by default
if (appInfo.ID != FIREFOX_ID) { // workaround - Seamonkey/Tbird (bug 708520) aren't opening popup by default
displayDropdown = function(e) {
displayDropdown = function(e) {
var id = e.originalTarget.getAttribute("anonid");
var id = e.originalTarget.getAttribute("anonid");
if (id != "historydropmarker") { return; }
if (id != "historydropmarker") { return; }
//Services.console.logStringMessage("historydropmarker click");
//Services.console.logStringMessage("historydropmarker click");
var acAddonList = e.target.ownerDocument.getElementById("aomhilite_ac_menu")
var acAddonList = e.target.ownerDocument.getElementById("aomhilite_ac_menu")
acAddonList.showHistoryPopup();
acAddonList.showHistoryPopup();
};
};
acAddonList.addEventListener("click", displayDropdown, false);
acAddonList.addEventListener("click", displayDropdown, false);
}
}
acAddonList.addEventListener("textentered", onACaddonListSelection, false);
acAddonList.addEventListener("textentered", onACaddonListSelection, false);
AddonManager.addAddonListener(addonListener);
AddonManager.addAddonListener(addonListener);
if (UIextra) {
if (UIextra) {
var addonList = AMdoc.getElementById("addon-list");
var addonList = AMdoc.getElementById("addon-list");
addonList.setAttribute('restoreondemand', addonList.getAttribute('aomhilite'));
addonList.setAttribute('restoreondemand', addonList.getAttribute('aomhilite'));
}
}
// (do here since addonListCallback will require data initialized above)
// (do here since addonListCallback will require data initialized above)
AddonManager.getAddonsByTypes([ "extension" ], function(addons) {
AddonManager.getAddonsByTypes([ "extension" ], function(addons) {
addonListCallback(addons, AMdoc, "extension");
addonListCallback(addons, AMdoc, "extension");
});
});
AddonManager.getAddonsByTypes([ "theme" ], function(addons) {
AddonManager.getAddonsByTypes([ "theme" ], function(addons) {
addonListCallback(addons, AMdoc, "theme");
addonListCallback(addons, AMdoc, "theme");
});
});
AddonManager.getAddonsByTypes([ "plugin" ], function(addons) {
AddonManager.getAddonsByTypes([ "plugin" ], function(addons) {
addonListCallback(addons, AMdoc, "plugin");
addonListCallback(addons, AMdoc, "plugin");
});
});
AddonManager.getAddonsByTypes([ "userstyle" ], function(addons) {
AddonManager.getAddonsByTypes([ "userstyle" ], function(addons) {
addonListCallback(addons, AMdoc, "userstyle");
addonListCallback(addons, AMdoc, "userstyle");
});
});
AddonManager.getAddonsByTypes([ "service" ], function(addons) {
AddonManager.getAddonsByTypes([ "service" ], function(addons) {
addonListCallback(addons, AMdoc, "service");
addonListCallback(addons, AMdoc, "service");
});
});
AddonManager.getAddonsByTypes([ "greasemonkey-user-script" ], function(addons) {
AddonManager.getAddonsByTypes([ "greasemonkey-user-script" ], function(addons) {
addonListCallback(addons, AMdoc, "greasemonkey-user-script");
addonListCallback(addons, AMdoc, "greasemonkey-user-script");
});
});
Copia
Copiato
Copia
Copiato
// Scriptish
AddonManager.getAddonsByTypes([ "userscript" ], function(addons) {
addonListCallback(addons, AMdoc, "userscript");
});
// Custom Buttons
AddonManager.getAddonsByTypes([ "custombuttons" ], function(addons) {
addonListCallback(addons, AMdoc, "custombuttons");
});
AddonManager.getAddonsByTypes([ "dictionary" ], function(addons) {
addonListCallback(addons, AMdoc, "dictionary");
});
AddonManager.getAddonsByTypes([ "locale" ], function(addons) {
addonListCallback(addons, AMdoc, "locale");
});
}
}
function addStylesheet(sheet) {
function addStylesheet(sheet) {
var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"]
var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"]
.getService(Components.interfaces.nsIStyleSheetService);
.getService(Components.interfaces.nsIStyleSheetService);
var ios = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
var ios = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
var uri = ios.newURI(sheet, null, null);
var uri = ios.newURI(sheet, null, null);
if (!sss.sheetRegistered(uri, sss.USER_SHEET)) {
if (!sss.sheetRegistered(uri, sss.USER_SHEET)) {
sss.loadAndRegisterSheet(uri, sss.USER_SHEET);
sss.loadAndRegisterSheet(uri, sss.USER_SHEET);
}
}
}
}
function removeStylesheet(sheet) {
function removeStylesheet(sheet) {
var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"]
var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"]
.getService(Components.interfaces.nsIStyleSheetService);
.getService(Components.interfaces.nsIStyleSheetService);
var ios = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
var ios = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
var uri = ios.newURI(sheet, null, null);
var uri = ios.newURI(sheet, null, null);
if (sss.sheetRegistered(uri, sss.USER_SHEET)) {
if (sss.sheetRegistered(uri, sss.USER_SHEET)) {
sss.unregisterSheet(uri, sss.USER_SHEET);
sss.unregisterSheet(uri, sss.USER_SHEET);
}
}
}
}
function findAddonsMgrs() {
function findAddonsMgrs() {
// find all open mgrs
// find all open mgrs
var mgrs = [];
var mgrs = [];
var windows = Services.wm.getEnumerator("navigator:browser");
var windows = Services.wm.getEnumerator("navigator:browser");
var window;
var window;
while (windows.hasMoreElements()) {
while (windows.hasMoreElements()) {
window = windows.getNext().QueryInterface(Components.interfaces.nsIDOMWindow);
window = windows.getNext().QueryInterface(Components.interfaces.nsIDOMWindow);
window.gBrowser.browsers.forEach(findMgrTab);
window.gBrowser.browsers.forEach(findMgrTab);
}
}
function findMgrTab(browser) {
function findMgrTab(browser) {
if (browser.currentURI.spec == "about:addons") {
if (browser.currentURI.spec == "about:addons") {
mgrs.push(browser.contentWindow);
mgrs.push(browser.contentWindow);
}
}
}
}
// Mgr in dialog window (for Add-ons Manager Dialog Returns compatibility)
// Mgr in dialog window (for Add-ons Manager Dialog Returns compatibility)
var topWin = Services.wm.getMostRecentWindow(null);
var topWin = Services.wm.getMostRecentWindow(null);
if (topWin.document.documentURI == "about:addons") {
if (topWin.document.documentURI == "about:addons") {
mgrs.push(topWin);
mgrs.push(topWin);
}
}
return mgrs;
return mgrs;
}
}
function updateListboxContents(addon, action) {
function updateListboxContents(addon, action) {
if (action != "add" && action != "remove") {
if (action != "add" && action != "remove") {
return;
return;
}
}
var currentArray = null;
var currentArray = null;
switch (addon.type) {
switch (addon.type) {
case "extension":
case "extension":
currentArray = extArray;
currentArray = extArray;
break;
break;
case "theme":
case "theme":
currentArray = themeArray;
currentArray = themeArray;
break;
break;
case "plugin":
case "plugin":
currentArray = pluginArray;
currentArray = pluginArray;
break;
break;
case "userstyle":
case "userstyle":
currentArray = userstyleArray;
currentArray = userstyleArray;
break;
break;
case "service":
case "service":
currentArray = serviceArray;
currentArray = serviceArray;
Copia
Copiato
Copia
Copiato
break;
case "greasemonkey-user-script":
case "greasemonkey-user-script":
currentArray = userscriptArray;
currentArray = userscriptArray;
break;
break;
Copia
Copiato
Copia
Copiato
case "userscript":
currentArray = scriptishArray;
break;
case "custombuttons":
currentArray = custombuttonsArray;
break;
case "dictionary":
currentArray = dictionaryArray;
break;
case "locale":
currentArray = localeArray;
break;
default:
default:
Services.console.logStringMessage("Addons Manager Hilite encountered an unsupported Add-on type: " +
Services.console.logStringMessage("Addons Manager Hilite encountered an unsupported Add-on type: " +
addon.type + " " + addon.name);
addon.type + " " + addon.name);
}
}
var entryFound = false;
var entryFound = false;
var element;
var element;
for (element = 0; element < currentArray.length; element++) {
for (element = 0; element < currentArray.length; element++) {
let
let
entry = currentArray[element];
entry = currentArray[element];
if (entry.indexOf(addon.name) != -1) { // found item
if (entry.indexOf(addon.name) != -1) { // found item
entryFound = true;
entryFound = true;
if (showVersionNumber && action == "add") { // version number needs updated
if (showVersionNumber && action == "add") { // version number needs updated
var nameVersion = entry.split(spacer, 2);
var nameVersion = entry.split(spacer, 2);
nameVersion[1] = (nameVersion[0].indexOf("<") == 0) ? addon.version + ">" : addon.version;
nameVersion[1] = (nameVersion[0].indexOf("<") == 0) ? addon.version + ">" : addon.version;
entry = nameVersion.join(spacer);
entry = nameVersion.join(spacer);
currentArray[element] = entry;
currentArray[element] = entry;
} else {
} else {
if (action == "remove") {
if (action == "remove") {
currentArray.splice(element, 1);
currentArray.splice(element, 1);
}
}
}
}
// process restoreondemand entry, if any + actual entry
// process restoreondemand entry, if any + actual entry
if (entry.indexOf("<") != 0) {
if (entry.indexOf("<") != 0) {
break;
break;
}
}
} // end if found
} // end if found
} // end for
} // end for
if (!entryFound && action == "add") { // item not present; needs added
if (!entryFound && action == "add") { // item not present; needs added
var entryToAdd = addon.name;
var entryToAdd = addon.name;
if (showVersionNumber) {
if (showVersionNumber) {
entryToAdd = entryToAdd + spacer + addon.version;
entryToAdd = entryToAdd + spacer + addon.version;
}
}
currentArray.push(entryToAdd);
currentArray.push(entryToAdd);
currentArray.sort(function(addonItem1, addonItem2) {
currentArray.sort(function(addonItem1, addonItem2) {
var addon1Name = addonItem1.toLowerCase();
var addon1Name = addonItem1.toLowerCase();
var addon2Name = addonItem2.toLowerCase();
var addon2Name = addonItem2.toLowerCase();
return addon1Name.localeCompare(addon2Name);
return addon1Name.localeCompare(addon2Name);
});
});
}
}
}
}
function updateAllListboxes() {
function updateAllListboxes() {
var mgrs = findAddonsMgrs();
var mgrs = findAddonsMgrs();
var i;
var i;
for (i = 0; i < mgrs.length; i++) {
for (i = 0; i < mgrs.length; i++) {
var AMdoc = mgrs[i].document;
var AMdoc = mgrs[i].document;
var acAddonList = AMdoc.getElementById("aomhilite_ac_menu");
var acAddonList = AMdoc.getElementById("aomhilite_ac_menu");
var cat = AMdoc.getElementById('categories');
var cat = AMdoc.getElementById('categories');
var selCat = cat.selectedItem.id;
var selCat = cat.selectedItem.id;
switch (selCat) { // select the proper menulist for the current category
switch (selCat) { // select the proper menulist for the current category
case "category-extension":
case "category-extension":
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(extArray));
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(extArray));
break;
break;
case "category-theme":
case "category-theme":
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(themeArray));
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(themeArray));
break;
break;
case "category-plugin":
case "category-plugin":
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(pluginArray));
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(pluginArray));
break;
break;
case "category-userstyle":
case "category-userstyle":
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userstyleArray));
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userstyleArray));
break;
break;
case "category-service":
case "category-service":
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(serviceArray));
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(serviceArray));
Copia
Copiato
Copia
Copiato
break;
case "category-greasemonkey-user-script":
case "category-greasemonkey-user-script":
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userscriptArray));
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userscriptArray));
break;
break;
Copia
Copiato
Copia
Copiato
case "category-userscript":
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(scriptishArray));
break;
case "category-custombuttons":
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(custombuttonsArray));
break;
case "category-dictionary":
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(dictionaryArray));
break;
case "category-locale":
acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(localeArray));
break;
}
}
}
}
}
}
function restoreHilite(AMdoc) {
function restoreHilite(AMdoc) {
//Services.console.logStringMessage("restoreHilite called");
//Services.console.logStringMessage("restoreHilite called");
// purpose: retrieve saved selection and restore it
// purpose: retrieve saved selection and restore it
// content.document does not get document we want if AoM was opened in background via session restore
// content.document does not get document we want if AoM was opened in background via session restore
var selAddon;
var selAddon;
var addonList = AMdoc.getElementById('addon-list');
var addonList = AMdoc.getElementById('addon-list');
var savedSelections = addonList.getAttribute('aomhilite');
var savedSelections = addonList.getAttribute('aomhilite');
//Services.console.logStringMessage(savedSelections);
//Services.console.logStringMessage(savedSelections);
var cat = AMdoc.getElementById('categories');
var cat = AMdoc.getElementById('categories');
var selCat = cat.selectedItem.id; // category-extension, etc.
var selCat = cat.selectedItem.id; // category-extension, etc.
var selectionArray = savedSelections.split(",");
var selectionArray = savedSelections.split(",");
var lastSel = selectionArray[supportedCats.indexOf(selCat)];
var lastSel = selectionArray[supportedCats.indexOf(selCat)];
if (lastSel) {
if (lastSel) {
selAddon = addonList.getElementsByAttribute('value', lastSel);
selAddon = addonList.getElementsByAttribute('value', lastSel);
}
}
if (!lastSel || !selAddon || !selAddon[0]) {
if (!lastSel || !selAddon || !selAddon[0]) {
// no lastSel will occur on newly opened AoM if (always) restore pref is false
// no lastSel will occur on newly opened AoM if (always) restore pref is false
// otherwise typically occurs when selected category has no installed items or has never had a saved selection
// otherwise typically occurs when selected category has no installed items or has never had a saved selection
var acAddonList = AMdoc.getElementById("aomhilite_ac_menu");
var acAddonList = AMdoc.getElementById("aomhilite_ac_menu");
if (acAddonList) {
if (acAddonList) {
acAddonList.value = "";
acAddonList.value = "";
} // onSelect not triggered (see below); need to clear this now
} // onSelect not triggered (see below); need to clear this now
return;
return;
}
}
addonList.selectItem(selAddon[0]); // will trigger onSelect
addonList.selectItem(selAddon[0]); // will trigger onSelect
//addonList.scrollBoxObject.scrollToElement(selAddon[0]);
//addonList.scrollBoxObject.scrollToElement(selAddon[0]);
selAddon[0].scrollIntoView();
selAddon[0].scrollIntoView();
addonList.focus();
addonList.focus();
}
}
function saveUpdatedSel(addonList, selCat, newSelId) {
function saveUpdatedSel(addonList, selCat, newSelId) {
var savedSelections = addonList.getAttribute('aomhilite');
var savedSelections = addonList.getAttribute('aomhilite');
var selectionArray = savedSelections.split(",");
var selectionArray = savedSelections.split(",");
selectionArray[supportedCats.indexOf(selCat)] = newSelId;
selectionArray[supportedCats.indexOf(selCat)] = newSelId;
var updatedSel = selectionArray.toString();
var updatedSel = selectionArray.toString();
addonList.setAttribute('aomhilite', updatedSel);
addonList.setAttribute('aomhilite', updatedSel);
}
}
function onSelect() { // called once per add-on upon loading mgr, but (this.currentIndex = = -1) at that point
function onSelect() { // called once per add-on upon loading mgr, but (this.currentIndex = = -1) at that point
// called when clicking an entry in addonList, selecting from autocomplete list, and from restoreHilite funct; also when changing categories?
// called when clicking an entry in addonList, selecting from autocomplete list, and from restoreHilite funct; also when changing categories?
//Services.console.logStringMessage("onSelect called");
//Services.console.logStringMessage("onSelect called");
//Services.console.logStringMessage(this.id); // addon-list
//Services.console.logStringMessage(this.id); // addon-list
if (this.currentIndex < 0) { return; } // there is no current selected item in this category
if (this.currentIndex < 0) { return; } // there is no current selected item in this category
if (!this.selectedItem) { return; } // avoid 'this.selectedItem is null' error in console (when opening Add-Ons Mgr)
if (!this.selectedItem) { return; } // avoid 'this.selectedItem is null' error in console (when opening Add-Ons Mgr)
var currentSel = this.selectedItem.mAddon.id;
var currentSel = this.selectedItem.mAddon.id;
var AMdoc = this.ownerDocument;
var AMdoc = this.ownerDocument;
var cat = AMdoc.getElementById('categories');
var cat = AMdoc.getElementById('categories');
var selCat = cat.selectedItem.id;
var selCat = cat.selectedItem.id;
if (!currentSel || (supportedCats.indexOf(selCat) == -1)) { return; }
if (!currentSel || (supportedCats.indexOf(selCat) == -1)) { return; }
saveUpdatedSel(this, selCat, currentSel);
saveUpdatedSel(this, selCat, currentSel);
var acAddonList = AMdoc.getElementById("aomhilite_ac_menu");
var acAddonList = AMdoc.getElementById("aomhilite_ac_menu");
if (!acAddonList || !acAddonList.value) {
if (!acAddonList || !acAddonList.value) {
return;
return;
}
}
if (acAddonList.value.indexOf(this.selectedItem.mAddon.name) < 0) {
if (acAddonList.value.indexOf(this.selectedItem.mAddon.name) < 0) {
acAddonList.value = ""; // clear ac list input field, rather than show name of a now unselected item
acAddonList.value = ""; // clear ac list input field, rather than show name of a now unselected item
}
}
}
}
function onACaddonListSelection() {
function onACaddonListSelection() {
// called when selection made from ac dropdown list or pressing ENTER in input field
// called when selection made from ac dropdown list or pressing ENTER in input field
var AMdoc = this.ownerDocument;
var AMdoc = this.ownerDocument;
var cat = AMdoc.getElementById('categories');
var cat = AMdoc.getElementById('categories');
var selCat = cat.selectedItem.id;
var selCat = cat.selectedItem.id;
var acAddonList = AMdoc.getElementById("aomhilite_ac_menu");
var acAddonList = AMdoc.getElementById("aomhilite_ac_menu");
// setting selectionStart & selectionEnd to same value sets the cursor position to that position
// setting selectionStart & selectionEnd to same value sets the cursor position to that position
// set to beginning so text looks cropped on right instead of on left
// set to beginning so text looks cropped on right instead of on left
acAddonList.inputField.selectionStart = 0;
acAddonList.inputField.selectionStart = 0;
acAddonList.inputField.selectionEnd = 0;
acAddonList.inputField.selectionEnd = 0;
var sel = AMdoc.getElementById("aomhilite_ac_menu").value;
var sel = AMdoc.getElementById("aomhilite_ac_menu").value;
if (UIextra && sel.indexOf("<") == 0 && sel.lastIndexOf(">") == sel.length - 1) {
if (UIextra && sel.indexOf("<") == 0 && sel.lastIndexOf(">") == sel.length - 1) {
sel = sel.slice(1, sel.length - 1); // remove angle brackets
sel = sel.slice(1, sel.length - 1); // remove angle brackets
}
}
if (showVersionNumber) {
if (showVersionNumber) {
let
let
nameEnd = sel.lastIndexOf(spacer);
nameEnd = sel.lastIndexOf(spacer);
if (nameEnd > 0) { // remove spacer and version #, if found (should be there, but...)
if (nameEnd > 0) { // remove spacer and version #, if found (should be there, but...)
sel = sel.slice(0, nameEnd);
sel = sel.slice(0, nameEnd);
}
}
}
}
var addonList = AMdoc.getElementById('addon-list');
var addonList = AMdoc.getElementById('addon-list');
var selAddon = addonList.getElementsByAttribute('name', sel);
var selAddon = addonList.getElementsByAttribute('name', sel);
if (selAddon && selAddon[0]) {
if (selAddon && selAddon[0]) {
var newSelId = selAddon[0].mAddon.id;
var newSelId = selAddon[0].mAddon.id;
if (!newSelId) {
if (!newSelId) {
return;
return;
}
}
saveUpdatedSel(addonList, selCat, newSelId);
saveUpdatedSel(addonList, selCat, newSelId);
var view = AMdoc.getElementById('view-port');
var view = AMdoc.getElementById('view-port');
if (view.getAttribute('selectedIndex') == LISTVIEW) {
if (view.getAttribute('selectedIndex') == LISTVIEW) {
restoreHilite(AMdoc);
restoreHilite(AMdoc);
} else {
} else {
selAddon[0].showInDetailView();
selAddon[0].showInDetailView();
}
}
} else {
} else {
/*
/*
* Workaround issue that occurs when using nav arrow takes us back into detail view of a non-current category,
* Workaround issue that occurs when using nav arrow takes us back into detail view of a non-current category,
* resulting in 'addon-list' element that is no longer populated with the list of add-ons, thus there are no
* resulting in 'addon-list' element that is no longer populated with the list of add-ons, thus there are no
* elements with the name we are looking for
* elements with the name we are looking for
*/
*/
savedAddonName = sel;
savedAddonName = sel;
// repopulates the list, finish workaround in the resulting onViewChange
// repopulates the list, finish workaround in the resulting onViewChange
cat.selectedItem.click();
cat.selectedItem.click();
}
}
}
}
Copia
Copiato
Copia
Copiato
function
onViewChange() {
function
on
//Services.console.logStringMessage("onViewChange called");
var AMdoc = this.document;
var acAddonList = AMdoc.getElementById("aomhilite_ac_menu");
var view = AMdoc.getElementById('view-port');
var cat = AMdoc.getElementById('categories');
var selCat = cat.selectedItem.id;
if (selCat == "category-userstyle") {
dontSort = true;
}
if (view && view.getAttribute('selectedIndex') == LISTVIEW) {
if (savedAddonName) {
// finish workaround from onACaddonListSelection - display add-on in detail view
var addonList = AMdoc.getElementById('addon-list');
// prevents annoying flash of list view before detail view appears
addonList.setAttribute('hidden', true);
var selAddon = addonList.getElementsByAttribute('name', savedAddonName);
if (selAddon && selAddon[0]) {
selAddon[0].showInDetailView();
var newSelId = selAddon[0].mAddon.id;
saveUpdatedSel(addonList, selCat, newSelId);
}
addonList.removeAttribute('hidden');
savedAddonName = null;
// workaround finished, we're now in detail view, which retriggers viewchange
// (if we unexpectedly fail to find add-on for detail view, just continue in list view)
if (selAddon && selAddon[0]) {
return;
}
}
// need to recheck pref, since we're not using pref observer
var prefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService);
prefs = prefs.getBranch("extensions.addonsmgrhilte@cfl.");
doAlphaSort = prefs.getBoolPref("alphaSort");
updatedSort = prefs.getBoolPre
Diff salvati
Testo originale
Apri file
Components.utils.import("resource://gre/modules/AddonManager.jsm"); Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); var doAlphaSort = null; // for pref (alphabetical vs by-state sorting) var updatedSort = false; // for pref (sort by last updated) var dontSort = false; // ignore sort pref in category-userstyles (provides own sorting) var restore = null; // for pref (restore hilite after closing AoM) var showUI = null; // for pref (whether to create/display ac menu) var UIwidth = null; // for pref (ac menu size) var showVersionNumber = null; // for pref (whether to show version number in ac menu) var spacer = " "; var UIextra = null; // for restore-on-demand hidden pref var extraRows = null; var extArray = null; var themeArray = null; var pluginArray = null; var userstyleArray = null; var serviceArray = null; var userscriptArray = null; var savedAddonName = null; var displayDropdown = null; // used for Seamonkey & Tbird workaround const LISTVIEW = 2; const DETAILVIEW = 4; var supportedCats = [ "category-extension", "category-theme", "category-plugin", "category-userstyle", "category-service", "category-greasemonkey-user-script" ]; // from http://erikvold.com/blog/index.cfm/2011/6/14/restartless-firefox-addons-part-6-better-includes // Thanks, Erik! (function(global) { global.include = function include(src) { var o = {}; Components.utils.import("resource://gre/modules/Services.jsm", o); var uri = o.Services.io.newURI(src, null, o.Services.io.newURI(__SCRIPT_URI_SPEC__, null, null)); o.Services.scriptloader.loadSubScript(uri.spec, global); }; })(this); include("components/addonList_autocomplete.js"); function startup(data, reason) { Services.obs.addObserver(ChromeDocObserver, "chrome-document-global-created", false); var defPrefs = Services.prefs.getDefaultBranch("extensions.addonsmgrhilte@cfl."); defPrefs.setBoolPref("restore", true); defPrefs.setBoolPref("alphaSort", false); defPrefs.setBoolPref("updatedSort", false); defPrefs.setBoolPref("extraRows", false); defPrefs.setBoolPref("showUI", true); // should we default this to true now?????? defPrefs.setIntPref("listboxSize", 18); defPrefs.setBoolPref("UIextra", false); defPrefs.setBoolPref("showVersion", false); // register our custom autocomplete component Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar).registerFactory(CLASS_ID, CLASS_NAME, CONTRACT_ID, NSGetFactory(CLASS_ID)); if (reason == ADDON_ENABLE || reason == ADDON_INSTALL) { var mgrs = findAddonsMgrs(); var i; for (i = 0; i < mgrs.length; i++) { mgrs[i].location.reload(); } } } function shutdown(data, reason) { Services.obs.removeObserver(ChromeDocObserver, "chrome-document-global-created"); // call flush due to the bundle service cache (for aomhilite.properties string bundle) Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService) .flushBundles(); // unregister our custom autocomplete component Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar).unregisterFactory(CLASS_ID, NSGetFactory(CLASS_ID)); // remove stylesheets removeStylesheet("chrome://aomhilite/content/aomhilite.css"); removeStylesheet("chrome://aomhilite/content/aomhiliteLG.css"); removeStylesheet("chrome://aomhilite/content/aomhiliteOSX.css"); if (reason == ADDON_DISABLE) { // remove any UI from any open Add-ons Manager tabs and revert to default sorting var mgrs = findAddonsMgrs(); var i; for (i = 0; i < mgrs.length; i++) { AddonsMgrOnUnload.call(mgrs[i]); // reverts to default sort; // also allows aomhilite.xml to be removed from memory w/o waiting for user to close AoM mgrs[i].location.reload(); } } } function install(data, reason) { } function uninstall(data, reason) { // don't remove user's selection when updating ext (as opposed to actual uninstall) if (reason != "ADDON_UNINSTALL") { return; } var RDF = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService); var localstore = RDF.GetDataSource('rdf:local-store'); var subj = RDF.GetResource('about:addons#addon-list'); var pred = RDF.GetResource('aomhilite'); var target = localstore.GetTarget(subj, pred, true); if (target == null) { return; } // if it's an empty string we want to remove it's entry target = target.QueryInterface(Components.interfaces.nsIRDFLiteral); var obj = RDF.GetLiteral(target.Value); localstore.Unassert(subj, pred, obj, true); } function ChromeDocObserver(aSubject, aTopic, aData) { try { if (aTopic != "chrome-document-global-created") { return; } var win = aSubject; var uri = win.document.documentURI; // if Add-ons Manager Dialog Returns add-on is installed, uri will be about:blank until loaded if (uri == "about:addons" || uri == "about:blank") { win.addEventListener("load", AddonsMgrOnload, false); } } catch (e) { Services.console.logStringMessage("Exception in ChromeDocObserver"); } } function AddonsMgrOnload() { // removing this load listener is req'd to prevent mem leak // if we're at about:blank we need to do that *now* // might as well do them all here // listener no longer needed since if the mgr is reloaded via F5, // unload is called, then ChromeDocObserver re-adds the listener this.removeEventListener("load", AddonsMgrOnload, false); if (this.document.documentURI != "about:addons") { return; } this.addEventListener("unload", AddonsMgrOnUnload, false); var AMdoc = this.document; // document obj of Addons Mgr window var addonList = AMdoc.getElementById("addon-list"); var prefs = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefService); prefs = prefs.getBranch("extensions.addonsmgrhilte@cfl."); doAlphaSort = prefs.getBoolPref("alphaSort"); updatedSort = prefs.getBoolPref("updatedSort"); restore = prefs.getBoolPref("restore"); UIextra = prefs.getBoolPref("UIextra"); showUI = prefs.getBoolPref("showUI"); extraRows = prefs.getBoolPref("extraRows"); // restore-on-demand useless if already auto-restored, or the UI not even visible if (restore || !showUI) { UIextra = false; } UIwidth = prefs.getIntPref("listboxSize"); UIwidth = (UIwidth > 50) ? 50 : UIwidth; UIwidth = (UIwidth < 10) ? 10 : UIwidth; if (!restore) { addonList.setAttribute('aomhilite', ""); } this.addEventListener("ViewChanged", onViewChange, false); var cat = AMdoc.getElementById("categories"); if (!cat || !addonList) { return; } var attr = addonList.getAttribute("persist"); // 'persist' enables this info to survive a restart of fx if (!attr) { addonList.setAttribute("persist", "aomhilite"); } else if (attr.indexOf("aomhilite") < 0) { addonList.setAttribute("persist", attr + " aomhilite"); } addonList.addEventListener("select", onSelect, false); // let AoM finish loading list, before attempting potential resort this.setTimeout(function() {initAddonList(AMdoc);}, 0); if (showUI) { this.setTimeout(function() {initUI(AMdoc);}, 100); } } function initAddonList (AMdoc) { //Services.console.logStringMessage("initAddonList called"); // check if we're in list view of a supported category; sort and hilite var cat = AMdoc.getElementById("categories"); var selCat = cat.selectedItem.id; var view = AMdoc.getElementById('view-port'); if ((supportedCats.indexOf(selCat) != -1) && view.getAttribute('selectedIndex') == LISTVIEW) { if (selCat == "category-userstyle" || selCat == "category-greasemonkey-user-script") { dontSort = true; } if (doAlphaSort || updatedSort) { resort(AMdoc); } restoreHilite(AMdoc); } } var addonListener = { onInstalled : function(addon) { updateListboxContents(addon, "add"); updateAllListboxes(); }, /* * due to the 'undo' option remaining available until aom closed/reopened, this won't get called until current * instance (tab) is closed, because that's when the actual uninstall occurs (and when we should remove item from * dropdown list) */ onUninstalled : function(addon) { updateListboxContents(addon, "remove"); updateAllListboxes(); } }; function initUI(AMdoc) { var acListboxStyle = "margin-left: 1em; margin-right: 1em; width: " + UIwidth + "em;"; var acAddonList = AMdoc.createElement("textbox"); acAddonList.setAttribute("id", "aomhilite_ac_menu"); acAddonList.setAttribute("style", acListboxStyle); acAddonList.setAttribute("type", "autocomplete"); // acAddonList.setAttribute("size", 24); // seems to have no effect; set via css width instead acAddonList.setAttribute("autocompletesearch", "addonList_autocomplete"); acAddonList.setAttribute("enablehistory", true); // acAddonList.setAttribute("completedefaultindex", true); acAddonList.setAttribute("forcecomplete", true); // ensures selection is valid // only applies to typing in box; see aomhilite.xml acAddonList.setAttribute("maxrows", 10); // default is about 6 var notifyListbox = "var evt = document.createEvent('Events'); " + "evt.initEvent('textentered', true, true); " + "this.dispatchEvent(evt);"; acAddonList.setAttribute("ontextentered", notifyListbox); var strbundle = Components.classes["@mozilla.org/intl/stringbundle;1"].getService( Components.interfaces.nsIStringBundleService).createBundle("chrome://aomhilite/locale/aomhilite.properties"); var selectaddon = strbundle.GetStringFromName("placeholderString"); acAddonList.setAttribute("placeholder", selectaddon); /* set up stylesheets */ var osString = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULRuntime).OS; addStylesheet("chrome://aomhilite/content/aomhilite.css"); if (osString == "Darwin") { addStylesheet("chrome://aomhilite/content/aomhiliteOSX.css"); } var updateBtn = AMdoc.getElementById("header-utils-btn"); var head = AMdoc.getElementById("header"); head.insertBefore(acAddonList, updateBtn); // prevents "Extension cannot be installed because Nightly cannot modify the needed file" // error when updating this ext (bug 719180) // although 71980 is fixed in fx 19+, using (tested on fx 21.0a1): // acAddonList.style.MozBinding = "url(chrome://aomhilite/content/aomhilite.xml#ac_menu_aomhilite)"; // leaves the aomhilite.xml file in memory even when AoM is closed and aomhilite is disabled! var chromeReg = Components.classes["@mozilla.org/chrome/chrome-registry;1"] .getService(Components.interfaces.nsIChromeRegistry); var ioService = Components.classes["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); var bindingUri; if (extraRows) { bindingUri = ioService.newURI("chrome://aomhilite/content/aomhiliteLG.xml#ac_menu_aomhilite", null, null); } else { bindingUri = ioService.newURI("chrome://aomhilite/content/aomhilite.xml#ac_menu_aomhilite", null, null); } var convertedBindingUri = chromeReg.convertChromeURL(bindingUri); acAddonList.style.MozBinding = 'url("' + convertedBindingUri.spec + '")'; const FIREFOX_ID = "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"; var appInfo = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULAppInfo); if (appInfo.ID != FIREFOX_ID) { // workaround - Seamonkey/Tbird (bug 708520) aren't opening popup by default displayDropdown = function(e) { var id = e.originalTarget.getAttribute("anonid"); if (id != "historydropmarker") { return; } //Services.console.logStringMessage("historydropmarker click"); var acAddonList = e.target.ownerDocument.getElementById("aomhilite_ac_menu") acAddonList.showHistoryPopup(); }; acAddonList.addEventListener("click", displayDropdown, false); } acAddonList.addEventListener("textentered", onACaddonListSelection, false); AddonManager.addAddonListener(addonListener); if (UIextra) { var addonList = AMdoc.getElementById("addon-list"); addonList.setAttribute('restoreondemand', addonList.getAttribute('aomhilite')); } // (do here since addonListCallback will require data initialized above) AddonManager.getAddonsByTypes([ "extension" ], function(addons) { addonListCallback(addons, AMdoc, "extension"); }); AddonManager.getAddonsByTypes([ "theme" ], function(addons) { addonListCallback(addons, AMdoc, "theme"); }); AddonManager.getAddonsByTypes([ "plugin" ], function(addons) { addonListCallback(addons, AMdoc, "plugin"); }); AddonManager.getAddonsByTypes([ "userstyle" ], function(addons) { addonListCallback(addons, AMdoc, "userstyle"); }); AddonManager.getAddonsByTypes([ "service" ], function(addons) { addonListCallback(addons, AMdoc, "service"); }); AddonManager.getAddonsByTypes([ "greasemonkey-user-script" ], function(addons) { addonListCallback(addons, AMdoc, "greasemonkey-user-script"); }); } function addStylesheet(sheet) { var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"] .getService(Components.interfaces.nsIStyleSheetService); var ios = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService); var uri = ios.newURI(sheet, null, null); if (!sss.sheetRegistered(uri, sss.USER_SHEET)) { sss.loadAndRegisterSheet(uri, sss.USER_SHEET); } } function removeStylesheet(sheet) { var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"] .getService(Components.interfaces.nsIStyleSheetService); var ios = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService); var uri = ios.newURI(sheet, null, null); if (sss.sheetRegistered(uri, sss.USER_SHEET)) { sss.unregisterSheet(uri, sss.USER_SHEET); } } function findAddonsMgrs() { // find all open mgrs var mgrs = []; var windows = Services.wm.getEnumerator("navigator:browser"); var window; while (windows.hasMoreElements()) { window = windows.getNext().QueryInterface(Components.interfaces.nsIDOMWindow); window.gBrowser.browsers.forEach(findMgrTab); } function findMgrTab(browser) { if (browser.currentURI.spec == "about:addons") { mgrs.push(browser.contentWindow); } } // Mgr in dialog window (for Add-ons Manager Dialog Returns compatibility) var topWin = Services.wm.getMostRecentWindow(null); if (topWin.document.documentURI == "about:addons") { mgrs.push(topWin); } return mgrs; } function updateListboxContents(addon, action) { if (action != "add" && action != "remove") { return; } var currentArray = null; switch (addon.type) { case "extension": currentArray = extArray; break; case "theme": currentArray = themeArray; break; case "plugin": currentArray = pluginArray; break; case "userstyle": currentArray = userstyleArray; break; case "service": currentArray = serviceArray; case "greasemonkey-user-script": currentArray = userscriptArray; break; default: Services.console.logStringMessage("Addons Manager Hilite encountered an unsupported Add-on type: " + addon.type + " " + addon.name); } var entryFound = false; var element; for (element = 0; element < currentArray.length; element++) { let entry = currentArray[element]; if (entry.indexOf(addon.name) != -1) { // found item entryFound = true; if (showVersionNumber && action == "add") { // version number needs updated var nameVersion = entry.split(spacer, 2); nameVersion[1] = (nameVersion[0].indexOf("<") == 0) ? addon.version + ">" : addon.version; entry = nameVersion.join(spacer); currentArray[element] = entry; } else { if (action == "remove") { currentArray.splice(element, 1); } } // process restoreondemand entry, if any + actual entry if (entry.indexOf("<") != 0) { break; } } // end if found } // end for if (!entryFound && action == "add") { // item not present; needs added var entryToAdd = addon.name; if (showVersionNumber) { entryToAdd = entryToAdd + spacer + addon.version; } currentArray.push(entryToAdd); currentArray.sort(function(addonItem1, addonItem2) { var addon1Name = addonItem1.toLowerCase(); var addon2Name = addonItem2.toLowerCase(); return addon1Name.localeCompare(addon2Name); }); } } function updateAllListboxes() { var mgrs = findAddonsMgrs(); var i; for (i = 0; i < mgrs.length; i++) { var AMdoc = mgrs[i].document; var acAddonList = AMdoc.getElementById("aomhilite_ac_menu"); var cat = AMdoc.getElementById('categories'); var selCat = cat.selectedItem.id; switch (selCat) { // select the proper menulist for the current category case "category-extension": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(extArray)); break; case "category-theme": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(themeArray)); break; case "category-plugin": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(pluginArray)); break; case "category-userstyle": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userstyleArray)); break; case "category-service": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(serviceArray)); case "category-greasemonkey-user-script": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userscriptArray)); break; } } } function restoreHilite(AMdoc) { //Services.console.logStringMessage("restoreHilite called"); // purpose: retrieve saved selection and restore it // content.document does not get document we want if AoM was opened in background via session restore var selAddon; var addonList = AMdoc.getElementById('addon-list'); var savedSelections = addonList.getAttribute('aomhilite'); //Services.console.logStringMessage(savedSelections); var cat = AMdoc.getElementById('categories'); var selCat = cat.selectedItem.id; // category-extension, etc. var selectionArray = savedSelections.split(","); var lastSel = selectionArray[supportedCats.indexOf(selCat)]; if (lastSel) { selAddon = addonList.getElementsByAttribute('value', lastSel); } if (!lastSel || !selAddon || !selAddon[0]) { // no lastSel will occur on newly opened AoM if (always) restore pref is false // otherwise typically occurs when selected category has no installed items or has never had a saved selection var acAddonList = AMdoc.getElementById("aomhilite_ac_menu"); if (acAddonList) { acAddonList.value = ""; } // onSelect not triggered (see below); need to clear this now return; } addonList.selectItem(selAddon[0]); // will trigger onSelect //addonList.scrollBoxObject.scrollToElement(selAddon[0]); selAddon[0].scrollIntoView(); addonList.focus(); } function saveUpdatedSel(addonList, selCat, newSelId) { var savedSelections = addonList.getAttribute('aomhilite'); var selectionArray = savedSelections.split(","); selectionArray[supportedCats.indexOf(selCat)] = newSelId; var updatedSel = selectionArray.toString(); addonList.setAttribute('aomhilite', updatedSel); } function onSelect() { // called once per add-on upon loading mgr, but (this.currentIndex = = -1) at that point // called when clicking an entry in addonList, selecting from autocomplete list, and from restoreHilite funct; also when changing categories? //Services.console.logStringMessage("onSelect called"); //Services.console.logStringMessage(this.id); // addon-list if (this.currentIndex < 0) { return; } // there is no current selected item in this category if (!this.selectedItem) { return; } // avoid 'this.selectedItem is null' error in console (when opening Add-Ons Mgr) var currentSel = this.selectedItem.mAddon.id; var AMdoc = this.ownerDocument; var cat = AMdoc.getElementById('categories'); var selCat = cat.selectedItem.id; if (!currentSel || (supportedCats.indexOf(selCat) == -1)) { return; } saveUpdatedSel(this, selCat, currentSel); var acAddonList = AMdoc.getElementById("aomhilite_ac_menu"); if (!acAddonList || !acAddonList.value) { return; } if (acAddonList.value.indexOf(this.selectedItem.mAddon.name) < 0) { acAddonList.value = ""; // clear ac list input field, rather than show name of a now unselected item } } function onACaddonListSelection() { // called when selection made from ac dropdown list or pressing ENTER in input field var AMdoc = this.ownerDocument; var cat = AMdoc.getElementById('categories'); var selCat = cat.selectedItem.id; var acAddonList = AMdoc.getElementById("aomhilite_ac_menu"); // setting selectionStart & selectionEnd to same value sets the cursor position to that position // set to beginning so text looks cropped on right instead of on left acAddonList.inputField.selectionStart = 0; acAddonList.inputField.selectionEnd = 0; var sel = AMdoc.getElementById("aomhilite_ac_menu").value; if (UIextra && sel.indexOf("<") == 0 && sel.lastIndexOf(">") == sel.length - 1) { sel = sel.slice(1, sel.length - 1); // remove angle brackets } if (showVersionNumber) { let nameEnd = sel.lastIndexOf(spacer); if (nameEnd > 0) { // remove spacer and version #, if found (should be there, but...) sel = sel.slice(0, nameEnd); } } var addonList = AMdoc.getElementById('addon-list'); var selAddon = addonList.getElementsByAttribute('name', sel); if (selAddon && selAddon[0]) { var newSelId = selAddon[0].mAddon.id; if (!newSelId) { return; } saveUpdatedSel(addonList, selCat, newSelId); var view = AMdoc.getElementById('view-port'); if (view.getAttribute('selectedIndex') == LISTVIEW) { restoreHilite(AMdoc); } else { selAddon[0].showInDetailView(); } } else { /* * Workaround issue that occurs when using nav arrow takes us back into detail view of a non-current category, * resulting in 'addon-list' element that is no longer populated with the list of add-ons, thus there are no * elements with the name we are looking for */ savedAddonName = sel; // repopulates the list, finish workaround in the resulting onViewChange cat.selectedItem.click(); } } function onViewChange() { //Services.console.logStringMessage("onViewChange called"); var AMdoc = this.document; var acAddonList = AMdoc.getElementById("aomhilite_ac_menu"); var view = AMdoc.getElementById('view-port'); var cat = AMdoc.getElementById('categories'); var selCat = cat.selectedItem.id; if (selCat == "category-userstyle") { dontSort = true; } if (view && view.getAttribute('selectedIndex') == LISTVIEW) { if (savedAddonName) { // finish workaround from onACaddonListSelection - display add-on in detail view var addonList = AMdoc.getElementById('addon-list'); // prevents annoying flash of list view before detail view appears addonList.setAttribute('hidden', true); var selAddon = addonList.getElementsByAttribute('name', savedAddonName); if (selAddon && selAddon[0]) { selAddon[0].showInDetailView(); var newSelId = selAddon[0].mAddon.id; saveUpdatedSel(addonList, selCat, newSelId); } addonList.removeAttribute('hidden'); savedAddonName = null; // workaround finished, we're now in detail view, which retriggers viewchange // (if we unexpectedly fail to find add-on for detail view, just continue in list view) if (selAddon && selAddon[0]) { return; } } // need to recheck pref, since we're not using pref observer var prefs = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefService); prefs = prefs.getBranch("extensions.addonsmgrhilte@cfl."); doAlphaSort = prefs.getBoolPref("alphaSort"); updatedSort = prefs.getBoolPref("updatedSort"); if (doAlphaSort || updatedSort) { resort(AMdoc); } restoreHilite(AMdoc); } else if (view && view.getAttribute('selectedIndex') == DETAILVIEW) { // if we are in this ext's detail view if (AMdoc.getElementById("detail-name").textContent == "Addons Manager Hilite") { // set input field of numeric setting to sensible size & disable if not applicable var setting = AMdoc.getElementById("aomhilite_size"); var inputField = AMdoc.getAnonymousElementByAttribute(setting, "anonid", "input"); inputField.setAttribute("style", "max-width: 3em;"); } } // if our menu has not been created yet or the UI is pref'ed off, nothing else to do if (!acAddonList) { return; } switch (selCat) { // select the proper menulist for the current category case "category-extension": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(extArray)); break; case "category-theme": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(themeArray)); break; case "category-plugin": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(pluginArray)); break; case "category-userstyle": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userstyleArray)); break; case "category-service": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(serviceArray)); case "category-greasemonkey-user-script": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userscriptArray)); break; default: acAddonList.setAttribute('hidden', 'true'); // hide UI in unsupported cats return; } acAddonList.removeAttribute('hidden'); // show UI } function resort(AMdoc) { //Services.console.logStringMessage("resort called"); // use alphabetical (or optionally updated) sort instead of by-state sort implemented by Bug 624808 if (dontSort) { dontSort = false; return; } var addonList = AMdoc.getElementById("addon-list"); if (!updatedSort) { var sortby = [ "name" ]; AMdoc.defaultView.sortList(addonList, sortby, true); // true = ascending return; } // most recently updated var list = addonList.children; list.sort(function(addonItem1, addonItem2) { var addon1Time = Date.parse(addonItem1.mAddon.updateDate); var addon2Time = Date.parse(addonItem2.mAddon.updateDate); if (addon1Time > addon2Time) { return -1; } if (addon1Time < addon2Time) { return 1; } var addon1Name = addonItem1.mAddon.name.toLowerCase(); var addon2Name = addonItem2.mAddon.name.toLowerCase(); return addon1Name.localeCompare(addon2Name); }); var i; for (i = 0; i < list.length; i++) { addonList.appendChild(list[i]); } } function addonListCallback(addons, AMdoc, addonType) { var addonList = AMdoc.getElementById("addon-list"); var prevHilite = addonList.getAttribute("restoreondemand"); var hiliteArray = prevHilite.split(","); var currentArray = null; var currentCat = null; addons.sort(function(addonItem1, addonItem2) { var addon1Name = addonItem1.name.toLowerCase(); var addon2Name = addonItem2.name.toLowerCase(); return addon1Name.localeCompare(addon2Name); }); switch (addonType) { case "extension": extArray = []; currentArray = extArray; currentCat = "category-extension"; break; case "theme": themeArray = []; currentArray = themeArray; currentCat = "category-theme"; break; case "plugin": pluginArray = []; currentArray = pluginArray; currentCat = "category-plugin"; break; case "userstyle": userstyleArray = []; currentArray = userstyleArray; currentCat = "category-userstyle"; break; case "service": serviceArray = []; currentArray = serviceArray; currentCat = "category-service"; case "greasemonkey-user-script": userscriptArray = []; currentArray = userscriptArray; currentCat = "category-greasemonkey-user-script"; break; } var i; // need to recheck pref, since we're not using pref observer var prefs = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefService); prefs = prefs.getBranch("extensions.addonsmgrhilte@cfl."); showVersionNumber = prefs.getBoolPref("showVersion"); for (i = 0; i < addons.length; i++) { if (showVersionNumber && addons[i].version) { currentArray.push(addons[i].name + spacer + addons[i].version); } else { currentArray.push(addons[i].name); } // for vers # opt off if (UIextra && hiliteArray[supportedCats.indexOf(currentCat)] == addons[i].id) { // if this is the previously hilited item, add it to the top of list for easy access var entry = "<" + addons[i].name; if (showVersionNumber) { entry = entry + spacer + addons[i].version; } entry = entry + ">"; currentArray.unshift(entry); } } // wait for all 6 requests to arrive if (!extArray || !themeArray || !pluginArray || !userstyleArray || !serviceArray || !userscriptArray) { return; } var acAddonList = AMdoc.getElementById("aomhilite_ac_menu"); var cat = AMdoc.getElementById("categories"); var selCat = cat.selectedItem.id; if (acAddonList) { switch (selCat) { case "category-extension": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(extArray)); break; case "category-theme": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(themeArray)); break; case "category-plugin": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(pluginArray)); break; case "category-userstyle": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userstyleArray)); break; case "category-service": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(serviceArray)); case "category-greasemonkey-user-script": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userscriptArray)); break; } } if (acAddonList && supportedCats.indexOf(selCat) != -1) { acAddonList.removeAttribute('hidden'); // hide ac menu in unsupported categories } else if (acAddonList) { acAddonList.setAttribute('hidden', true); } } function AddonsMgrOnUnload() { AddonManager.removeAddonListener(addonListener); this.removeEventListener("unload", AddonsMgrOnUnload, false); this.removeEventListener("ViewChanged", onViewChange, false); var addonList = this.document.getElementById("addon-list"); addonList.removeEventListener("select", onSelect, false); var acAddonList = this.document.getElementById("aomhilite_ac_menu"); if (acAddonList) { acAddonList.removeEventListener("textentered", onACaddonListSelection, false); acAddonList.removeEventListener("change", onACaddonListSelection, false); acAddonList.popup.removeEventListener("click", onACaddonListSelection, false); var arrow = this.document.getAnonymousElementByAttribute(acAddonList, "anonid", "historydropmarker"); if (arrow && displayDropdown) { arrow.removeEventListener("click", displayDropdown, false); displayDropdown = null; } var head = this.document.getElementById("header"); head.removeChild(acAddonList); } if (UIextra && addonList.hasAttribute("restoreondemand")) { // save needed info to aomhite so it will survive fx restart var savedSelections = addonList.getAttribute('aomhilite'); var selectionArray = savedSelections.split(","); var prevHilites = addonList.getAttribute('restoreondemand'); var hiliteArray = prevHilites.split(","); // save previous category selections until new ones have been made var i; for (i = 0; i < hiliteArray.length; i++) { if (hiliteArray[i] && !selectionArray[i]) { selectionArray[i] = hiliteArray[i]; } } var selectionsToSave = selectionArray.toString(); addonList.setAttribute('aomhilite', selectionsToSave); } extArray = null; themeArray = null; pluginArray = null; userstyleArray = null; serviceArray = null; userscriptArray = null; }
Testo modificato
Apri file
Components.utils.import("resource://gre/modules/AddonManager.jsm"); Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); var doAlphaSort = null; // for pref (alphabetical vs by-state sorting) var updatedSort = false; // for pref (sort by last updated) var dontSort = false; // ignore sort pref in category-userstyles (provides own sorting) var restore = null; // for pref (restore hilite after closing AoM) var showUI = null; // for pref (whether to create/display ac menu) var UIwidth = null; // for pref (ac menu size) var showVersionNumber = null; // for pref (whether to show version number in ac menu) var spacer = " "; var UIextra = null; // for restore-on-demand hidden pref var extraRows = null; var extArray = null; var themeArray = null; var pluginArray = null; var userstyleArray = null; var serviceArray = null; var userscriptArray = null; var scriptishArray = null; var custombuttonsArray = null; var dictionaryArray = null; var localeArray = null; var savedAddonName = null; var displayDropdown = null; // used for Seamonkey & Tbird workaround const LISTVIEW = 2; const DETAILVIEW = 4; var supportedCats = [ "category-extension", "category-theme", "category-plugin", "category-userstyle", "category-service", "category-greasemonkey-user-script", "category-userscript", "category-custombuttons", "category-dictionary", "category-locale" ]; // from http://erikvold.com/blog/index.cfm/2011/6/14/restartless-firefox-addons-part-6-better-includes // Thanks, Erik! (function(global) { global.include = function include(src) { var o = {}; Components.utils.import("resource://gre/modules/Services.jsm", o); var uri = o.Services.io.newURI(src, null, o.Services.io.newURI(__SCRIPT_URI_SPEC__, null, null)); o.Services.scriptloader.loadSubScript(uri.spec, global); }; })(this); include("components/addonList_autocomplete.js"); function startup(data, reason) { Services.obs.addObserver(ChromeDocObserver, "chrome-document-global-created", false); var defPrefs = Services.prefs.getDefaultBranch("extensions.addonsmgrhilte@cfl."); defPrefs.setBoolPref("restore", true); defPrefs.setBoolPref("alphaSort", false); defPrefs.setBoolPref("updatedSort", false); defPrefs.setBoolPref("extraRows", false); defPrefs.setBoolPref("showUI", true); // should we default this to true now?????? defPrefs.setIntPref("listboxSize", 18); defPrefs.setBoolPref("UIextra", false); defPrefs.setBoolPref("showVersion", false); // register our custom autocomplete component Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar).registerFactory(CLASS_ID, CLASS_NAME, CONTRACT_ID, NSGetFactory(CLASS_ID)); if (reason == ADDON_ENABLE || reason == ADDON_INSTALL) { var mgrs = findAddonsMgrs(); var i; for (i = 0; i < mgrs.length; i++) { mgrs[i].location.reload(); } } } function shutdown(data, reason) { Services.obs.removeObserver(ChromeDocObserver, "chrome-document-global-created"); // call flush due to the bundle service cache (for aomhilite.properties string bundle) Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService) .flushBundles(); // unregister our custom autocomplete component Components.manager.QueryInterface(Components.interfaces.nsIComponentRegistrar).unregisterFactory(CLASS_ID, NSGetFactory(CLASS_ID)); // remove stylesheets removeStylesheet("chrome://aomhilite/content/aomhilite.css"); removeStylesheet("chrome://aomhilite/content/aomhiliteLG.css"); removeStylesheet("chrome://aomhilite/content/aomhiliteOSX.css"); if (reason == ADDON_DISABLE) { // remove any UI from any open Add-ons Manager tabs and revert to default sorting var mgrs = findAddonsMgrs(); var i; for (i = 0; i < mgrs.length; i++) { AddonsMgrOnUnload.call(mgrs[i]); // reverts to default sort; // also allows aomhilite.xml to be removed from memory w/o waiting for user to close AoM mgrs[i].location.reload(); } } } function install(data, reason) { } function uninstall(data, reason) { // don't remove user's selection when updating ext (as opposed to actual uninstall) if (reason != "ADDON_UNINSTALL") { return; } var RDF = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService); var localstore = RDF.GetDataSource('rdf:local-store'); var subj = RDF.GetResource('about:addons#addon-list'); var pred = RDF.GetResource('aomhilite'); var target = localstore.GetTarget(subj, pred, true); if (target == null) { return; } // if it's an empty string we want to remove it's entry target = target.QueryInterface(Components.interfaces.nsIRDFLiteral); var obj = RDF.GetLiteral(target.Value); localstore.Unassert(subj, pred, obj, true); } function ChromeDocObserver(aSubject, aTopic, aData) { try { if (aTopic != "chrome-document-global-created") { return; } var win = aSubject; var uri = win.document.documentURI; // if Add-ons Manager Dialog Returns add-on is installed, uri will be about:blank until loaded if (uri == "about:addons" || uri == "about:blank") { win.addEventListener("load", AddonsMgrOnload, false); } } catch (e) { Services.console.logStringMessage("Exception in ChromeDocObserver"); } } function AddonsMgrOnload() { // removing this load listener is req'd to prevent mem leak // if we're at about:blank we need to do that *now* // might as well do them all here // listener no longer needed since if the mgr is reloaded via F5, // unload is called, then ChromeDocObserver re-adds the listener this.removeEventListener("load", AddonsMgrOnload, false); if (this.document.documentURI != "about:addons") { return; } this.addEventListener("unload", AddonsMgrOnUnload, false); var AMdoc = this.document; // document obj of Addons Mgr window var addonList = AMdoc.getElementById("addon-list"); var prefs = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefService); prefs = prefs.getBranch("extensions.addonsmgrhilte@cfl."); doAlphaSort = prefs.getBoolPref("alphaSort"); updatedSort = prefs.getBoolPref("updatedSort"); restore = prefs.getBoolPref("restore"); UIextra = prefs.getBoolPref("UIextra"); showUI = prefs.getBoolPref("showUI"); extraRows = prefs.getBoolPref("extraRows"); // restore-on-demand useless if already auto-restored, or the UI not even visible if (restore || !showUI) { UIextra = false; } UIwidth = prefs.getIntPref("listboxSize"); UIwidth = (UIwidth > 50) ? 50 : UIwidth; UIwidth = (UIwidth < 10) ? 10 : UIwidth; if (!restore) { addonList.setAttribute('aomhilite', ""); } this.addEventListener("ViewChanged", onViewChange, false); var cat = AMdoc.getElementById("categories"); if (!cat || !addonList) { return; } var attr = addonList.getAttribute("persist"); // 'persist' enables this info to survive a restart of fx if (!attr) { addonList.setAttribute("persist", "aomhilite"); } else if (attr.indexOf("aomhilite") < 0) { addonList.setAttribute("persist", attr + " aomhilite"); } addonList.addEventListener("select", onSelect, false); // let AoM finish loading list, before attempting potential resort this.setTimeout(function() {initAddonList(AMdoc);}, 0); if (showUI) { this.setTimeout(function() {initUI(AMdoc);}, 100); } } function initAddonList (AMdoc) { //Services.console.logStringMessage("initAddonList called"); // check if we're in list view of a supported category; sort and hilite var cat = AMdoc.getElementById("categories"); var selCat = cat.selectedItem.id; var view = AMdoc.getElementById('view-port'); if ((supportedCats.indexOf(selCat) != -1) && view.getAttribute('selectedIndex') == LISTVIEW) { if (selCat == "category-userstyle" || selCat == "category-greasemonkey-user-script") { dontSort = true; } if (doAlphaSort || updatedSort) { resort(AMdoc); } restoreHilite(AMdoc); } } var addonListener = { onInstalled : function(addon) { updateListboxContents(addon, "add"); updateAllListboxes(); }, /* * due to the 'undo' option remaining available until aom closed/reopened, this won't get called until current * instance (tab) is closed, because that's when the actual uninstall occurs (and when we should remove item from * dropdown list) */ onUninstalled : function(addon) { updateListboxContents(addon, "remove"); updateAllListboxes(); } }; function initUI(AMdoc) { var acListboxStyle = "margin-left: 1em; margin-right: 1em; width: " + UIwidth + "em;"; var acAddonList = AMdoc.createElement("textbox"); acAddonList.setAttribute("id", "aomhilite_ac_menu"); acAddonList.setAttribute("style", acListboxStyle); acAddonList.setAttribute("type", "autocomplete"); // acAddonList.setAttribute("size", 24); // seems to have no effect; set via css width instead acAddonList.setAttribute("autocompletesearch", "addonList_autocomplete"); acAddonList.setAttribute("enablehistory", true); // acAddonList.setAttribute("completedefaultindex", true); acAddonList.setAttribute("forcecomplete", true); // ensures selection is valid // only applies to typing in box; see aomhilite.xml acAddonList.setAttribute("maxrows", 10); // default is about 6 var notifyListbox = "var evt = document.createEvent('Events'); " + "evt.initEvent('textentered', true, true); " + "this.dispatchEvent(evt);"; acAddonList.setAttribute("ontextentered", notifyListbox); var strbundle = Components.classes["@mozilla.org/intl/stringbundle;1"].getService( Components.interfaces.nsIStringBundleService).createBundle("chrome://aomhilite/locale/aomhilite.properties"); var selectaddon = strbundle.GetStringFromName("placeholderString"); acAddonList.setAttribute("placeholder", selectaddon); /* set up stylesheets */ var osString = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULRuntime).OS; addStylesheet("chrome://aomhilite/content/aomhilite.css"); if (osString == "Darwin") { addStylesheet("chrome://aomhilite/content/aomhiliteOSX.css"); } var updateBtn = AMdoc.getElementById("header-utils-btn"); var head = AMdoc.getElementById("header"); head.insertBefore(acAddonList, updateBtn); // prevents "Extension cannot be installed because Nightly cannot modify the needed file" // error when updating this ext (bug 719180) // although 71980 is fixed in fx 19+, using (tested on fx 21.0a1): // acAddonList.style.MozBinding = "url(chrome://aomhilite/content/aomhilite.xml#ac_menu_aomhilite)"; // leaves the aomhilite.xml file in memory even when AoM is closed and aomhilite is disabled! var chromeReg = Components.classes["@mozilla.org/chrome/chrome-registry;1"] .getService(Components.interfaces.nsIChromeRegistry); var ioService = Components.classes["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService); var bindingUri; if (extraRows) { bindingUri = ioService.newURI("chrome://aomhilite/content/aomhiliteLG.xml#ac_menu_aomhilite", null, null); } else { bindingUri = ioService.newURI("chrome://aomhilite/content/aomhilite.xml#ac_menu_aomhilite", null, null); } var convertedBindingUri = chromeReg.convertChromeURL(bindingUri); acAddonList.style.MozBinding = 'url("' + convertedBindingUri.spec + '")'; const FIREFOX_ID = "{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"; var appInfo = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULAppInfo); if (appInfo.ID != FIREFOX_ID) { // workaround - Seamonkey/Tbird (bug 708520) aren't opening popup by default displayDropdown = function(e) { var id = e.originalTarget.getAttribute("anonid"); if (id != "historydropmarker") { return; } //Services.console.logStringMessage("historydropmarker click"); var acAddonList = e.target.ownerDocument.getElementById("aomhilite_ac_menu") acAddonList.showHistoryPopup(); }; acAddonList.addEventListener("click", displayDropdown, false); } acAddonList.addEventListener("textentered", onACaddonListSelection, false); AddonManager.addAddonListener(addonListener); if (UIextra) { var addonList = AMdoc.getElementById("addon-list"); addonList.setAttribute('restoreondemand', addonList.getAttribute('aomhilite')); } // (do here since addonListCallback will require data initialized above) AddonManager.getAddonsByTypes([ "extension" ], function(addons) { addonListCallback(addons, AMdoc, "extension"); }); AddonManager.getAddonsByTypes([ "theme" ], function(addons) { addonListCallback(addons, AMdoc, "theme"); }); AddonManager.getAddonsByTypes([ "plugin" ], function(addons) { addonListCallback(addons, AMdoc, "plugin"); }); AddonManager.getAddonsByTypes([ "userstyle" ], function(addons) { addonListCallback(addons, AMdoc, "userstyle"); }); AddonManager.getAddonsByTypes([ "service" ], function(addons) { addonListCallback(addons, AMdoc, "service"); }); AddonManager.getAddonsByTypes([ "greasemonkey-user-script" ], function(addons) { addonListCallback(addons, AMdoc, "greasemonkey-user-script"); }); // Scriptish AddonManager.getAddonsByTypes([ "userscript" ], function(addons) { addonListCallback(addons, AMdoc, "userscript"); }); // Custom Buttons AddonManager.getAddonsByTypes([ "custombuttons" ], function(addons) { addonListCallback(addons, AMdoc, "custombuttons"); }); AddonManager.getAddonsByTypes([ "dictionary" ], function(addons) { addonListCallback(addons, AMdoc, "dictionary"); }); AddonManager.getAddonsByTypes([ "locale" ], function(addons) { addonListCallback(addons, AMdoc, "locale"); }); } function addStylesheet(sheet) { var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"] .getService(Components.interfaces.nsIStyleSheetService); var ios = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService); var uri = ios.newURI(sheet, null, null); if (!sss.sheetRegistered(uri, sss.USER_SHEET)) { sss.loadAndRegisterSheet(uri, sss.USER_SHEET); } } function removeStylesheet(sheet) { var sss = Components.classes["@mozilla.org/content/style-sheet-service;1"] .getService(Components.interfaces.nsIStyleSheetService); var ios = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService); var uri = ios.newURI(sheet, null, null); if (sss.sheetRegistered(uri, sss.USER_SHEET)) { sss.unregisterSheet(uri, sss.USER_SHEET); } } function findAddonsMgrs() { // find all open mgrs var mgrs = []; var windows = Services.wm.getEnumerator("navigator:browser"); var window; while (windows.hasMoreElements()) { window = windows.getNext().QueryInterface(Components.interfaces.nsIDOMWindow); window.gBrowser.browsers.forEach(findMgrTab); } function findMgrTab(browser) { if (browser.currentURI.spec == "about:addons") { mgrs.push(browser.contentWindow); } } // Mgr in dialog window (for Add-ons Manager Dialog Returns compatibility) var topWin = Services.wm.getMostRecentWindow(null); if (topWin.document.documentURI == "about:addons") { mgrs.push(topWin); } return mgrs; } function updateListboxContents(addon, action) { if (action != "add" && action != "remove") { return; } var currentArray = null; switch (addon.type) { case "extension": currentArray = extArray; break; case "theme": currentArray = themeArray; break; case "plugin": currentArray = pluginArray; break; case "userstyle": currentArray = userstyleArray; break; case "service": currentArray = serviceArray; break; case "greasemonkey-user-script": currentArray = userscriptArray; break; case "userscript": currentArray = scriptishArray; break; case "custombuttons": currentArray = custombuttonsArray; break; case "dictionary": currentArray = dictionaryArray; break; case "locale": currentArray = localeArray; break; default: Services.console.logStringMessage("Addons Manager Hilite encountered an unsupported Add-on type: " + addon.type + " " + addon.name); } var entryFound = false; var element; for (element = 0; element < currentArray.length; element++) { let entry = currentArray[element]; if (entry.indexOf(addon.name) != -1) { // found item entryFound = true; if (showVersionNumber && action == "add") { // version number needs updated var nameVersion = entry.split(spacer, 2); nameVersion[1] = (nameVersion[0].indexOf("<") == 0) ? addon.version + ">" : addon.version; entry = nameVersion.join(spacer); currentArray[element] = entry; } else { if (action == "remove") { currentArray.splice(element, 1); } } // process restoreondemand entry, if any + actual entry if (entry.indexOf("<") != 0) { break; } } // end if found } // end for if (!entryFound && action == "add") { // item not present; needs added var entryToAdd = addon.name; if (showVersionNumber) { entryToAdd = entryToAdd + spacer + addon.version; } currentArray.push(entryToAdd); currentArray.sort(function(addonItem1, addonItem2) { var addon1Name = addonItem1.toLowerCase(); var addon2Name = addonItem2.toLowerCase(); return addon1Name.localeCompare(addon2Name); }); } } function updateAllListboxes() { var mgrs = findAddonsMgrs(); var i; for (i = 0; i < mgrs.length; i++) { var AMdoc = mgrs[i].document; var acAddonList = AMdoc.getElementById("aomhilite_ac_menu"); var cat = AMdoc.getElementById('categories'); var selCat = cat.selectedItem.id; switch (selCat) { // select the proper menulist for the current category case "category-extension": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(extArray)); break; case "category-theme": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(themeArray)); break; case "category-plugin": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(pluginArray)); break; case "category-userstyle": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userstyleArray)); break; case "category-service": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(serviceArray)); break; case "category-greasemonkey-user-script": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userscriptArray)); break; case "category-userscript": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(scriptishArray)); break; case "category-custombuttons": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(custombuttonsArray)); break; case "category-dictionary": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(dictionaryArray)); break; case "category-locale": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(localeArray)); break; } } } function restoreHilite(AMdoc) { //Services.console.logStringMessage("restoreHilite called"); // purpose: retrieve saved selection and restore it // content.document does not get document we want if AoM was opened in background via session restore var selAddon; var addonList = AMdoc.getElementById('addon-list'); var savedSelections = addonList.getAttribute('aomhilite'); //Services.console.logStringMessage(savedSelections); var cat = AMdoc.getElementById('categories'); var selCat = cat.selectedItem.id; // category-extension, etc. var selectionArray = savedSelections.split(","); var lastSel = selectionArray[supportedCats.indexOf(selCat)]; if (lastSel) { selAddon = addonList.getElementsByAttribute('value', lastSel); } if (!lastSel || !selAddon || !selAddon[0]) { // no lastSel will occur on newly opened AoM if (always) restore pref is false // otherwise typically occurs when selected category has no installed items or has never had a saved selection var acAddonList = AMdoc.getElementById("aomhilite_ac_menu"); if (acAddonList) { acAddonList.value = ""; } // onSelect not triggered (see below); need to clear this now return; } addonList.selectItem(selAddon[0]); // will trigger onSelect //addonList.scrollBoxObject.scrollToElement(selAddon[0]); selAddon[0].scrollIntoView(); addonList.focus(); } function saveUpdatedSel(addonList, selCat, newSelId) { var savedSelections = addonList.getAttribute('aomhilite'); var selectionArray = savedSelections.split(","); selectionArray[supportedCats.indexOf(selCat)] = newSelId; var updatedSel = selectionArray.toString(); addonList.setAttribute('aomhilite', updatedSel); } function onSelect() { // called once per add-on upon loading mgr, but (this.currentIndex = = -1) at that point // called when clicking an entry in addonList, selecting from autocomplete list, and from restoreHilite funct; also when changing categories? //Services.console.logStringMessage("onSelect called"); //Services.console.logStringMessage(this.id); // addon-list if (this.currentIndex < 0) { return; } // there is no current selected item in this category if (!this.selectedItem) { return; } // avoid 'this.selectedItem is null' error in console (when opening Add-Ons Mgr) var currentSel = this.selectedItem.mAddon.id; var AMdoc = this.ownerDocument; var cat = AMdoc.getElementById('categories'); var selCat = cat.selectedItem.id; if (!currentSel || (supportedCats.indexOf(selCat) == -1)) { return; } saveUpdatedSel(this, selCat, currentSel); var acAddonList = AMdoc.getElementById("aomhilite_ac_menu"); if (!acAddonList || !acAddonList.value) { return; } if (acAddonList.value.indexOf(this.selectedItem.mAddon.name) < 0) { acAddonList.value = ""; // clear ac list input field, rather than show name of a now unselected item } } function onACaddonListSelection() { // called when selection made from ac dropdown list or pressing ENTER in input field var AMdoc = this.ownerDocument; var cat = AMdoc.getElementById('categories'); var selCat = cat.selectedItem.id; var acAddonList = AMdoc.getElementById("aomhilite_ac_menu"); // setting selectionStart & selectionEnd to same value sets the cursor position to that position // set to beginning so text looks cropped on right instead of on left acAddonList.inputField.selectionStart = 0; acAddonList.inputField.selectionEnd = 0; var sel = AMdoc.getElementById("aomhilite_ac_menu").value; if (UIextra && sel.indexOf("<") == 0 && sel.lastIndexOf(">") == sel.length - 1) { sel = sel.slice(1, sel.length - 1); // remove angle brackets } if (showVersionNumber) { let nameEnd = sel.lastIndexOf(spacer); if (nameEnd > 0) { // remove spacer and version #, if found (should be there, but...) sel = sel.slice(0, nameEnd); } } var addonList = AMdoc.getElementById('addon-list'); var selAddon = addonList.getElementsByAttribute('name', sel); if (selAddon && selAddon[0]) { var newSelId = selAddon[0].mAddon.id; if (!newSelId) { return; } saveUpdatedSel(addonList, selCat, newSelId); var view = AMdoc.getElementById('view-port'); if (view.getAttribute('selectedIndex') == LISTVIEW) { restoreHilite(AMdoc); } else { selAddon[0].showInDetailView(); } } else { /* * Workaround issue that occurs when using nav arrow takes us back into detail view of a non-current category, * resulting in 'addon-list' element that is no longer populated with the list of add-ons, thus there are no * elements with the name we are looking for */ savedAddonName = sel; // repopulates the list, finish workaround in the resulting onViewChange cat.selectedItem.click(); } } function onViewChange() { //Services.console.logStringMessage("onViewChange called"); var AMdoc = this.document; var acAddonList = AMdoc.getElementById("aomhilite_ac_menu"); var view = AMdoc.getElementById('view-port'); var cat = AMdoc.getElementById('categories'); var selCat = cat.selectedItem.id; if (selCat == "category-userstyle") { dontSort = true; } if (view && view.getAttribute('selectedIndex') == LISTVIEW) { if (savedAddonName) { // finish workaround from onACaddonListSelection - display add-on in detail view var addonList = AMdoc.getElementById('addon-list'); // prevents annoying flash of list view before detail view appears addonList.setAttribute('hidden', true); var selAddon = addonList.getElementsByAttribute('name', savedAddonName); if (selAddon && selAddon[0]) { selAddon[0].showInDetailView(); var newSelId = selAddon[0].mAddon.id; saveUpdatedSel(addonList, selCat, newSelId); } addonList.removeAttribute('hidden'); savedAddonName = null; // workaround finished, we're now in detail view, which retriggers viewchange // (if we unexpectedly fail to find add-on for detail view, just continue in list view) if (selAddon && selAddon[0]) { return; } } // need to recheck pref, since we're not using pref observer var prefs = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefService); prefs = prefs.getBranch("extensions.addonsmgrhilte@cfl."); doAlphaSort = prefs.getBoolPref("alphaSort"); updatedSort = prefs.getBoolPref("updatedSort"); if (doAlphaSort || updatedSort) { resort(AMdoc); } restoreHilite(AMdoc); } else if (view && view.getAttribute('selectedIndex') == DETAILVIEW) { // if we are in this ext's detail view if (AMdoc.getElementById("detail-name").textContent == "Addons Manager Hilite") { // set input field of numeric setting to sensible size & disable if not applicable var setting = AMdoc.getElementById("aomhilite_size"); var inputField = AMdoc.getAnonymousElementByAttribute(setting, "anonid", "input"); inputField.setAttribute("style", "max-width: 3em;"); } } // if our menu has not been created yet or the UI is pref'ed off, nothing else to do if (!acAddonList) { return; } switch (selCat) { // select the proper menulist for the current category case "category-extension": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(extArray)); break; case "category-theme": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(themeArray)); break; case "category-plugin": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(pluginArray)); break; case "category-userstyle": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userstyleArray)); break; case "category-service": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(serviceArray)); break; case "category-greasemonkey-user-script": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userscriptArray)); break; case "category-userscript": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(scriptishArray)); break; case "category-custombuttons": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(custombuttonsArray)); break; case "category-dictionary": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(dictionaryArray)); break; case "category-locale": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(localeArray)); break; default: acAddonList.setAttribute('hidden', 'true'); // hide UI in unsupported cats return; } acAddonList.removeAttribute('hidden'); // show UI } function resort(AMdoc) { //Services.console.logStringMessage("resort called"); // use alphabetical (or optionally updated) sort instead of by-state sort implemented by Bug 624808 if (dontSort) { dontSort = false; return; } var addonList = AMdoc.getElementById("addon-list"); if (!updatedSort) { var sortby = [ "name" ]; AMdoc.defaultView.sortList(addonList, sortby, true); // true = ascending return; } // most recently updated var list = addonList.children; list.sort(function(addonItem1, addonItem2) { var addon1Time = Date.parse(addonItem1.mAddon.updateDate); var addon2Time = Date.parse(addonItem2.mAddon.updateDate); if (addon1Time > addon2Time) { return -1; } if (addon1Time < addon2Time) { return 1; } var addon1Name = addonItem1.mAddon.name.toLowerCase(); var addon2Name = addonItem2.mAddon.name.toLowerCase(); return addon1Name.localeCompare(addon2Name); }); var i; for (i = 0; i < list.length; i++) { addonList.appendChild(list[i]); } } function addonListCallback(addons, AMdoc, addonType) { var addonList = AMdoc.getElementById("addon-list"); var prevHilite = addonList.getAttribute("restoreondemand"); var hiliteArray = prevHilite.split(","); var currentArray = null; var currentCat = null; addons.sort(function(addonItem1, addonItem2) { var addon1Name = addonItem1.name.toLowerCase(); var addon2Name = addonItem2.name.toLowerCase(); return addon1Name.localeCompare(addon2Name); }); switch (addonType) { case "extension": extArray = []; currentArray = extArray; currentCat = "category-extension"; break; case "theme": themeArray = []; currentArray = themeArray; currentCat = "category-theme"; break; case "plugin": pluginArray = []; currentArray = pluginArray; currentCat = "category-plugin"; break; case "userstyle": userstyleArray = []; currentArray = userstyleArray; currentCat = "category-userstyle"; break; case "service": serviceArray = []; currentArray = serviceArray; currentCat = "category-service"; break; case "greasemonkey-user-script": userscriptArray = []; currentArray = userscriptArray; currentCat = "category-greasemonkey-user-script"; break; case "userscript": scriptishArray = []; currentArray = scriptishArray; currentCat = "category-userscript"; break; case "custombuttons": custombuttonsArray = []; currentArray = custombuttonsArray; currentCat = "category-custombuttons"; break; case "dictionary": dictionaryArray = []; currentArray = dictionaryArray; currentCat = "category-dictionary"; break; case "locale": localeArray = []; currentArray = localeArray; currentCat = "category-locale"; break; } var i; // need to recheck pref, since we're not using pref observer var prefs = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefService); prefs = prefs.getBranch("extensions.addonsmgrhilte@cfl."); showVersionNumber = prefs.getBoolPref("showVersion"); for (i = 0; i < addons.length; i++) { if (showVersionNumber && addons[i].version) { currentArray.push(addons[i].name + spacer + addons[i].version); } else { currentArray.push(addons[i].name); } // for vers # opt off if (UIextra && hiliteArray[supportedCats.indexOf(currentCat)] == addons[i].id) { // if this is the previously hilited item, add it to the top of list for easy access var entry = "<" + addons[i].name; if (showVersionNumber) { entry = entry + spacer + addons[i].version; } entry = entry + ">"; currentArray.unshift(entry); } } // wait for all 6 requests to arrive if (!(extArray || themeArray || pluginArray || userstyleArray || serviceArray || userscriptArray || scriptishArray || custombuttonsArray || dictionaryArray || localeArray)) { return; } var acAddonList = AMdoc.getElementById("aomhilite_ac_menu"); var cat = AMdoc.getElementById("categories"); var selCat = cat.selectedItem.id; if (acAddonList) { switch (selCat) { case "category-extension": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(extArray)); break; case "category-theme": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(themeArray)); break; case "category-plugin": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(pluginArray)); break; case "category-userstyle": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userstyleArray)); break; case "category-service": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(serviceArray)); break; case "category-greasemonkey-user-script": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(userscriptArray)); break; case "category-userscript": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(scriptishArray)); break; case "category-custombuttons": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(custombuttonsArray)); break; case "category-dictionary": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(dictionaryArray)); break; case "category-locale": acAddonList.setAttribute("autocompletesearchparam", JSON.stringify(localeArray)); break; } } if (acAddonList && supportedCats.indexOf(selCat) != -1) { acAddonList.removeAttribute('hidden'); // hide ac menu in unsupported categories } else if (acAddonList) { acAddonList.setAttribute('hidden', true); } } function AddonsMgrOnUnload() { AddonManager.removeAddonListener(addonListener); this.removeEventListener("unload", AddonsMgrOnUnload, false); this.removeEventListener("ViewChanged", onViewChange, false); var addonList = this.document.getElementById("addon-list"); addonList.removeEventListener("select", onSelect, false); var acAddonList = this.document.getElementById("aomhilite_ac_menu"); if (acAddonList) { acAddonList.removeEventListener("textentered", onACaddonListSelection, false); acAddonList.removeEventListener("change", onACaddonListSelection, false); acAddonList.popup.removeEventListener("click", onACaddonListSelection, false); var arrow = this.document.getAnonymousElementByAttribute(acAddonList, "anonid", "historydropmarker"); if (arrow && displayDropdown) { arrow.removeEventListener("click", displayDropdown, false); displayDropdown = null; } var head = this.document.getElementById("header"); head.removeChild(acAddonList); } if (UIextra && addonList.hasAttribute("restoreondemand")) { // save needed info to aomhite so it will survive fx restart var savedSelections = addonList.getAttribute('aomhilite'); var selectionArray = savedSelections.split(","); var prevHilites = addonList.getAttribute('restoreondemand'); var hiliteArray = prevHilites.split(","); // save previous category selections until new ones have been made var i; for (i = 0; i < hiliteArray.length; i++) { if (hiliteArray[i] && !selectionArray[i]) { selectionArray[i] = hiliteArray[i]; } } var selectionsToSave = selectionArray.toString(); addonList.setAttribute('aomhilite', selectionsToSave); } extArray = null; themeArray = null; pluginArray = null; userstyleArray = null; serviceArray = null; userscriptArray = null; scriptishArray = null; custombuttonsArray = null; dictionaryArray = null; localeArray = null; }
Trovare la differenza