the huge 117+ fixes update
This commit is contained in:
parent
baf06e964f
commit
ccae90fb3e
110 changed files with 7809 additions and 2864 deletions
102
chrome/utils/aboutconfig/aboutconfig.xhtml
Normal file
102
chrome/utils/aboutconfig/aboutconfig.xhtml
Normal file
|
@ -0,0 +1,102 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
||||
|
||||
<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://global/skin/in-content/info-pages.css" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://userchromejs/content/aboutconfig/config.css" type="text/css"?>
|
||||
|
||||
<window id="config"
|
||||
title="about:config"
|
||||
csp="default-src chrome:; object-src 'none'"
|
||||
data-l10n-id="config-window"
|
||||
aria-describedby="warningTitle warningText"
|
||||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:html="http://www.w3.org/1999/xhtml"
|
||||
windowtype="Preferences:ConfigManager"
|
||||
role="application"
|
||||
width="750"
|
||||
height="500">
|
||||
|
||||
<script src="chrome://userchromejs/content/aboutconfig/config.js"/>
|
||||
<script src="chrome://global/content/editMenuOverlay.js"/>
|
||||
<script src="chrome://global/content/globalOverlay.js"/>
|
||||
|
||||
<menupopup id="configContext">
|
||||
<menuitem id="toggleSelected" label="Toggle" accesskey="T" default="true"/>
|
||||
<menuitem id="modifySelected" label="Modify" accesskey="M" default="true"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="copyPref" label="Copy" accesskey="C"/>
|
||||
<menuitem id="copyName" label="Copy Name" accesskey="N"/>
|
||||
<menuitem id="copyValue" label="Copy Value" accesskey="V"/>
|
||||
<menu label="New" accesskey="w">
|
||||
<menupopup>
|
||||
<menuitem id="configString" label="String" accesskey="S"/>
|
||||
<menuitem id="configInt" label="Integer" accesskey="I"/>
|
||||
<menuitem id="configBool" label="Boolean" accesskey="B"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
<menuitem id="resetSelected" label="Reset" accesskey="R"/>
|
||||
</menupopup>
|
||||
|
||||
<keyset id="configTreeKeyset" disabled="true">
|
||||
<key id="keyVKReturn" keycode="VK_RETURN"/>
|
||||
<key id="configFocuSearch" modifiers="accel" key="r"/>
|
||||
<key id="configFocuSearch2" modifiers="accel" key="f"/>
|
||||
</keyset>
|
||||
<deck id="configDeck" flex="1">
|
||||
<vbox id="warningScreen" flex="1" align="center" style="overflow: auto;">
|
||||
<spacer flex="1"/>
|
||||
<vbox id="warningBox" class="container">
|
||||
<hbox class="title" flex="1">
|
||||
<label id="warningTitle" value="This might void your warranty!" class="title-text" flex="1"></label>
|
||||
</hbox>
|
||||
<vbox class="description" flex="1">
|
||||
<label id="warningText">Changing these advanced settings can be harmful to the stability, security, and performance of this application. You should only continue if you are sure of what you are doing.</label>
|
||||
<checkbox id="showWarningNextTime" label="Show this warning next time" checked="true"/>
|
||||
<hbox class="button-container">
|
||||
<button id="warningButton" label="I accept the risk!" class="primary"/>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</vbox>
|
||||
<spacer style="-moz-box-flex: 2"/>
|
||||
</vbox>
|
||||
<vbox flex="1">
|
||||
<hbox id="filterRow" align="center">
|
||||
<label value="Search:" accesskey="r" control="textbox"/>
|
||||
<search-textbox id="textbox" flex="1"
|
||||
aria-controls="configTree"/>
|
||||
</hbox>
|
||||
<tree id="configTree" flex="1" seltype="single"
|
||||
enableColumnDrag="true" context="configContext">
|
||||
<treecols>
|
||||
<!--
|
||||
The below code may suggest that 'ordinal' is still a supported XUL
|
||||
attribute. It is not. This is a crutch so that we can continue
|
||||
persisting the CSS -moz-box-ordinal-group attribute, which is the
|
||||
appropriate replacement for the ordinal attribute but cannot yet
|
||||
be easily persisted. The code that synchronizes the attribute with
|
||||
the CSS lives in toolkit/content/widget/tree.js and is specific to
|
||||
tree elements.
|
||||
-->
|
||||
<treecol id="prefCol" label="Preference Name" style="-moz-box-flex: 7"
|
||||
ignoreincolumnpicker="true"
|
||||
persist="hidden width ordinal sortDirection"/>
|
||||
<splitter class="tree-splitter" />
|
||||
<treecol id="lockCol" label="Status" flex="1"
|
||||
persist="hidden width ordinal sortDirection"/>
|
||||
<splitter class="tree-splitter" />
|
||||
<treecol id="typeCol" label="Type" flex="1"
|
||||
persist="hidden width ordinal sortDirection"/>
|
||||
<splitter class="tree-splitter" />
|
||||
<treecol id="valueCol" label="Value" style="-moz-box-flex: 10"
|
||||
persist="hidden width ordinal sortDirection"/>
|
||||
</treecols>
|
||||
|
||||
<treechildren id="configTreeBody"/>
|
||||
</tree>
|
||||
</vbox>
|
||||
</deck>
|
||||
</window>
|
49
chrome/utils/aboutconfig/config.css
Normal file
49
chrome/utils/aboutconfig/config.css
Normal file
|
@ -0,0 +1,49 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#warningScreen {
|
||||
font-size: 15px;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
padding-inline-start: calc(48px + 4.6em);
|
||||
padding-inline-end: 48px;
|
||||
}
|
||||
|
||||
.title {
|
||||
background-image: url("chrome://global/skin/icons/warning.svg");
|
||||
fill: #fcd100;
|
||||
}
|
||||
|
||||
#warningTitle {
|
||||
font-weight: lighter;
|
||||
line-height: 1.2;
|
||||
margin: 0;
|
||||
margin-bottom: .5em;
|
||||
}
|
||||
|
||||
#warningText {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
#warningButton {
|
||||
margin-top: 0.6em;
|
||||
}
|
||||
|
||||
#filterRow {
|
||||
margin-top: 4px;
|
||||
margin-inline-start: 4px;
|
||||
}
|
||||
|
||||
#configTree {
|
||||
margin-top: 4px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
#configTreeBody::-moz-tree-cell-text(user) {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#configTreeBody::-moz-tree-cell-text(locked) {
|
||||
font-style: italic;
|
||||
}
|
781
chrome/utils/aboutconfig/config.js
Normal file
781
chrome/utils/aboutconfig/config.js
Normal file
|
@ -0,0 +1,781 @@
|
|||
// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
|
||||
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const nsIPrefLocalizedString = Ci.nsIPrefLocalizedString;
|
||||
const nsISupportsString = Ci.nsISupportsString;
|
||||
const nsIPrefBranch = Ci.nsIPrefBranch;
|
||||
const nsIClipboardHelper = Ci.nsIClipboardHelper;
|
||||
|
||||
const nsClipboardHelper_CONTRACTID = "@mozilla.org/widget/clipboardhelper;1";
|
||||
|
||||
const gPrefBranch = Services.prefs;
|
||||
const gClipboardHelper = Cc[nsClipboardHelper_CONTRACTID].getService(
|
||||
nsIClipboardHelper
|
||||
);
|
||||
|
||||
var gLockProps = ["default", "user", "locked"];
|
||||
// we get these from a string bundle
|
||||
var gLockStrs = [];
|
||||
var gTypeStrs = [];
|
||||
|
||||
const PREF_IS_DEFAULT_VALUE = 0;
|
||||
const PREF_IS_MODIFIED = 1;
|
||||
const PREF_IS_LOCKED = 2;
|
||||
|
||||
var gPrefHash = {};
|
||||
var gPrefArray = [];
|
||||
var gPrefView = gPrefArray; // share the JS array
|
||||
var gSortedColumn = "prefCol";
|
||||
var gSortFunction = null;
|
||||
var gSortDirection = 1; // 1 is ascending; -1 is descending
|
||||
var gFilter = null;
|
||||
|
||||
var view = {
|
||||
get rowCount() {
|
||||
return gPrefView.length;
|
||||
},
|
||||
getCellText(index, col) {
|
||||
if (!(index in gPrefView)) {
|
||||
return "";
|
||||
}
|
||||
|
||||
var value = gPrefView[index][col.id];
|
||||
|
||||
switch (col.id) {
|
||||
case "lockCol":
|
||||
return gLockStrs[value];
|
||||
case "typeCol":
|
||||
return gTypeStrs[value];
|
||||
default:
|
||||
return value;
|
||||
}
|
||||
},
|
||||
getRowProperties(index) {
|
||||
return "";
|
||||
},
|
||||
getCellProperties(index, col) {
|
||||
if (index in gPrefView) {
|
||||
return gLockProps[gPrefView[index].lockCol];
|
||||
}
|
||||
|
||||
return "";
|
||||
},
|
||||
getColumnProperties(col) {
|
||||
return "";
|
||||
},
|
||||
treebox: null,
|
||||
selection: null,
|
||||
isContainer(index) {
|
||||
return false;
|
||||
},
|
||||
isContainerOpen(index) {
|
||||
return false;
|
||||
},
|
||||
isContainerEmpty(index) {
|
||||
return false;
|
||||
},
|
||||
isSorted() {
|
||||
return true;
|
||||
},
|
||||
canDrop(index, orientation) {
|
||||
return false;
|
||||
},
|
||||
drop(row, orientation) {},
|
||||
setTree(out) {
|
||||
this.treebox = out;
|
||||
},
|
||||
getParentIndex(rowIndex) {
|
||||
return -1;
|
||||
},
|
||||
hasNextSibling(rowIndex, afterIndex) {
|
||||
return false;
|
||||
},
|
||||
getLevel(index) {
|
||||
return 1;
|
||||
},
|
||||
getImageSrc(row, col) {
|
||||
return "";
|
||||
},
|
||||
toggleOpenState(index) {},
|
||||
cycleHeader(col) {
|
||||
var index = this.selection.currentIndex;
|
||||
if (col.id == gSortedColumn) {
|
||||
gSortDirection = -gSortDirection;
|
||||
gPrefArray.reverse();
|
||||
if (gPrefView != gPrefArray) {
|
||||
gPrefView.reverse();
|
||||
}
|
||||
if (index >= 0) {
|
||||
index = gPrefView.length - index - 1;
|
||||
}
|
||||
} else {
|
||||
var pref = null;
|
||||
if (index >= 0) {
|
||||
pref = gPrefView[index];
|
||||
}
|
||||
|
||||
var old = document.getElementById(gSortedColumn);
|
||||
old.removeAttribute("sortDirection");
|
||||
gPrefArray.sort((gSortFunction = gSortFunctions[col.id]));
|
||||
if (gPrefView != gPrefArray) {
|
||||
gPrefView.sort(gSortFunction);
|
||||
}
|
||||
gSortedColumn = col.id;
|
||||
if (pref) {
|
||||
index = getViewIndexOfPref(pref);
|
||||
}
|
||||
}
|
||||
col.element.setAttribute(
|
||||
"sortDirection",
|
||||
gSortDirection > 0 ? "ascending" : "descending"
|
||||
);
|
||||
this.treebox.invalidate();
|
||||
if (index >= 0) {
|
||||
this.selection.select(index);
|
||||
this.treebox.ensureRowIsVisible(index);
|
||||
}
|
||||
},
|
||||
selectionChanged() {},
|
||||
cycleCell(row, col) {},
|
||||
isEditable(row, col) {
|
||||
return false;
|
||||
},
|
||||
setCellValue(row, col, value) {},
|
||||
setCellText(row, col, value) {},
|
||||
isSeparator(index) {
|
||||
return false;
|
||||
},
|
||||
};
|
||||
|
||||
// find the index in gPrefView of a pref object
|
||||
// or -1 if it does not exist in the filtered view
|
||||
function getViewIndexOfPref(pref) {
|
||||
var low = -1,
|
||||
high = gPrefView.length;
|
||||
var index = (low + high) >> 1;
|
||||
while (index > low) {
|
||||
var mid = gPrefView[index];
|
||||
if (mid == pref) {
|
||||
return index;
|
||||
}
|
||||
if (gSortFunction(mid, pref) < 0) {
|
||||
low = index;
|
||||
} else {
|
||||
high = index;
|
||||
}
|
||||
index = (low + high) >> 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// find the index in gPrefView where a pref object belongs
|
||||
function getNearestViewIndexOfPref(pref) {
|
||||
var low = -1,
|
||||
high = gPrefView.length;
|
||||
var index = (low + high) >> 1;
|
||||
while (index > low) {
|
||||
if (gSortFunction(gPrefView[index], pref) < 0) {
|
||||
low = index;
|
||||
} else {
|
||||
high = index;
|
||||
}
|
||||
index = (low + high) >> 1;
|
||||
}
|
||||
return high;
|
||||
}
|
||||
|
||||
// find the index in gPrefArray of a pref object
|
||||
function getIndexOfPref(pref) {
|
||||
var low = -1,
|
||||
high = gPrefArray.length;
|
||||
var index = (low + high) >> 1;
|
||||
while (index > low) {
|
||||
var mid = gPrefArray[index];
|
||||
if (mid == pref) {
|
||||
return index;
|
||||
}
|
||||
if (gSortFunction(mid, pref) < 0) {
|
||||
low = index;
|
||||
} else {
|
||||
high = index;
|
||||
}
|
||||
index = (low + high) >> 1;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
function getNearestIndexOfPref(pref) {
|
||||
var low = -1,
|
||||
high = gPrefArray.length;
|
||||
var index = (low + high) >> 1;
|
||||
while (index > low) {
|
||||
if (gSortFunction(gPrefArray[index], pref) < 0) {
|
||||
low = index;
|
||||
} else {
|
||||
high = index;
|
||||
}
|
||||
index = (low + high) >> 1;
|
||||
}
|
||||
return high;
|
||||
}
|
||||
|
||||
var gPrefListener = {
|
||||
observe(subject, topic, prefName) {
|
||||
if (topic != "nsPref:changed") {
|
||||
return;
|
||||
}
|
||||
|
||||
var arrayIndex = gPrefArray.length;
|
||||
var viewIndex = arrayIndex;
|
||||
var selectedIndex = view.selection.currentIndex;
|
||||
var pref;
|
||||
var updateView = false;
|
||||
var updateArray = false;
|
||||
var addedRow = false;
|
||||
if (prefName in gPrefHash) {
|
||||
pref = gPrefHash[prefName];
|
||||
viewIndex = getViewIndexOfPref(pref);
|
||||
arrayIndex = getIndexOfPref(pref);
|
||||
fetchPref(prefName, arrayIndex);
|
||||
// fetchPref replaces the existing pref object
|
||||
pref = gPrefHash[prefName];
|
||||
if (viewIndex >= 0) {
|
||||
// Might need to update the filtered view
|
||||
gPrefView[viewIndex] = gPrefHash[prefName];
|
||||
view.treebox.invalidateRow(viewIndex);
|
||||
}
|
||||
if (gSortedColumn == "lockCol" || gSortedColumn == "valueCol") {
|
||||
updateArray = true;
|
||||
gPrefArray.splice(arrayIndex, 1);
|
||||
if (gFilter && gFilter.test(pref.prefCol + ";" + pref.valueCol)) {
|
||||
updateView = true;
|
||||
gPrefView.splice(viewIndex, 1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fetchPref(prefName, arrayIndex);
|
||||
pref = gPrefArray.pop();
|
||||
updateArray = true;
|
||||
addedRow = true;
|
||||
if (gFilter && gFilter.test(pref.prefCol + ";" + pref.valueCol)) {
|
||||
updateView = true;
|
||||
}
|
||||
}
|
||||
if (updateArray) {
|
||||
// Reinsert in the data array
|
||||
var newIndex = getNearestIndexOfPref(pref);
|
||||
gPrefArray.splice(newIndex, 0, pref);
|
||||
|
||||
if (updateView) {
|
||||
// View is filtered, reinsert in the view separately
|
||||
newIndex = getNearestViewIndexOfPref(pref);
|
||||
gPrefView.splice(newIndex, 0, pref);
|
||||
} else if (gFilter) {
|
||||
// View is filtered, but nothing to update
|
||||
return;
|
||||
}
|
||||
|
||||
if (addedRow) {
|
||||
view.treebox.rowCountChanged(newIndex, 1);
|
||||
}
|
||||
|
||||
// Invalidate the changed range in the view
|
||||
var low = Math.min(viewIndex, newIndex);
|
||||
var high = Math.max(viewIndex, newIndex);
|
||||
view.treebox.invalidateRange(low, high);
|
||||
|
||||
if (selectedIndex == viewIndex) {
|
||||
selectedIndex = newIndex;
|
||||
} else if (selectedIndex >= low && selectedIndex <= high) {
|
||||
selectedIndex += newIndex > viewIndex ? -1 : 1;
|
||||
}
|
||||
if (selectedIndex >= 0) {
|
||||
view.selection.select(selectedIndex);
|
||||
if (selectedIndex == newIndex) {
|
||||
view.treebox.ensureRowIsVisible(selectedIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
function prefObject(prefName, prefIndex) {
|
||||
this.prefCol = prefName;
|
||||
}
|
||||
|
||||
prefObject.prototype = {
|
||||
lockCol: PREF_IS_DEFAULT_VALUE,
|
||||
typeCol: nsIPrefBranch.PREF_STRING,
|
||||
valueCol: "",
|
||||
};
|
||||
|
||||
function fetchPref(prefName, prefIndex) {
|
||||
var pref = new prefObject(prefName);
|
||||
|
||||
gPrefHash[prefName] = pref;
|
||||
gPrefArray[prefIndex] = pref;
|
||||
|
||||
if (gPrefBranch.prefIsLocked(prefName)) {
|
||||
pref.lockCol = PREF_IS_LOCKED;
|
||||
} else if (gPrefBranch.prefHasUserValue(prefName)) {
|
||||
pref.lockCol = PREF_IS_MODIFIED;
|
||||
}
|
||||
|
||||
try {
|
||||
switch (gPrefBranch.getPrefType(prefName)) {
|
||||
case gPrefBranch.PREF_BOOL:
|
||||
pref.typeCol = gPrefBranch.PREF_BOOL;
|
||||
// convert to a string
|
||||
pref.valueCol = gPrefBranch.getBoolPref(prefName).toString();
|
||||
break;
|
||||
case gPrefBranch.PREF_INT:
|
||||
pref.typeCol = gPrefBranch.PREF_INT;
|
||||
// convert to a string
|
||||
pref.valueCol = gPrefBranch.getIntPref(prefName).toString();
|
||||
break;
|
||||
default:
|
||||
case gPrefBranch.PREF_STRING:
|
||||
pref.valueCol = gPrefBranch.getStringPref(prefName);
|
||||
// Try in case it's a localized string (will throw an exception if not)
|
||||
if (
|
||||
pref.lockCol == PREF_IS_DEFAULT_VALUE &&
|
||||
/^chrome:\/\/.+\/locale\/.+\.properties/.test(pref.valueCol)
|
||||
) {
|
||||
pref.valueCol = gPrefBranch.getComplexValue(
|
||||
prefName,
|
||||
nsIPrefLocalizedString
|
||||
).data;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
// Also catch obscure cases in which you can't tell in advance
|
||||
// that the pref exists but has no user or default value...
|
||||
}
|
||||
}
|
||||
|
||||
async function onConfigLoad() {
|
||||
let configContext = document.getElementById("configContext");
|
||||
configContext.addEventListener("popupshowing", function(event) {
|
||||
if (event.target == this) {
|
||||
updateContextMenu();
|
||||
}
|
||||
});
|
||||
|
||||
let commandListeners = {
|
||||
toggleSelected: ModifySelected,
|
||||
modifySelected: ModifySelected,
|
||||
copyPref,
|
||||
copyName,
|
||||
copyValue,
|
||||
resetSelected: ResetSelected,
|
||||
};
|
||||
|
||||
configContext.addEventListener("command", e => {
|
||||
if (e.target.id in commandListeners) {
|
||||
commandListeners[e.target.id]();
|
||||
}
|
||||
});
|
||||
|
||||
let configString = document.getElementById("configString");
|
||||
configString.addEventListener("command", function() {
|
||||
NewPref(nsIPrefBranch.PREF_STRING);
|
||||
});
|
||||
|
||||
let configInt = document.getElementById("configInt");
|
||||
configInt.addEventListener("command", function() {
|
||||
NewPref(nsIPrefBranch.PREF_INT);
|
||||
});
|
||||
|
||||
let configBool = document.getElementById("configBool");
|
||||
configBool.addEventListener("command", function() {
|
||||
NewPref(nsIPrefBranch.PREF_BOOL);
|
||||
});
|
||||
|
||||
let keyVKReturn = document.getElementById("keyVKReturn");
|
||||
keyVKReturn.addEventListener("command", ModifySelected);
|
||||
|
||||
let textBox = document.getElementById("textbox");
|
||||
textBox.addEventListener("command", FilterPrefs);
|
||||
|
||||
let configFocuSearch = document.getElementById("configFocuSearch");
|
||||
configFocuSearch.addEventListener("command", function() {
|
||||
textBox.focus();
|
||||
});
|
||||
|
||||
let configFocuSearch2 = document.getElementById("configFocuSearch2");
|
||||
configFocuSearch2.addEventListener("command", function() {
|
||||
textBox.focus();
|
||||
});
|
||||
|
||||
let warningButton = document.getElementById("warningButton");
|
||||
warningButton.addEventListener("command", ShowPrefs);
|
||||
|
||||
let configTree = document.getElementById("configTree");
|
||||
configTree.addEventListener("select", function() {
|
||||
window.updateCommands("select");
|
||||
});
|
||||
|
||||
let configTreeBody = document.getElementById("configTreeBody");
|
||||
configTreeBody.addEventListener("dblclick", function(event) {
|
||||
if (event.button == 0) {
|
||||
ModifySelected();
|
||||
}
|
||||
});
|
||||
|
||||
gLockStrs[PREF_IS_DEFAULT_VALUE] = 'default';
|
||||
gLockStrs[PREF_IS_MODIFIED] = 'modified';
|
||||
gLockStrs[PREF_IS_LOCKED] = 'locked';
|
||||
gTypeStrs[nsIPrefBranch.PREF_STRING] = 'string';
|
||||
gTypeStrs[nsIPrefBranch.PREF_INT] = 'integer';
|
||||
gTypeStrs[nsIPrefBranch.PREF_BOOL] = 'boolean';
|
||||
|
||||
var showWarning = gPrefBranch.getBoolPref("general.warnOnAboutConfig");
|
||||
|
||||
if (showWarning) {
|
||||
document.getElementById("warningButton").focus();
|
||||
} else {
|
||||
ShowPrefs();
|
||||
}
|
||||
}
|
||||
|
||||
// Unhide the warning message
|
||||
function ShowPrefs() {
|
||||
document.getElementById('configDeck').lastElementChild.style.visibility = 'visible';
|
||||
gPrefBranch.getChildList("").forEach(fetchPref);
|
||||
|
||||
var descending = document.getElementsByAttribute(
|
||||
"sortDirection",
|
||||
"descending"
|
||||
);
|
||||
if (descending.item(0)) {
|
||||
gSortedColumn = descending[0].id;
|
||||
gSortDirection = -1;
|
||||
} else {
|
||||
var ascending = document.getElementsByAttribute(
|
||||
"sortDirection",
|
||||
"ascending"
|
||||
);
|
||||
if (ascending.item(0)) {
|
||||
gSortedColumn = ascending[0].id;
|
||||
} else {
|
||||
document
|
||||
.getElementById(gSortedColumn)
|
||||
.setAttribute("sortDirection", "ascending");
|
||||
}
|
||||
}
|
||||
gSortFunction = gSortFunctions[gSortedColumn];
|
||||
gPrefArray.sort(gSortFunction);
|
||||
|
||||
gPrefBranch.addObserver("", gPrefListener);
|
||||
|
||||
var configTree = document.getElementById("configTree");
|
||||
configTree.view = view;
|
||||
configTree.controllers.insertControllerAt(0, configController);
|
||||
|
||||
document.getElementById("configDeck").setAttribute("selectedIndex", 1);
|
||||
document.getElementById("configTreeKeyset").removeAttribute("disabled");
|
||||
if (!document.getElementById("showWarningNextTime").checked) {
|
||||
gPrefBranch.setBoolPref("general.warnOnAboutConfig", false);
|
||||
}
|
||||
|
||||
// Process about:config?filter=<string>
|
||||
var textbox = document.getElementById("textbox");
|
||||
// About URIs don't support query params, so do this manually
|
||||
var loc = document.location.href;
|
||||
var matches = /[?&]filter\=([^&]+)/i.exec(loc);
|
||||
if (matches) {
|
||||
textbox.value = decodeURIComponent(matches[1]);
|
||||
}
|
||||
|
||||
// Even if we did not set the filter string via the URL query,
|
||||
// textbox might have been set via some other mechanism
|
||||
if (textbox.value) {
|
||||
FilterPrefs();
|
||||
}
|
||||
textbox.focus();
|
||||
}
|
||||
|
||||
function onConfigUnload() {
|
||||
if (
|
||||
document.getElementById("configDeck").getAttribute("selectedIndex") == 1
|
||||
) {
|
||||
gPrefBranch.removeObserver("", gPrefListener);
|
||||
var configTree = document.getElementById("configTree");
|
||||
configTree.view = null;
|
||||
configTree.controllers.removeController(configController);
|
||||
}
|
||||
}
|
||||
|
||||
function FilterPrefs() {
|
||||
if (
|
||||
document.getElementById("configDeck").getAttribute("selectedIndex") != 1
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
var substring = document.getElementById("textbox").value;
|
||||
// Check for "/regex/[i]"
|
||||
if (substring.charAt(0) == "/") {
|
||||
var r = substring.match(/^\/(.*)\/(i?)$/);
|
||||
try {
|
||||
gFilter = RegExp(r[1], r[2]);
|
||||
} catch (e) {
|
||||
return; // Do nothing on incomplete or bad RegExp
|
||||
}
|
||||
} else if (substring) {
|
||||
gFilter = RegExp(
|
||||
substring
|
||||
.replace(/([^* \w])/g, "\\$1")
|
||||
.replace(/^\*+/, "")
|
||||
.replace(/\*+/g, ".*"),
|
||||
"i"
|
||||
);
|
||||
} else {
|
||||
gFilter = null;
|
||||
}
|
||||
|
||||
var prefCol =
|
||||
view.selection && view.selection.currentIndex < 0
|
||||
? null
|
||||
: gPrefView[view.selection.currentIndex].prefCol;
|
||||
var oldlen = gPrefView.length;
|
||||
gPrefView = gPrefArray;
|
||||
if (gFilter) {
|
||||
gPrefView = [];
|
||||
for (var i = 0; i < gPrefArray.length; ++i) {
|
||||
if (gFilter.test(gPrefArray[i].prefCol + ";" + gPrefArray[i].valueCol)) {
|
||||
gPrefView.push(gPrefArray[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
view.treebox.invalidate();
|
||||
view.treebox.rowCountChanged(oldlen, gPrefView.length - oldlen);
|
||||
gotoPref(prefCol);
|
||||
}
|
||||
|
||||
function prefColSortFunction(x, y) {
|
||||
if (x.prefCol > y.prefCol) {
|
||||
return gSortDirection;
|
||||
}
|
||||
if (x.prefCol < y.prefCol) {
|
||||
return -gSortDirection;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
function lockColSortFunction(x, y) {
|
||||
if (x.lockCol != y.lockCol) {
|
||||
return gSortDirection * (y.lockCol - x.lockCol);
|
||||
}
|
||||
return prefColSortFunction(x, y);
|
||||
}
|
||||
|
||||
function typeColSortFunction(x, y) {
|
||||
if (x.typeCol != y.typeCol) {
|
||||
return gSortDirection * (y.typeCol - x.typeCol);
|
||||
}
|
||||
return prefColSortFunction(x, y);
|
||||
}
|
||||
|
||||
function valueColSortFunction(x, y) {
|
||||
if (x.valueCol > y.valueCol) {
|
||||
return gSortDirection;
|
||||
}
|
||||
if (x.valueCol < y.valueCol) {
|
||||
return -gSortDirection;
|
||||
}
|
||||
return prefColSortFunction(x, y);
|
||||
}
|
||||
|
||||
const gSortFunctions = {
|
||||
prefCol: prefColSortFunction,
|
||||
lockCol: lockColSortFunction,
|
||||
typeCol: typeColSortFunction,
|
||||
valueCol: valueColSortFunction,
|
||||
};
|
||||
|
||||
const gCategoryLabelForSortColumn = {
|
||||
prefCol: "SortByName",
|
||||
lockCol: "SortByStatus",
|
||||
typeCol: "SortByType",
|
||||
valueCol: "SortByValue",
|
||||
};
|
||||
|
||||
const configController = {
|
||||
supportsCommand: function supportsCommand(command) {
|
||||
return command == "cmd_copy";
|
||||
},
|
||||
isCommandEnabled: function isCommandEnabled(command) {
|
||||
return view.selection && view.selection.currentIndex >= 0;
|
||||
},
|
||||
doCommand: function doCommand(command) {
|
||||
copyPref();
|
||||
},
|
||||
onEvent: function onEvent(event) {},
|
||||
};
|
||||
|
||||
function updateContextMenu() {
|
||||
var lockCol = PREF_IS_LOCKED;
|
||||
var typeCol = nsIPrefBranch.PREF_STRING;
|
||||
var valueCol = "";
|
||||
var copyDisabled = true;
|
||||
var prefSelected = view.selection.currentIndex >= 0;
|
||||
|
||||
if (prefSelected) {
|
||||
var prefRow = gPrefView[view.selection.currentIndex];
|
||||
lockCol = prefRow.lockCol;
|
||||
typeCol = prefRow.typeCol;
|
||||
valueCol = prefRow.valueCol;
|
||||
copyDisabled = false;
|
||||
}
|
||||
|
||||
var copyPref = document.getElementById("copyPref");
|
||||
copyPref.setAttribute("disabled", copyDisabled);
|
||||
|
||||
var copyName = document.getElementById("copyName");
|
||||
copyName.setAttribute("disabled", copyDisabled);
|
||||
|
||||
var copyValue = document.getElementById("copyValue");
|
||||
copyValue.setAttribute("disabled", copyDisabled);
|
||||
|
||||
var resetSelected = document.getElementById("resetSelected");
|
||||
resetSelected.setAttribute("disabled", lockCol != PREF_IS_MODIFIED);
|
||||
|
||||
var canToggle = typeCol == nsIPrefBranch.PREF_BOOL && valueCol != "";
|
||||
// indicates that a pref is locked or no pref is selected at all
|
||||
var isLocked = lockCol == PREF_IS_LOCKED;
|
||||
|
||||
var modifySelected = document.getElementById("modifySelected");
|
||||
modifySelected.setAttribute("disabled", isLocked);
|
||||
modifySelected.hidden = canToggle;
|
||||
|
||||
var toggleSelected = document.getElementById("toggleSelected");
|
||||
toggleSelected.setAttribute("disabled", isLocked);
|
||||
toggleSelected.hidden = !canToggle;
|
||||
}
|
||||
|
||||
function copyPref() {
|
||||
var pref = gPrefView[view.selection.currentIndex];
|
||||
gClipboardHelper.copyString(pref.prefCol + ";" + pref.valueCol);
|
||||
}
|
||||
|
||||
function copyName() {
|
||||
gClipboardHelper.copyString(gPrefView[view.selection.currentIndex].prefCol);
|
||||
}
|
||||
|
||||
function copyValue() {
|
||||
gClipboardHelper.copyString(gPrefView[view.selection.currentIndex].valueCol);
|
||||
}
|
||||
|
||||
function ModifySelected() {
|
||||
if (view.selection.currentIndex >= 0) {
|
||||
ModifyPref(gPrefView[view.selection.currentIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
function ResetSelected() {
|
||||
var entry = gPrefView[view.selection.currentIndex];
|
||||
gPrefBranch.clearUserPref(entry.prefCol);
|
||||
}
|
||||
|
||||
async function NewPref(type) {
|
||||
var result = { value: "" };
|
||||
var dummy = { value: 0 };
|
||||
|
||||
let [newTitle, newPrompt] = [`New ${gTypeStrs[type]} value`, 'Enter the preference name'];
|
||||
|
||||
if (
|
||||
Services.prompt.prompt(window, newTitle, newPrompt, result, null, dummy)
|
||||
) {
|
||||
result.value = result.value.trim();
|
||||
if (!result.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
var pref;
|
||||
if (result.value in gPrefHash) {
|
||||
pref = gPrefHash[result.value];
|
||||
} else {
|
||||
pref = {
|
||||
prefCol: result.value,
|
||||
lockCol: PREF_IS_DEFAULT_VALUE,
|
||||
typeCol: type,
|
||||
valueCol: "",
|
||||
};
|
||||
}
|
||||
if (ModifyPref(pref)) {
|
||||
setTimeout(gotoPref, 0, result.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function gotoPref(pref) {
|
||||
// make sure the pref exists and is displayed in the current view
|
||||
var index = pref in gPrefHash ? getViewIndexOfPref(gPrefHash[pref]) : -1;
|
||||
if (index >= 0) {
|
||||
view.selection.select(index);
|
||||
view.treebox.ensureRowIsVisible(index);
|
||||
} else {
|
||||
view.selection.clearSelection();
|
||||
view.selection.currentIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
async function ModifyPref(entry) {
|
||||
if (entry.lockCol == PREF_IS_LOCKED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let [title] = [`Enter ${gTypeStrs[entry.typeCol]} value`];
|
||||
|
||||
if (entry.typeCol == nsIPrefBranch.PREF_BOOL) {
|
||||
var check = { value: entry.valueCol == "false" };
|
||||
if (
|
||||
!entry.valueCol &&
|
||||
!Services.prompt.select(
|
||||
window,
|
||||
title,
|
||||
entry.prefCol,
|
||||
[false, true],
|
||||
check
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
gPrefBranch.setBoolPref(entry.prefCol, check.value);
|
||||
} else {
|
||||
var result = { value: entry.valueCol };
|
||||
var dummy = { value: 0 };
|
||||
if (
|
||||
!Services.prompt.prompt(window, title, entry.prefCol, result, null, dummy)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (entry.typeCol == nsIPrefBranch.PREF_INT) {
|
||||
// | 0 converts to integer or 0; - 0 to float or NaN.
|
||||
// Thus, this check should catch all cases.
|
||||
var val = result.value | 0;
|
||||
if (val != result.value - 0) {
|
||||
const [err_title, err_text] = ['Invalid value', 'The text you entered is not a number.'];
|
||||
|
||||
Services.prompt.alert(window, err_title, err_text);
|
||||
return false;
|
||||
}
|
||||
gPrefBranch.setIntPref(entry.prefCol, val);
|
||||
} else {
|
||||
gPrefBranch.setStringPref(entry.prefCol, result.value);
|
||||
}
|
||||
}
|
||||
|
||||
Services.prefs.savePrefFile(null);
|
||||
return true;
|
||||
}
|
||||
|
||||
window.onload = onConfigLoad;
|
||||
window.onunload = onConfigUnload;
|
Loading…
Add table
Add a link
Reference in a new issue