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;
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",
"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");
});
});
// 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;
break;
case "greasemonkey-user-script":
case "greasemonkey-user-script":
currentArray = userscriptArray;
currentArray = userscriptArray;
break;
break;
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));
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;
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();
}
}
}
}
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