зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1642570 - capture only user input for Form History r=dimi
We can skip checks for `input.value != input.defaultValue` by using `lastInteractiveValue` which tells us what user typed in the field. Differential Revision: https://phabricator.services.mozilla.com/D150990
This commit is contained in:
Родитель
1d4fdff5ec
Коммит
a9e99bef15
|
@ -51,9 +51,9 @@ function $_(formNum, name) {
|
|||
return null;
|
||||
}
|
||||
|
||||
var element = form.children.namedItem(name);
|
||||
var element = form.querySelector(`:is([name="${name}"], [id="${name}"])`);
|
||||
if (!element) {
|
||||
ok(false, "$_ couldn't find requested element " + name);
|
||||
ok(false, `$_ couldn't find requested element "${name}"`);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -95,10 +95,17 @@ class FormHistoryChild extends JSWindowActorChild {
|
|||
continue;
|
||||
}
|
||||
|
||||
let value = input.value.trim();
|
||||
const value = input.lastInteractiveValue?.trim();
|
||||
|
||||
// Don't save empty or unchanged values.
|
||||
if (!value || value == input.defaultValue.trim()) {
|
||||
// Only save user entered values even if they match the default value.
|
||||
// Any script input is ignored.
|
||||
// See Bug 1642570 for details.
|
||||
if (!value) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Save only when user input was last.
|
||||
if (value != input.value.trim()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,9 +18,6 @@ skip-if = (verify && debug && (os == 'win')) || (os == 'mac') # Bug 1514249
|
|||
[test_form_autocomplete_validation_at_input_event.html]
|
||||
[test_form_autocomplete_with_list.html]
|
||||
[test_form_submission.html]
|
||||
skip-if =
|
||||
os == "mac" && bits == 64 && debug # Bug 1481802
|
||||
os == "linux" && bits == 64 # Bug 1481802
|
||||
[test_form_submission_cap.html]
|
||||
[test_form_submission_cap2.html]
|
||||
[test_input_valid_state_with_autocomplete.html]
|
||||
|
|
|
@ -25,16 +25,16 @@ const TelemetryFilterPropsAC = Object.freeze({
|
|||
/*
|
||||
* Returns the element with the specified |name| attribute.
|
||||
*/
|
||||
function $_(formNum, name) {
|
||||
function getFormElementByName(formNum, name) {
|
||||
let form = document.getElementById("form" + formNum);
|
||||
if (!form) {
|
||||
ok(false, "$_ couldn't find requested form " + formNum);
|
||||
ok(false, "getFormElementByName couldn't find requested form " + formNum);
|
||||
return null;
|
||||
}
|
||||
|
||||
let element = form.elements.namedItem(name);
|
||||
if (!element) {
|
||||
ok(false, "$_ couldn't find requested element " + name);
|
||||
ok(false, "getFormElementByName couldn't find requested element " + name);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -43,11 +43,11 @@ function $_(formNum, name) {
|
|||
// the element.
|
||||
|
||||
if (element.hasAttribute("name") && element.getAttribute("name") != name) {
|
||||
ok(false, "$_ got confused.");
|
||||
ok(false, "getFormElementByName got confused.");
|
||||
return null;
|
||||
}
|
||||
|
||||
return element;
|
||||
return SpecialPowers.wrap(element);
|
||||
}
|
||||
|
||||
function registerPopupShownListener(listener) {
|
||||
|
@ -79,7 +79,7 @@ function checkArrayValues(actualValues, expectedValues, msg) {
|
|||
}
|
||||
}
|
||||
|
||||
var checkObserver = {
|
||||
var gCheckObserver = {
|
||||
verifyStack: [],
|
||||
callback: null,
|
||||
|
||||
|
@ -122,17 +122,41 @@ var checkObserver = {
|
|||
|
||||
countEntries(expected.name, expected.value, function(num) {
|
||||
ok(num > 0, expected.message);
|
||||
if (!checkObserver.verifyStack.length) {
|
||||
let callback = checkObserver.callback;
|
||||
checkObserver.callback = null;
|
||||
if (!gCheckObserver.verifyStack.length) {
|
||||
let callback = gCheckObserver.callback;
|
||||
gCheckObserver.callback = null;
|
||||
callback();
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
class StorageEventsObserver {
|
||||
promisesToResolve = [];
|
||||
|
||||
constructor() {
|
||||
gChromeScript.sendAsyncMessage("addObserver");
|
||||
gChromeScript.addMessageListener(
|
||||
"satchel-storage-changed",
|
||||
this.observe.bind(this)
|
||||
);
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
gChromeScript.sendAsyncMessage("removeObserver");
|
||||
}
|
||||
|
||||
observe({ subject, topic, data }) {
|
||||
this.promisesToResolve.shift()?.({ subject, topic, data });
|
||||
}
|
||||
|
||||
promiseNextStorageEvent() {
|
||||
return new Promise(resolve => this.promisesToResolve.push(resolve));
|
||||
}
|
||||
}
|
||||
|
||||
function checkForSave(name, value, message) {
|
||||
checkObserver.verifyStack.push({ name, value, message });
|
||||
gCheckObserver.verifyStack.push({ name, value, message });
|
||||
}
|
||||
|
||||
function getFormSubmitButton(formNum) {
|
||||
|
@ -297,6 +321,12 @@ function checkACTelemetryEvent(actualEvent, input, augmentedExtra) {
|
|||
isDeeply(actualEvent[5], expectedExtra, "Check event extra object");
|
||||
}
|
||||
|
||||
let gStorageEventsObserver;
|
||||
|
||||
function promiseNextStorageEvent() {
|
||||
return gStorageEventsObserver.promiseNextStorageEvent();
|
||||
}
|
||||
|
||||
function satchelCommonSetup() {
|
||||
let chromeURL = SimpleTest.getTestFileURL("parent_utils.js");
|
||||
gChromeScript = SpecialPowers.loadChromeScript(chromeURL);
|
||||
|
@ -307,7 +337,10 @@ function satchelCommonSetup() {
|
|||
}
|
||||
});
|
||||
|
||||
gStorageEventsObserver = new StorageEventsObserver();
|
||||
|
||||
SimpleTest.registerCleanupFunction(() => {
|
||||
gStorageEventsObserver.cleanup();
|
||||
gChromeScript.sendAsyncMessage("cleanup");
|
||||
return new Promise(resolve => {
|
||||
gChromeScript.addMessageListener("cleanup-done", function done() {
|
||||
|
|
|
@ -6,15 +6,10 @@
|
|||
|
||||
<body>
|
||||
|
||||
<form id="subform2" onsubmit="return false">
|
||||
<form>
|
||||
<input id="subtest2" type="text" name="subtest2">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
// set the input's value (can't use a default value, as satchel will ignore it)
|
||||
document.getElementById("subtest2").value = "subtestValue";
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
function submitForm() {
|
||||
if (!location.search.includes("field")) {
|
||||
let form = document.getElementById("form");
|
||||
let field = document.getElementById("field");
|
||||
field.value = "value";
|
||||
let field = SpecialPowers.wrap(document.getElementById("field"));
|
||||
field.setUserInput("value");
|
||||
form.submit();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,7 +76,9 @@ function checkSelectedIndexAfterResponseTime(expectedIndex) {
|
|||
});
|
||||
}
|
||||
|
||||
let input = $_(1, "field1");
|
||||
// getFormElementByName() returns wrapped input,
|
||||
// but in this test we want to test untrusted events, so we must unwrap
|
||||
const input = SpecialPowers.unwrap(getFormElementByName(1, "field1"));
|
||||
|
||||
function doKeyUnprivileged(key) {
|
||||
let keyName = "DOM_VK_" + key.toUpperCase();
|
||||
|
|
|
@ -60,7 +60,7 @@ function waitForNextPopup() {
|
|||
}
|
||||
|
||||
add_task(async function test_popup_not_move_input() {
|
||||
let input = $_(1, "field1");
|
||||
let input = getFormElementByName(1, "field1");
|
||||
let rect = input.getBoundingClientRect();
|
||||
|
||||
await new Promise(resolve => updateFormHistory([
|
||||
|
|
|
@ -29,7 +29,7 @@ Form History test: form field autocomplete
|
|||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
let input = $_(1, "field1");
|
||||
let input = getFormElementByName(1, "field1");
|
||||
|
||||
function setupFormHistory(aCallback) {
|
||||
updateFormHistory([
|
||||
|
|
|
@ -144,7 +144,7 @@ Form History test: form field autocomplete
|
|||
SpecialPowers.pushPrefEnv({"set": [["security.allow_eval_with_system_principal", true]]});
|
||||
var kSetUserInputCancelable = SpecialPowers.getBoolPref("dom.input_event.allow_to_cancel_set_user_input");
|
||||
|
||||
var input = $_(1, "field1");
|
||||
var input = getFormElementByName(1, "field1");
|
||||
|
||||
function setupFormHistory(aCallback) {
|
||||
updateFormHistory([
|
||||
|
@ -580,7 +580,7 @@ async function runTest() { // eslint-disable-line complexity
|
|||
|
||||
case 64:
|
||||
// Look at form 2, trigger autocomplete popup
|
||||
input = $_(2, "field2");
|
||||
input = getFormElementByName(2, "field2");
|
||||
testNum = 99;
|
||||
expectPopup();
|
||||
restoreForm();
|
||||
|
@ -596,7 +596,7 @@ async function runTest() { // eslint-disable-line complexity
|
|||
checkForm("value1");
|
||||
|
||||
// Look at form 3, try to trigger autocomplete popup
|
||||
input = $_(3, "field2");
|
||||
input = getFormElementByName(3, "field2");
|
||||
restoreForm();
|
||||
// Sometimes, this will fail if scrollTo(0, 0) is called, so that doesn't
|
||||
// happen here. Fortunately, a different input is used from the last test,
|
||||
|
@ -612,7 +612,7 @@ async function runTest() { // eslint-disable-line complexity
|
|||
checkForm("");
|
||||
|
||||
// Look at form 4, try to trigger autocomplete popup
|
||||
input = $_(4, "field2");
|
||||
input = getFormElementByName(4, "field2");
|
||||
restoreForm();
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
waitForMenuChange(0);
|
||||
|
@ -625,7 +625,7 @@ async function runTest() { // eslint-disable-line complexity
|
|||
checkForm("");
|
||||
|
||||
// Look at form 5, try to trigger autocomplete popup
|
||||
input = $_(5, "field3");
|
||||
input = getFormElementByName(5, "field3");
|
||||
restoreForm();
|
||||
testNum = 199;
|
||||
expectPopup();
|
||||
|
@ -709,7 +709,7 @@ async function runTest() { // eslint-disable-line complexity
|
|||
synthesizeKey("KEY_Escape");
|
||||
|
||||
// Look at form 6, try to trigger autocomplete popup
|
||||
input = $_(6, "field4");
|
||||
input = getFormElementByName(6, "field4");
|
||||
restoreForm();
|
||||
testNum = 249;
|
||||
expectPopup();
|
||||
|
@ -775,7 +775,7 @@ async function runTest() { // eslint-disable-line complexity
|
|||
checkMenuEntries([], testNum);
|
||||
|
||||
// Look at form 7, try to trigger autocomplete popup
|
||||
input = $_(7, "field5");
|
||||
input = getFormElementByName(7, "field5");
|
||||
testNum = 299;
|
||||
expectPopup();
|
||||
restoreForm();
|
||||
|
@ -869,7 +869,7 @@ async function runTest() { // eslint-disable-line complexity
|
|||
case 310:
|
||||
checkMenuEntries([], testNum);
|
||||
|
||||
input = $_(8, "field6");
|
||||
input = getFormElementByName(8, "field6");
|
||||
testNum = 399;
|
||||
expectPopup();
|
||||
restoreForm();
|
||||
|
@ -886,14 +886,14 @@ async function runTest() { // eslint-disable-line complexity
|
|||
checkForm("value");
|
||||
|
||||
if (testNum == 400) {
|
||||
input = $_(9, "field7");
|
||||
input = getFormElementByName(9, "field7");
|
||||
} else if (testNum == 401) {
|
||||
input = $_(10, "field8");
|
||||
input = getFormElementByName(10, "field8");
|
||||
} else if (testNum == 402) {
|
||||
input = $_(11, "field9");
|
||||
input = getFormElementByName(11, "field9");
|
||||
} else if (testNum == 403) {
|
||||
todo(false, "Fix input type=number");
|
||||
input = $_(12, "field10");
|
||||
input = getFormElementByName(12, "field10");
|
||||
}
|
||||
|
||||
expectPopup();
|
||||
|
@ -907,7 +907,7 @@ async function runTest() { // eslint-disable-line complexity
|
|||
synthesizeKey("KEY_Enter");
|
||||
checkForm("42");
|
||||
|
||||
input = $_(14, "field11");
|
||||
input = getFormElementByName(14, "field11");
|
||||
restoreForm();
|
||||
waitForMenuChange(0);
|
||||
break;
|
||||
|
@ -917,7 +917,7 @@ async function runTest() { // eslint-disable-line complexity
|
|||
// have a drop down menu for now
|
||||
checkForm("");
|
||||
|
||||
input = $_(15, "field12");
|
||||
input = getFormElementByName(15, "field12");
|
||||
restoreForm();
|
||||
waitForMenuChange(0);
|
||||
break;
|
||||
|
@ -927,7 +927,7 @@ async function runTest() { // eslint-disable-line complexity
|
|||
// have a drop down menu for now
|
||||
checkForm("");
|
||||
|
||||
input = $_(16, "field13");
|
||||
input = getFormElementByName(16, "field13");
|
||||
restoreForm();
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
waitForMenuChange(0);
|
||||
|
@ -939,7 +939,7 @@ async function runTest() { // eslint-disable-line complexity
|
|||
synthesizeKey("KEY_Enter");
|
||||
checkForm("30"); // default (midway between minimum (0) and maximum (64)) - step
|
||||
|
||||
input = $_(17, "field14");
|
||||
input = getFormElementByName(17, "field14");
|
||||
restoreForm();
|
||||
waitForMenuChange(0);
|
||||
break;
|
||||
|
@ -948,7 +948,7 @@ async function runTest() { // eslint-disable-line complexity
|
|||
checkMenuEntries([]); // type=color does not have a drop down menu
|
||||
checkForm("#000000"); // default color value
|
||||
|
||||
input = $_(18, "field15");
|
||||
input = getFormElementByName(18, "field15");
|
||||
restoreForm();
|
||||
expectPopup();
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
|
@ -960,7 +960,7 @@ async function runTest() { // eslint-disable-line complexity
|
|||
synthesizeKey("KEY_Enter");
|
||||
checkForm("2016-08");
|
||||
|
||||
input = $_(19, "field16");
|
||||
input = getFormElementByName(19, "field16");
|
||||
restoreForm();
|
||||
expectPopup();
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
|
@ -972,7 +972,7 @@ async function runTest() { // eslint-disable-line complexity
|
|||
synthesizeKey("KEY_Enter");
|
||||
checkForm("2016-W32");
|
||||
|
||||
input = $_(20, "field17");
|
||||
input = getFormElementByName(20, "field17");
|
||||
restoreForm();
|
||||
waitForMenuChange(0);
|
||||
synthesizeKey("KEY_ArrowDown");
|
||||
|
@ -987,7 +987,7 @@ async function runTest() { // eslint-disable-line complexity
|
|||
break;
|
||||
|
||||
case 412:
|
||||
input = $_(1, "field1");
|
||||
input = getFormElementByName(1, "field1");
|
||||
// Go to test 500.
|
||||
testNum = 499;
|
||||
|
||||
|
@ -1073,7 +1073,7 @@ async function runTest() { // eslint-disable-line complexity
|
|||
}
|
||||
case 600:
|
||||
// check we don't show autocomplete for searchbar-history
|
||||
input = $_(13, "searchbar-history");
|
||||
input = getFormElementByName(13, "searchbar-history");
|
||||
|
||||
// Trigger autocomplete popup
|
||||
checkForm("");
|
||||
|
|
|
@ -51,7 +51,7 @@ Form History test: form field autocomplete
|
|||
|
||||
/** Test for Form History autocomplete **/
|
||||
|
||||
var input = $_(1, "field1");
|
||||
var input = getFormElementByName(1, "field1");
|
||||
|
||||
function setupFormHistory(aCallback) {
|
||||
updateFormHistory([
|
||||
|
@ -238,7 +238,7 @@ async function runTest() {
|
|||
// Trigger autocomplete popup
|
||||
// Look at form 3, try to trigger autocomplete popup
|
||||
input.value = "";
|
||||
input = $_(3, "field2");
|
||||
input = getFormElementByName(3, "field2");
|
||||
testNum = 99;
|
||||
expectPopup();
|
||||
restoreForm();
|
||||
|
@ -527,7 +527,7 @@ async function runTest() {
|
|||
});
|
||||
|
||||
testNum = 499;
|
||||
input = $_(5, "field3");
|
||||
input = getFormElementByName(5, "field3");
|
||||
checkForm("");
|
||||
expectPopup();
|
||||
restoreForm();
|
||||
|
|
|
@ -13,239 +13,245 @@
|
|||
|
||||
<!-- ===== Things that should not be saved. ===== -->
|
||||
|
||||
<!-- autocomplete=off (case-insensitive token) for input -->
|
||||
<form id="form1" onsubmit="return checkSubmit(1)">
|
||||
<form purpose="nothing stored for input autocomplete=off (case-insensitive token)"
|
||||
id="form1">
|
||||
<input type="text" name="test1" autocomplete=" oFf ">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- autocomplete=off for form -->
|
||||
<form id="form2" onsubmit="return checkSubmit(2)" autocomplete="oFf">
|
||||
<form purpose="nothing stored for form autocomplete=off"
|
||||
id="form2" autocomplete="oFf">
|
||||
<input type="text" name="test1">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- don't save type=hidden -->
|
||||
<form id="form3" onsubmit="return checkSubmit(3)">
|
||||
<form purpose="nothing stored for type=hidden"
|
||||
id="form3">
|
||||
<input type="hidden" name="test1">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- don't save type=checkbox -->
|
||||
<form id="form4" onsubmit="return checkSubmit(4)">
|
||||
<form purpose="nothing stored for type=checkbox"
|
||||
id="form4">
|
||||
<input type="checkbox" name="test1">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- Don't save empty values. -->
|
||||
<form id="form5" onsubmit="return checkSubmit(5)">
|
||||
<form purpose="nothing stored for empty values."
|
||||
id="form5">
|
||||
<input type="text" name="test1" value="originalValue">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- Don't save unchanged values. -->
|
||||
<form id="form6" onsubmit="return checkSubmit(6)">
|
||||
<form purpose="nothing stored for unchanged values when set by a script."
|
||||
id="form6">
|
||||
<input type="text" name="test1" value="dontSaveThis">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- Don't save unchanged values. (.value not touched) -->
|
||||
<form id="form7" onsubmit="return checkSubmit(7)">
|
||||
<form purpose="nothing stored for unchanged values. (.value not touched)"
|
||||
id="form7">
|
||||
<input type="text" name="test1" value="dontSaveThis">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- No field name or ID. -->
|
||||
<form id="form8" onsubmit="return checkSubmit(8)">
|
||||
<form purpose="nothing stored for no field name or ID"
|
||||
id="form8">
|
||||
<input type="text">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- Nothing to save! -->
|
||||
<form id="form9" onsubmit="return checkSubmit(9)">
|
||||
<form purpose="nothing stored for nothing to save"
|
||||
id="form9">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- input with name too long (300 chars.) -->
|
||||
<form id="form10" onsubmit="return checkSubmit(10)">
|
||||
<form purpose="nothing stored for input with name too long (300 chars.)"
|
||||
id="form10">
|
||||
<input type="text" name="12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- input with value too long (300 chars.) -->
|
||||
<form id="form11" onsubmit="return checkSubmit(11)">
|
||||
<form purpose="nothing stored for input with value too long (300 chars.)"
|
||||
id="form11">
|
||||
<input type="text" name="test1">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- input with value of one space (which should be trimmed) -->
|
||||
<form id="form12" onsubmit="return checkSubmit(12)">
|
||||
<form purpose="nothing stored for input with value of one space (which should be trimmed)"
|
||||
id="form12">
|
||||
<input type="text" name="test1">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- password field -->
|
||||
<form id="form13" onsubmit="return checkSubmit(13)">
|
||||
<form purpose="nothing stored for password field"
|
||||
id="form13">
|
||||
<input type="password" name="test1">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- password field (type toggled to password and back after pageload) -->
|
||||
<form id="form14" onsubmit="return checkSubmit(14)">
|
||||
<form purpose="nothing stored for password field (type toggled to password and back after pageload)"
|
||||
id="form14">
|
||||
<input type="text" name="test1">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- input with sensitive data (16 digit credit card number) -->
|
||||
<form id="form15" onsubmit="return checkSubmit(15)">
|
||||
<form purpose="nothing stored for input with sensitive data (16 digit credit card number)"
|
||||
id="form15">
|
||||
<script type="text/javascript">
|
||||
var form = document.getElementById("form15");
|
||||
for (let i = 0; i != 10; i++) {
|
||||
let input = document.createElement("input");
|
||||
let form = document.getElementById("form15");
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const input = form.appendChild(document.createElement("input"));
|
||||
input.type = "text";
|
||||
input.name = "test" + (i + 1);
|
||||
form.appendChild(input);
|
||||
}
|
||||
</script>
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- input with sensitive data (15 digit credit card number) -->
|
||||
<form id="form16" onsubmit="return checkSubmit(16)">
|
||||
<form purpose="nothing stored for input with sensitive data (15 digit credit card number)"
|
||||
id="form16">
|
||||
<script type="text/javascript">
|
||||
form = document.getElementById("form16");
|
||||
for (let i = 0; i != 10; i++) {
|
||||
let input = document.createElement("input");
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const input = form.appendChild(document.createElement("input"));
|
||||
input.type = "text";
|
||||
input.name = "test" + (i + 1);
|
||||
form.appendChild(input);
|
||||
}
|
||||
</script>
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- input with sensitive data (19 digit credit card number) -->
|
||||
<form id="form17" onsubmit="return checkSubmit(17)">
|
||||
<form purpose="nothing stored for input with sensitive data (19 digit credit card number)"
|
||||
id="form17">
|
||||
<input type="text" name="test1">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- input with sensitive data (16 digit hyphenated credit card number) -->
|
||||
<form id="form18" onsubmit="return checkSubmit(18)">
|
||||
<form purpose="nothing stored for input with sensitive data (16 digit hyphenated credit card number)"
|
||||
id="form18">
|
||||
<input type="text" name="test1">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- input with sensitive data (15 digit whitespace-separated credit card number) -->
|
||||
<form id="form19" onsubmit="return checkSubmit(19)">
|
||||
<form purpose="nothing stored for input with sensitive data (15 digit whitespace-separated credit card number)"
|
||||
id="form19">
|
||||
<input type="text" name="test1">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- Don't save values if the form is invalid. -->
|
||||
<form id="form20" onsubmit="return checkSubmit(20);">
|
||||
<input type='email' name='test1' oninvalid="return checkSubmit(20);">
|
||||
<form purpose="nothing stored for the invalid form"
|
||||
id="form20">
|
||||
<input type='email' name='test1'>
|
||||
<button type='submit'>Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- Don't save values if the form is invalid. -->
|
||||
<form id="form21" onsubmit="return checkSubmit(21);">
|
||||
<input type='email' value='foo' oninvalid="return checkSubmit(21);">
|
||||
<form purpose="nothing stored for the invalid form"
|
||||
id="form21">
|
||||
<input type='email' value='foo'>
|
||||
<input type='text' name='test1'>
|
||||
<button type='submit'>Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- Don't save values if the input name is 'searchbar-history' -->
|
||||
<form id="form22" onsubmit="return checkSubmit(22);">
|
||||
<form purpose="nothing stored for the input with name 'searchbar-history'"
|
||||
id="form22">
|
||||
<input type='text' name='searchbar-history'>
|
||||
<button type='submit'>Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- autocomplete=cc-csc (case-insensitive token) for input -->
|
||||
<form id="form23" onsubmit="return checkSubmit(23)">
|
||||
<form purpose="nothing stored for input autocomplete=cc-csc (case-insensitive token)"
|
||||
id="form23">
|
||||
<input type="text" name="test1" autocomplete=" cc-CSC ">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- autocomplete=new-password (case-insensitive token) for input -->
|
||||
<form id="form24" onsubmit="return checkSubmit(24)">
|
||||
<form purpose="nothing stored for input autocomplete=new-password (case-insensitive token)"
|
||||
id="form24">
|
||||
<input type="text" name="test1" autocomplete=" NEW-password ">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<form purpose="nothing stored after user input followed by reset button click"
|
||||
id="form25">
|
||||
<input type="text" name="test1" defaultValue="do not save me" value="do not save me either">
|
||||
<button type="submit">Submit</button>
|
||||
<button type="reset">Reset</button>
|
||||
</form>
|
||||
|
||||
<form purpose="nothing stored after user input changed by a script"
|
||||
id="form26">
|
||||
<input type="text" name="test1" defaultValue="do not save me" value="do not save me either">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- ===== Things that should be saved ===== -->
|
||||
|
||||
<!-- Form 100 is submitted into an iframe, not declared here. -->
|
||||
|
||||
<!-- input with no default value -->
|
||||
<form id="form101" onsubmit="return checkSubmit(101)">
|
||||
<form purpose="saved input with no default value"
|
||||
id="form101">
|
||||
<input type="text" name="test1">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- input with a default value -->
|
||||
<form id="form102" onsubmit="return checkSubmit(102)">
|
||||
<form purpose="saved input with a default value"
|
||||
id="form102">
|
||||
<input type="text" name="test2" value="originalValue">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- input uses id but not name -->
|
||||
<form id="form103" onsubmit="return checkSubmit(103)">
|
||||
<form purpose="saved input with id and not name"
|
||||
id="form103">
|
||||
<input type="text" id="test3">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- input with leading and trailing space -->
|
||||
<form id="form104" onsubmit="return checkSubmit(104)">
|
||||
<form purpose="saved input with leading and trailing space"
|
||||
id="form104">
|
||||
<input type="text" name="test4">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- input with leading and trailing whitespace -->
|
||||
<form id="form105" onsubmit="return checkSubmit(105)">
|
||||
<form purpose="saved input with leading and trailing whitespace"
|
||||
id="form105">
|
||||
<input type="text" name="test5">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- input that looks like sensitive data but doesn't
|
||||
satisfy the requirements (incorrect length) -->
|
||||
<form id="form106" onsubmit="return checkSubmit(106)">
|
||||
<form purpose="saved input that looks like sensitive data but doesn't satisfy the requirements (incorrect length)"
|
||||
id="form106">
|
||||
<input type="text" name="test6">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- input that looks like sensitive data but doesn't
|
||||
satisfy the requirements (Luhn check fails for 16 chars) -->
|
||||
<form id="form107" onsubmit="return checkSubmit(107)">
|
||||
<form purpose="input that looks like sensitive data but doesn't satisfy the requirements (Luhn check fails for 16 chars)"
|
||||
id="form107">
|
||||
<script type="text/javascript">
|
||||
form = document.getElementById("form107");
|
||||
for (let i = 0; i != 10; i++) {
|
||||
let input = document.createElement("input");
|
||||
for (let i = 0; i < 10; i++) {
|
||||
let input = form.appendChild(document.createElement("input"));
|
||||
input.type = "text";
|
||||
input.name = "test7_" + (i + 1);
|
||||
form.appendChild(input);
|
||||
}
|
||||
</script>
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- input that looks like sensitive data but doesn't
|
||||
satisfy the requirements (Luhn check fails for 15 chars) -->
|
||||
<form id="form108" onsubmit="return checkSubmit(108)">
|
||||
<form purpose="input that looks like sensitive data but doesn't satisfy the requirements (Luhn check fails for 15 chars)"
|
||||
id="form108">
|
||||
<script type="text/javascript">
|
||||
form = document.getElementById("form108");
|
||||
for (let i = 0; i != 10; i++) {
|
||||
let input = document.createElement("input");
|
||||
let input = form.appendChild(document.createElement("input"));
|
||||
input.type = "text";
|
||||
input.name = "test8_" + (i + 1);
|
||||
form.appendChild(input);
|
||||
}
|
||||
</script>
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
||||
<!-- form data submitted through HTTPS, when browser.formfill.saveHttpsForms is true -->
|
||||
<form id="form109" action="https://www.example.com/" onsubmit="return checkSubmit(109)">
|
||||
<form purpose="form data submitted through HTTPS, when browser.formfill.saveHttpsForms is true"
|
||||
id="form109" action="https://www.example.com/">
|
||||
<input type="text" name="test9">
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
|
@ -255,9 +261,7 @@
|
|||
<script class="testbody" type="text/javascript">
|
||||
/* eslint-disable complexity */
|
||||
|
||||
var numSubmittedForms = 0;
|
||||
|
||||
var ccNumbers = {
|
||||
const ccNumbers = {
|
||||
valid15: [
|
||||
"930771457288760", "474915027480942",
|
||||
"924894781317325", "714816113937185",
|
||||
|
@ -288,235 +292,308 @@ var ccNumbers = {
|
|||
],
|
||||
};
|
||||
|
||||
function checkInitialState() {
|
||||
countEntries(null, null,
|
||||
function(num) {
|
||||
ok(!num, "checking for initially empty storage");
|
||||
startTest();
|
||||
function setUserInput(formNumber, inputName, value) {
|
||||
const input = SpecialPowers.wrap(getFormElementByName(formNumber, inputName));
|
||||
input.setUserInput(value);
|
||||
}
|
||||
|
||||
function setScriptInput(formNumber, inputName, value) {
|
||||
getFormElementByName(formNumber, inputName).value = value;
|
||||
}
|
||||
|
||||
function checkSubmitDoesNotSave(formNumber, inputName, value) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const form = document.getElementById("form" + formNumber);
|
||||
form.addEventListener("submit", function listener(e) {
|
||||
countEntries(null, null, historyEntriesCount => {
|
||||
ok(!historyEntriesCount, form.getAttribute("purpose"));
|
||||
form.removeEventListener("submit", listener);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
getFormSubmitButton(formNumber).click();
|
||||
});
|
||||
}
|
||||
|
||||
function startTest() {
|
||||
// Fill in values for the various fields. We could just set the <input>'s
|
||||
// value attribute, but we don't save default form values (and we want to
|
||||
// ensure unsaved values are because of autocomplete=off or whatever).
|
||||
$_(1, "test1").value = "dontSaveThis";
|
||||
$_(2, "test1").value = "dontSaveThis";
|
||||
$_(3, "test1").value = "dontSaveThis";
|
||||
$_(4, "test1").value = "dontSaveThis";
|
||||
$_(5, "test1").value = "";
|
||||
$_(6, "test1").value = "dontSaveThis";
|
||||
function checkInvalidFirstInputDoesNotSave(formNumber, value) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const form = document.getElementById("form" + formNumber);
|
||||
const input = form.querySelector("input");
|
||||
input.addEventListener("invalid", function listener(e) {
|
||||
countEntries(null, null, historyEntriesCount => {
|
||||
ok(!historyEntriesCount, form.getAttribute("purpose"));
|
||||
input.removeEventListener("invalid", listener);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
|
||||
getFormSubmitButton(formNumber).click();
|
||||
});
|
||||
}
|
||||
|
||||
async function checkSubmitSaves(formNumber, inputName, interactiveValue, savedValue, storageEventData = "formhistory-add") {
|
||||
setUserInput(formNumber, inputName, interactiveValue);
|
||||
const form = document.getElementById("form" + formNumber);
|
||||
const storageEventPromise = promiseNextStorageEvent();
|
||||
|
||||
getFormSubmitButton(formNumber).click();
|
||||
|
||||
const storageEvent = await storageEventPromise;
|
||||
isDeeply(storageEvent, {
|
||||
subject: null,
|
||||
topic: "satchel-storage-changed",
|
||||
data: storageEventData
|
||||
}, "expected storage event");
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
countEntries(inputName, savedValue, historyEntriesCount => {
|
||||
ok(historyEntriesCount == 1, form.getAttribute("purpose"));
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// This will prevent endless loop of tests
|
||||
for (const form of document.forms) {
|
||||
form.addEventListener("submit", e => e.preventDefault());
|
||||
}
|
||||
|
||||
add_task(async function checkInitialState() {
|
||||
await new Promise((resolve)=>{
|
||||
countEntries(null, null,
|
||||
historyEntriesCount => {
|
||||
ok(!historyEntriesCount, "checking for initially empty storage");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
})
|
||||
|
||||
add_task(async function form1_does_not_save() {
|
||||
setUserInput(1, "test1", "dontSaveThis");
|
||||
await checkSubmitDoesNotSave(1);
|
||||
});
|
||||
|
||||
add_task(async function form2_does_not_save() {
|
||||
setUserInput(2, "test1", "dontSaveThis");
|
||||
await checkSubmitDoesNotSave(2);
|
||||
});
|
||||
|
||||
add_task(async function form3_does_not_save() {
|
||||
setUserInput(3, "test1", "dontSaveThis");
|
||||
await checkSubmitDoesNotSave(3);
|
||||
});
|
||||
|
||||
add_task(async function form4_does_not_save() {
|
||||
setUserInput(4, "test1", "dontSaveThis");
|
||||
await checkSubmitDoesNotSave(4);
|
||||
});
|
||||
|
||||
add_task(async function form5_does_not_save() {
|
||||
setUserInput(5, "test1", "");
|
||||
await checkSubmitDoesNotSave(5);
|
||||
});
|
||||
|
||||
add_task(async function form6_does_not_save() {
|
||||
setScriptInput(6, "test1", "dontSaveThis");
|
||||
await checkSubmitDoesNotSave(6);
|
||||
});
|
||||
|
||||
add_task(async function form7_does_not_save() {
|
||||
// Form 7 deliberately left untouched.
|
||||
await checkSubmitDoesNotSave(7);
|
||||
});
|
||||
|
||||
add_task(async function form8_does_not_save() {
|
||||
// Form 8 has an input with no name or input attribute.
|
||||
let input = document.getElementById("form8").elements[0];
|
||||
let input = SpecialPowers.wrap(document.getElementById("form8").elements[0]);
|
||||
is(input.type, "text", "checking we got unidentified input");
|
||||
input.value = "dontSaveThis";
|
||||
input.setUserInput("dontSaveThis");
|
||||
await checkSubmitDoesNotSave(8);
|
||||
});
|
||||
|
||||
add_task(async function form9_does_not_save() {
|
||||
// Form 9 has nothing to modify.
|
||||
$_(10, "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456" +
|
||||
await checkSubmitDoesNotSave(9);
|
||||
});
|
||||
|
||||
add_task(async function form10_does_not_save() {
|
||||
setUserInput(10,
|
||||
"12345678901234567890123456789012345678901234567890123456789012345678901234567890123456" +
|
||||
"789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456" +
|
||||
"789012345678901234567890123456789012345678901234567890123456789012345678901234567890").value
|
||||
= "dontSaveThis";
|
||||
$_(11, "test1").value = "123456789012345678901234567890123456789012345678901234567890123456789" +
|
||||
"789012345678901234567890123456789012345678901234567890123456789012345678901234567890",
|
||||
"dontSaveThis");
|
||||
await checkSubmitDoesNotSave(10);
|
||||
});
|
||||
|
||||
add_task(async function form11_does_not_save() {
|
||||
setUserInput(11, "test1",
|
||||
"123456789012345678901234567890123456789012345678901234567890123456789" +
|
||||
"012345678901234567890123456789012345678901234567890123456789012345678" +
|
||||
"901234567890123456789012345678901234567890123456789012345678901234567" +
|
||||
"89012345678901234567890123456789012345678901234567890";
|
||||
$_(12, "test1").value = " ";
|
||||
$_(13, "test1").value = "dontSaveThis";
|
||||
$_(14, "test1").type = "password";
|
||||
$_(14, "test1").value = "dontSaveThis";
|
||||
"89012345678901234567890123456789012345678901234567890");
|
||||
await checkSubmitDoesNotSave(11);
|
||||
});
|
||||
|
||||
add_task(async function form12_does_not_save() {
|
||||
setUserInput(12, "test1", " ");
|
||||
await checkSubmitDoesNotSave(12);
|
||||
});
|
||||
|
||||
add_task(async function form13_does_not_save() {
|
||||
setUserInput(13, "test1", "dontSaveThis");
|
||||
await checkSubmitDoesNotSave(13);
|
||||
});
|
||||
|
||||
add_task(async function form14_does_not_save() {
|
||||
let input = SpecialPowers.wrap(document.getElementById("form14").elements[0]);
|
||||
input.type = "password";
|
||||
input.setUserInput("dontSaveThis");
|
||||
// Set it back to type=text to simulate a password visibility toggle.
|
||||
$_(14, "test1").type = "text";
|
||||
input.type = "text";
|
||||
await checkSubmitDoesNotSave(14);
|
||||
});
|
||||
|
||||
let testData = ccNumbers.valid16;
|
||||
for (let i = 0; i != testData.length; i++) {
|
||||
$_(15, "test" + (i + 1)).value = testData[i];
|
||||
add_task(async function form15_does_not_save() {
|
||||
const testData = ccNumbers.valid16;
|
||||
for (let i = 0; i < testData.length; i++) {
|
||||
setUserInput(15, "test" + (i + 1), testData[i]);
|
||||
}
|
||||
await checkSubmitDoesNotSave(15);
|
||||
});
|
||||
|
||||
testData = ccNumbers.valid15;
|
||||
for (let i = 0; i != testData.length; i++) {
|
||||
$_(16, "test" + (i + 1)).value = testData[i];
|
||||
add_task(async function form16_does_not_save() {
|
||||
const testData = ccNumbers.valid15;
|
||||
for (let i = 0; i < testData.length; i++) {
|
||||
setUserInput(16, "test" + (i + 1), testData[i]);
|
||||
}
|
||||
$_(17, "test1").value = "6799990100000000019";
|
||||
$_(18, "test1").value = "0000-0000-0080-4609";
|
||||
$_(19, "test1").value = "0000 0000 0222 331";
|
||||
$_(20, "test1").value = "dontSaveThis";
|
||||
$_(21, "test1").value = "dontSaveThis";
|
||||
$_(22, "searchbar-history").value = "dontSaveThis";
|
||||
$_(23, "test1").value = "987";
|
||||
$_(24, "test1").value = "s3cr3t";
|
||||
await checkSubmitDoesNotSave(16);
|
||||
});
|
||||
|
||||
$_(101, "test1").value = "savedValue";
|
||||
$_(102, "test2").value = "savedValue";
|
||||
$_(103, "test3").value = "savedValue";
|
||||
$_(104, "test4").value = " trimTrailingAndLeadingSpace ";
|
||||
$_(105, "test5").value = "\t trimTrailingAndLeadingWhitespace\t ";
|
||||
$_(106, "test6").value = "55555555555544445553"; // passes luhn but too long
|
||||
add_task(async function form17_does_not_save() {
|
||||
setUserInput(17, "test1", "6799990100000000019");
|
||||
await checkSubmitDoesNotSave(17);
|
||||
});
|
||||
|
||||
testData = ccNumbers.invalid16;
|
||||
for (let i = 0; i != testData.length; i++) {
|
||||
$_(107, "test7_" + (i + 1)).value = testData[i];
|
||||
}
|
||||
add_task(async function form18_does_not_save() {
|
||||
setUserInput(18, "test1", "0000-0000-0080-4609");
|
||||
await checkSubmitDoesNotSave(18);
|
||||
});
|
||||
|
||||
testData = ccNumbers.invalid15;
|
||||
for (let i = 0; i != testData.length; i++) {
|
||||
$_(108, "test8_" + (i + 1)).value = testData[i];
|
||||
}
|
||||
add_task(async function form19_does_not_save() {
|
||||
setUserInput(19, "test1", "0000 0000 0222 331");
|
||||
await checkSubmitDoesNotSave(19);
|
||||
});
|
||||
|
||||
$_(109, "test9").value = "savedValue";
|
||||
add_task(async function form20_does_not_save() {
|
||||
setUserInput(20, "test1", "dontSaveThis");
|
||||
await checkInvalidFirstInputDoesNotSave(20, "invalid");
|
||||
});
|
||||
|
||||
// submit the first form.
|
||||
let button = getFormSubmitButton(1);
|
||||
button.click();
|
||||
}
|
||||
add_task(async function form21_does_not_save() {
|
||||
setUserInput(21, "test1", "dontSaveThis");
|
||||
await checkInvalidFirstInputDoesNotSave(21, "invalid");
|
||||
});
|
||||
|
||||
add_task(async function form22_does_not_save() {
|
||||
setUserInput(22, "searchbar-history", "dontSaveThis");
|
||||
await checkSubmitDoesNotSave(22);
|
||||
});
|
||||
|
||||
/* exported checkSubmit */
|
||||
// Called by each form's onsubmit handler.
|
||||
function checkSubmit(formNum) {
|
||||
ok(true, "form " + formNum + " submitted");
|
||||
numSubmittedForms++;
|
||||
add_task(async function form23_does_not_save() {
|
||||
setUserInput(23, "test1", "987");
|
||||
await checkSubmitDoesNotSave(23);
|
||||
});
|
||||
|
||||
// Check for expected storage state.
|
||||
switch (formNum) {
|
||||
// Test 1-24 should not save anything.
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
case 6:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 12:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 16:
|
||||
case 17:
|
||||
case 18:
|
||||
case 19:
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
case 23:
|
||||
case 24:
|
||||
countEntries(null, null,
|
||||
function(num) {
|
||||
ok(!num, "checking for empty storage");
|
||||
submitForm(formNum);
|
||||
});
|
||||
return false;
|
||||
case 100:
|
||||
checkForSave("subtest2", "subtestValue", "checking saved subtest value");
|
||||
break;
|
||||
case 101:
|
||||
checkForSave("test1", "savedValue", "checking saved value");
|
||||
break;
|
||||
case 102:
|
||||
checkForSave("test2", "savedValue", "checking saved value");
|
||||
break;
|
||||
case 103:
|
||||
checkForSave("test3", "savedValue", "checking saved value");
|
||||
break;
|
||||
case 104:
|
||||
checkForSave("test4", "trimTrailingAndLeadingSpace",
|
||||
"checking saved value is trimmed on both sides");
|
||||
break;
|
||||
case 105:
|
||||
checkForSave("test5", "trimTrailingAndLeadingWhitespace",
|
||||
"checking saved value is trimmed on both sides");
|
||||
break;
|
||||
case 106:
|
||||
checkForSave("test6", "55555555555544445553", "checking saved value");
|
||||
break;
|
||||
case 107:
|
||||
for (let i = 0; i != ccNumbers.invalid16.length; i++) {
|
||||
checkForSave("test7_" + (i + 1), ccNumbers.invalid16[i], "checking saved value");
|
||||
}
|
||||
break;
|
||||
case 108:
|
||||
for (let i = 0; i != ccNumbers.invalid15.length; i++) {
|
||||
checkForSave("test8_" + (i + 1), ccNumbers.invalid15[i], "checking saved value");
|
||||
}
|
||||
break;
|
||||
case 109:
|
||||
checkForSave("test9", "savedValue", "checking saved value");
|
||||
break;
|
||||
default:
|
||||
ok(false, "Unexpected form submission");
|
||||
break;
|
||||
}
|
||||
add_task(async function form24_does_not_save() {
|
||||
setUserInput(24, "test1", "s3cr3t");
|
||||
await checkSubmitDoesNotSave(24);
|
||||
});
|
||||
|
||||
return submitForm(formNum);
|
||||
}
|
||||
add_task(async function form25_does_not_save() {
|
||||
setUserInput(25, "test1", "s3cr3t");
|
||||
document.querySelector("form[id=form25] button[type=reset]").click();
|
||||
await checkSubmitDoesNotSave(25);
|
||||
});
|
||||
|
||||
function submitForm(formNum) {
|
||||
// End the test now on SeaMonkey.
|
||||
if (formNum == 20 && navigator.userAgent.match(/ SeaMonkey\//)) {
|
||||
checkObserver.uninit();
|
||||
is(numSubmittedForms, 20, "Ensuring all forms were submitted.");
|
||||
add_task(async function form26_does_not_save() {
|
||||
setUserInput(26, "test1", "s3cr3t");
|
||||
document.querySelector("form[id=form26] input[name=test1]").value = "script changed me";
|
||||
await checkSubmitDoesNotSave(26);
|
||||
});
|
||||
|
||||
todo(false, "Skipping remaining checks on SeaMonkey ftb. (Bug 589471)");
|
||||
// finish(), yet let the test actually end first, to be safe.
|
||||
SimpleTest.executeSoon(SimpleTest.finish);
|
||||
|
||||
return false; // return false to cancel current form submission
|
||||
}
|
||||
|
||||
// End the test at the last form.
|
||||
if (formNum == 109) {
|
||||
is(numSubmittedForms, 34, "Ensuring all forms were submitted.");
|
||||
checkObserver.uninit();
|
||||
SimpleTest.executeSoon(SimpleTest.finish);
|
||||
return false; // return false to cancel current form submission
|
||||
}
|
||||
|
||||
// This timeout is here so that button.click() is never called before this
|
||||
// function returns. If button.click() is called before returning, a long
|
||||
// chain of submits will happen recursively since the submit is dispatched
|
||||
// immediately.
|
||||
//
|
||||
// This in itself is fine, but if there are errors in the code, mochitests
|
||||
// will in some cases give you "server too busy", which is hard to debug!
|
||||
//
|
||||
setTimeout(function() {
|
||||
checkObserver.waitForChecks(function() {
|
||||
let nextFormNum = formNum == 24 ? 100 : (formNum + 1);
|
||||
|
||||
// Submit the next form. Special cases are Forms 21 and 100, which happen
|
||||
// from an HTTPS domain in an iframe.
|
||||
if (nextFormNum == 100) {
|
||||
ok(true, "submitting iframe test " + nextFormNum);
|
||||
|
||||
// Need to call checkSubmit first, as the iframe's document can be in another
|
||||
// process and won't be able to notify back before the submit occurs.
|
||||
checkSubmit(100);
|
||||
|
||||
let browsingContext = SpecialPowers.unwrap(
|
||||
SpecialPowers.wrap(document.getElementById("iframe")).browsingContext);
|
||||
SpecialPowers.spawn(browsingContext, [], () => {
|
||||
add_task(async function form100_saves() {
|
||||
const iframe = SpecialPowers.wrap(document.getElementById("iframe"));
|
||||
const browsingContext = SpecialPowers.unwrap(iframe.browsingContext);
|
||||
const storageEventPromise = promiseNextStorageEvent();
|
||||
await SpecialPowers.spawn(browsingContext, [], () => {
|
||||
/* eslint-disable no-undef */
|
||||
content.document.querySelectorAll("button")[0].click();
|
||||
const input = SpecialPowers.wrap(content.document.getElementById("subtest2"));
|
||||
input.setUserInput("subtestValue");
|
||||
content.document.querySelector("button").click();
|
||||
/* eslint-enable no-undef */
|
||||
});
|
||||
} else {
|
||||
let button = getFormSubmitButton(nextFormNum);
|
||||
button.click();
|
||||
}
|
||||
|
||||
const storageEvent = await storageEventPromise;
|
||||
isDeeply(storageEvent, {
|
||||
subject: null,
|
||||
topic: "satchel-storage-changed",
|
||||
data: "formhistory-add"
|
||||
}, "expected storage event");
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
countEntries("subtest2", "subtestValue", historyEntriesCount => {
|
||||
ok(historyEntriesCount == 1, "saved from iframe");
|
||||
resolve();
|
||||
});
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
return false; // cancel current form submission
|
||||
}
|
||||
add_task(async function form101_saves() {
|
||||
await checkSubmitSaves(101, "test1", "savedValue", "savedValue");
|
||||
});
|
||||
|
||||
checkObserver.init();
|
||||
add_task(async function form102_saves() {
|
||||
await checkSubmitSaves(102, "test2", "savedValue", "savedValue");
|
||||
});
|
||||
|
||||
window.onload = checkInitialState;
|
||||
add_task(async function form103_saves() {
|
||||
await checkSubmitSaves(103, "test3", "savedValue", "savedValue");
|
||||
});
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
add_task(async function form104_saves() {
|
||||
await checkSubmitSaves(104, "test4", " trimTrailingAndLeadingSpace ", "trimTrailingAndLeadingSpace");
|
||||
});
|
||||
|
||||
add_task(async function form105_saves() {
|
||||
await checkSubmitSaves(105, "test5", "\t trimTrailingAndLeadingWhitespace\t ", "trimTrailingAndLeadingWhitespace");
|
||||
});
|
||||
|
||||
add_task(async function form106_saves() {
|
||||
// passes luhn but too long
|
||||
await checkSubmitSaves(106, "test6", "55555555555544445553", "55555555555544445553");
|
||||
});
|
||||
|
||||
add_task(async function form107_saves() {
|
||||
for (let i = 0; i != ccNumbers.invalid16.length; i++) {
|
||||
const name = "test7_" + (i + 1);
|
||||
const value = ccNumbers.invalid16[i];
|
||||
await checkSubmitSaves(107, name, value, value, i != 0 ? "formhistory-update" : "formhistory-add");
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function form108_saves() {
|
||||
for (let i = 0; i != ccNumbers.invalid15.length; i++) {
|
||||
const name = "test8_" + (i + 1);
|
||||
const value = ccNumbers.invalid15[i];
|
||||
await checkSubmitSaves(108, name, value, value, i != 0 ? "formhistory-update" : "formhistory-add");
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function form109_saves() {
|
||||
setUserInput(109, "test9", "savedValue");
|
||||
await checkSubmitSaves(109, "test9", "savedValue", "savedValue");
|
||||
});
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
|
|
|
@ -48,7 +48,7 @@ function startTest() {
|
|||
// value attribute, but we don't save default form values (and we want to
|
||||
// ensure unsaved values are because of autocomplete=off or whatever).
|
||||
for (let i = 1; i <= numInputFields; i++) {
|
||||
$_(1, "test" + i).value = i;
|
||||
getFormElementByName(1, "test" + i).value = i;
|
||||
}
|
||||
|
||||
// submit the first form.
|
||||
|
|
|
@ -137,7 +137,7 @@ function startTest() {
|
|||
// Fill in values for the various fields. We could just set the <input>'s
|
||||
// value attribute, but we don't save default form values (and we want to
|
||||
// ensure unsaved values are because of autocomplete=off or whatever).
|
||||
$_(1, "test" + numInputFields).value = numInputFields + " changed";
|
||||
getFormElementByName(1, "test" + numInputFields).value = numInputFields + " changed";
|
||||
|
||||
// submit the first form.
|
||||
let button = getFormSubmitButton(1);
|
||||
|
|
|
@ -79,8 +79,8 @@ add_task(async function test_initialize() {
|
|||
is(window.location.protocol, "https:", "This test must run on HTTPS");
|
||||
|
||||
// Now that rememberSignons is false, create the password fields.
|
||||
$_(1, "field1").type = "password";
|
||||
$_(2, "field1").type = "password";
|
||||
getFormElementByName(1, "field1").type = "password";
|
||||
getFormElementByName(2, "field1").type = "password";
|
||||
|
||||
await new Promise(resolve => updateFormHistory([
|
||||
{ op: "remove" },
|
||||
|
@ -97,7 +97,7 @@ add_task(async function test_initialize() {
|
|||
});
|
||||
|
||||
add_task(async function test_secure_noFormHistoryOrWarning() {
|
||||
let input = $_(1, "field1");
|
||||
let input = getFormElementByName(1, "field1");
|
||||
|
||||
// The autocomplete popup should not open under any circumstances on
|
||||
// type=password with password manager disabled.
|
||||
|
@ -122,7 +122,7 @@ add_task(async function test_secure_noFormHistoryOrWarning() {
|
|||
|
||||
add_task(async function test_insecure_focusWarning() {
|
||||
// Form 2 has an insecure action so should show the warning even if password manager is disabled.
|
||||
let input = $_(2, "field1");
|
||||
let input = getFormElementByName(2, "field1");
|
||||
let shownPromise = waitForNextPopup();
|
||||
input.focus();
|
||||
await shownPromise;
|
||||
|
|
|
@ -30,7 +30,7 @@ function waitForNextPopup() {
|
|||
}
|
||||
|
||||
add_task(async function test_popup_direction() {
|
||||
let input = $_(1, "field1");
|
||||
let input = getFormElementByName(1, "field1");
|
||||
|
||||
await new Promise(resolve => updateFormHistory([
|
||||
{ op: "remove" },
|
||||
|
|
|
@ -22,7 +22,7 @@ Form History test: Test for events while the form history popup is open
|
|||
<pre id="test">
|
||||
<script class="testbody">
|
||||
var form = document.getElementById("form1");
|
||||
var input = $_(1, "field1");
|
||||
var input = getFormElementByName(1, "field1");
|
||||
var expectedValue = "value1";
|
||||
|
||||
function setupFormHistory(aCallback) {
|
||||
|
|
|
@ -22,7 +22,7 @@ Form History test: Test for keydown handler submitting the form
|
|||
<pre id="test">
|
||||
<script class="testbody">
|
||||
var form = document.getElementById("form1");
|
||||
var input = $_(1, "field1");
|
||||
var input = getFormElementByName(1, "field1");
|
||||
var expectedValue = "value1";
|
||||
var beforeInputFired = false;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче