Bug 1497726 - Add ability to modify prefs on new "about:config" page. r=paolo

Differential Revision: https://phabricator.services.mozilla.com/D12620

--HG--
extra : rebase_source : d9125ca8a60f7823bbd6a78450f7416ad6d0107e
This commit is contained in:
matthias 2018-11-28 20:40:01 +00:00
Родитель a90d895334
Коммит 2de608a30a
4 изменённых файлов: 225 добавлений и 10 удалений

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

@ -47,3 +47,8 @@
.cell-value {
word-break: break-all;
}
td.cell-value > form > input[type="text"] {
width: 100%;
box-sizing: border-box;
}

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

@ -7,6 +7,12 @@ ChromeUtils.import("resource://gre/modules/Preferences.jsm");
let gDefaultBranch = Services.prefs.getDefaultBranch("");
let gPrefArray;
let gPrefRowInEdit;
let gPrefInEdit;
function getPrefName(prefRow) {
return prefRow.getAttribute("aria-label");
}
function onLoad() {
gPrefArray = Services.prefs.getChildList("").map(function(name) {
@ -43,21 +49,42 @@ function onLoad() {
return;
}
let prefRow = event.target.closest("tr");
let prefName = prefRow.getAttribute("aria-label");
let prefName = getPrefName(prefRow);
let pref = gPrefArray.find(p => p.name == prefName);
let button = event.target.closest("button");
if (button.classList.contains("button-reset")) {
// Reset pref and update gPrefArray.
Services.prefs.clearUserPref(prefName);
let pref = gPrefArray.find(p => p.name == prefName);
pref.value = Preferences.get(prefName);
pref.hasUserValue = false;
// Update UI.
prefRow.textContent = "";
prefRow.classList.remove("has-user-value");
prefRow.appendChild(getPrefRow(pref));
prefRow.querySelector("td.cell-edit").firstChild.focus();
} else if (button.classList.contains("button-toggle")) {
// Toggle the pref and update gPrefArray.
Services.prefs.setBoolPref(prefName, !pref.value);
pref.value = !pref.value;
pref.hasUserValue = Services.prefs.prefHasUserValue(pref.name);
// Update UI.
prefRow.textContent = "";
if (pref.hasUserValue) {
prefRow.classList.add("has-user-value");
} else {
prefRow.classList.remove("has-user-value");
}
prefRow.appendChild(getPrefRow(pref));
prefRow.querySelector("td.cell-edit").firstChild.focus();
} else if (button.classList.contains("button-edit")) {
startEditingPref(prefRow, pref);
prefRow.querySelector("td.cell-value").firstChild.firstChild.focus();
} else if (button.classList.contains("button-save")) {
endEditingPref(prefRow);
prefRow.querySelector("td.cell-edit").firstChild.focus();
} else {
Services.prefs.clearUserPref(prefName);
gPrefArray.splice(gPrefArray.findIndex(pref => pref.name == prefName), 1);
gPrefArray.splice(gPrefArray.findIndex(p => p.name == prefName), 1);
prefRow.remove();
}
});
@ -103,21 +130,103 @@ function getPrefRow(pref) {
valueCell.textContent = pref.value;
rowFragment.appendChild(valueCell);
let editCell = document.createElement("td");
editCell.className = "cell-edit";
let button = document.createElement("button");
if (Services.prefs.getPrefType(pref.name) == Services.prefs.PREF_BOOL) {
document.l10n.setAttributes(button, "about-config-pref-toggle");
button.className = "button-toggle";
} else {
document.l10n.setAttributes(button, "about-config-pref-edit");
button.className = "button-edit";
}
editCell.appendChild(button);
rowFragment.appendChild(editCell);
let buttonCell = document.createElement("td");
if (pref.hasUserValue) {
let button = document.createElement("button");
let resetButton = document.createElement("button");
if (!pref.hasDefaultValue) {
document.l10n.setAttributes(button, "about-config-pref-delete");
document.l10n.setAttributes(resetButton, "about-config-pref-delete");
} else {
document.l10n.setAttributes(button, "about-config-pref-reset");
button.className = "button-reset";
document.l10n.setAttributes(resetButton, "about-config-pref-reset");
resetButton.className = "button-reset";
}
buttonCell.appendChild(button);
buttonCell.appendChild(resetButton);
}
rowFragment.appendChild(buttonCell);
return rowFragment;
}
function startEditingPref(row, arrayEntry) {
if (gPrefRowInEdit != undefined) {
// Abort editing-process first.
gPrefRowInEdit.textContent = "";
gPrefRowInEdit.appendChild(getPrefRow(gPrefInEdit));
}
gPrefRowInEdit = row;
let name = getPrefName(row);
gPrefInEdit = arrayEntry;
let valueCell = row.querySelector("td.cell-value");
let oldValue = valueCell.textContent;
valueCell.textContent = "";
// The form is needed for the invalid-tooltip to appear.
let form = document.createElement("form");
form.id = "form-" + name;
let inputField = document.createElement("input");
inputField.type = "text";
inputField.value = oldValue;
if (Services.prefs.getPrefType(name) == Services.prefs.PREF_INT) {
inputField.setAttribute("pattern", "-?[0-9]*");
document.l10n.setAttributes(inputField, "about-config-pref-input-number");
} else {
document.l10n.setAttributes(inputField, "about-config-pref-input-string");
}
inputField.placeholder = oldValue;
form.appendChild(inputField);
valueCell.appendChild(form);
let buttonCell = row.querySelector("td.cell-edit");
buttonCell.childNodes[0].remove();
let button = document.createElement("button");
button.classList.add("primary", "button-save");
document.l10n.setAttributes(button, "about-config-pref-save");
button.setAttribute("form", form.id);
buttonCell.appendChild(button);
}
function endEditingPref(row) {
let name = gPrefInEdit.name;
let input = row.querySelector("td.cell-value").firstChild.firstChild;
let newValue = input.value;
if (Services.prefs.getPrefType(name) == Services.prefs.PREF_INT) {
let numberValue = parseInt(newValue);
if (!/^-?[0-9]*$/.test(newValue) || isNaN(numberValue)) {
input.setCustomValidity(input.title);
return;
}
newValue = numberValue;
Services.prefs.setIntPref(name, newValue);
} else {
Services.prefs.setStringPref(name, newValue);
}
// Update gPrefArray.
gPrefInEdit.value = newValue;
gPrefInEdit.hasUserValue = Services.prefs.prefHasUserValue(name);
// Update UI.
row.textContent = "";
if (gPrefInEdit.hasUserValue) {
row.classList.add("has-user-value");
} else {
row.classList.remove("has-user-value");
}
row.appendChild(getPrefRow(gPrefInEdit));
}
function prefHasDefaultValue(name) {
try {
switch (Services.prefs.getPrefType(name)) {

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

@ -7,5 +7,12 @@ about-config-title = about:config
about-config-search =
.placeholder = Search
about-config-pref-toggle = Toggle
about-config-pref-edit = Edit
about-config-pref-input-number =
.title = Please enter an integer value
about-config-pref-input-string =
.title = Please enter the value
about-config-pref-save = Save
about-config-pref-reset = Reset
about-config-pref-delete = Delete

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

@ -3,6 +3,22 @@
const PAGE_URL = "chrome://browser/content/aboutconfig/aboutconfig.html";
add_task(async function setup() {
await SpecialPowers.pushPrefEnv({
set: [
["test.aboutconfig.modify.boolean", true],
["test.aboutconfig.modify.number", 1337],
["test.aboutconfig.modify.string", "the answer to the life the universe and everything"],
],
});
registerCleanupFunction(() => {
Services.prefs.clearUserPref("accessibility.typeaheadfind.autostart");
Services.prefs.clearUserPref("accessibility.typeaheadfind.soundURL");
Services.prefs.clearUserPref("accessibility.typeaheadfind.casesensitive");
});
});
add_task(async function test_delete_user_pref() {
Services.prefs.setBoolPref("userAddedPref", true);
await BrowserTestUtils.withNewTab({
@ -65,7 +81,7 @@ add_task(async function test_reset_user_pref() {
list = [...content.document.getElementById("prefs")
.getElementsByTagName("tr")];
Assert.ok(!row.classList.contains("has-user-value"));
Assert.equal(row.childNodes[2].childNodes.length, 0);
Assert.equal(row.lastChild.childNodes.length, 0);
Assert.ok(!Services.prefs.prefHasUserValue(testPref));
Assert.equal(getValue(testPref), "" + Preferences.get(testPref));
@ -88,8 +104,86 @@ add_task(async function test_reset_user_pref() {
.getElementsByTagName("tr")];
let row = getRow(testPref);
Assert.ok(!row.classList.contains("has-user-value"));
Assert.equal(row.childNodes[2].childNodes.length, 0);
Assert.equal(row.lastChild.childNodes.length, 0);
Assert.equal(getValue(testPref), "" + Preferences.get(testPref));
});
});
});
add_task(async function test_modify() {
await BrowserTestUtils.withNewTab({
gBrowser,
url: PAGE_URL,
}, browser => {
return ContentTask.spawn(browser, null, () => {
ChromeUtils.import("resource://gre/modules/Preferences.jsm");
function getRow(name, list) {
return list.find(row => row.querySelector("td").textContent == name);
}
function getValue(name, list) {
return getRow(name, list).querySelector("td.cell-value").textContent;
}
// Test toggle for boolean prefs.
let list = [...content.document.getElementById("prefs")
.getElementsByTagName("tr")];
for (let nameOfBoolPref of [
"test.aboutconfig.modify.boolean",
"accessibility.typeaheadfind.autostart",
]) {
let row = getRow(nameOfBoolPref, list);
// Do this a two times to reset the pref.
for (let i = 0; i < 2; i++) {
row.querySelector("td.cell-edit").firstChild.click();
// Check new layout and saving in backend.
Assert.equal(getValue(nameOfBoolPref, list),
"" + Preferences.get(nameOfBoolPref));
let prefHasUserValue = Services.prefs.prefHasUserValue(nameOfBoolPref);
Assert.equal(row.classList.contains("has-user-value"), prefHasUserValue);
Assert.equal(row.lastChild.childNodes.length > 0, prefHasUserValue);
}
}
// Test abort of edit by starting with string and continuing with editing Int pref.
let row = getRow("test.aboutconfig.modify.string", list);
row.querySelector("td.cell-edit").firstChild.click();
row.querySelector("td.cell-value").firstChild.firstChild.value = "test";
let intRow = getRow("test.aboutconfig.modify.number", list);
intRow.querySelector("td.cell-edit").firstChild.click();
Assert.equal(intRow.querySelector("td.cell-value").firstChild.firstChild.value,
Preferences.get("test.aboutconfig.modify.number"));
Assert.equal(getValue("test.aboutconfig.modify.string", list),
"" + Preferences.get("test.aboutconfig.modify.string"));
Assert.equal(row.querySelector("td.cell-value").textContent,
Preferences.get("test.aboutconfig.modify.string"));
// Test regex check for Int pref.
intRow.querySelector("td.cell-value").firstChild.firstChild.value += "a";
intRow.querySelector("td.cell-edit").firstChild.click();
Assert.ok(!intRow.querySelector("td.cell-value").firstChild.firstChild.checkValidity());
// Test correct saving and DOM-update.
for (let prefName of [
"test.aboutconfig.modify.string",
"test.aboutconfig.modify.number",
"accessibility.typeaheadfind.soundURL",
"accessibility.typeaheadfind.casesensitive",
]) {
row = getRow(prefName, list);
// Activate edit and check displaying.
row.querySelector("td.cell-edit").firstChild.click();
Assert.equal(row.querySelector("td.cell-value").firstChild.firstChild.value,
Preferences.get(prefName));
row.querySelector("td.cell-value").firstChild.firstChild.value = "42";
// Save and check saving.
row.querySelector("td.cell-edit").firstChild.click();
Assert.equal(getValue(prefName, list),
"" + Preferences.get(prefName));
let prefHasUserValue = Services.prefs.prefHasUserValue(prefName);
Assert.equal(row.lastChild.childNodes.length > 0, prefHasUserValue);
Assert.equal(row.classList.contains("has-user-value"), prefHasUserValue);
}
});
});
});