aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Wörner <git@simon-woerner.de>2017-11-26 15:13:02 +0100
committerSimon Wörner <fixed-term.Simon.Woerner3@boschrexroth.de>2017-12-04 11:21:28 +0100
commita999239f28672aed053c9c3db001a2e6a26efa7f (patch)
tree77165e3391a6ee6cc4155aa0d14380e41fb91a3a
parentac6e04ebfbf27317fea00ea93e855520237b538d (diff)
downloadservo-a999239f28672aed053c9c3db001a2e6a26efa7f.tar.gz
servo-a999239f28672aed053c9c3db001a2e6a26efa7f.zip
Added time input sanitization:
- Implemented is_valid_time_string for DOMString. - Use is_valid_time_string for sanitize_value with time input. - Improved input type change test
-rw-r--r--components/script/dom/bindings/str.rs71
-rwxr-xr-xcomponents/script/dom/htmlinputelement.rs7
-rw-r--r--tests/wpt/metadata/MANIFEST.json2
-rw-r--r--tests/wpt/metadata/html/semantics/forms/the-input-element/time-2.html.ini23
-rw-r--r--tests/wpt/metadata/html/semantics/forms/the-input-element/time.html.ini3
-rw-r--r--tests/wpt/metadata/html/semantics/forms/the-input-element/type-change-state.html.ini222
-rw-r--r--tests/wpt/metadata/html/semantics/forms/the-input-element/valueMode.html.ini6
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/type-change-state.html51
8 files changed, 228 insertions, 157 deletions
diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs
index 3667dddf92d..6601d8e6856 100644
--- a/components/script/dom/bindings/str.rs
+++ b/components/script/dom/bindings/str.rs
@@ -208,6 +208,77 @@ impl DOMString {
self.0.truncate(last_non_whitespace);
let _ = self.0.splice(0..first_non_whitespace, "");
}
+
+ /// Validates this `DOMString` is a time string according to
+ /// <https://html.spec.whatwg.org/multipage/#valid-time-string>.
+ pub fn is_valid_time_string(&self) -> bool {
+ enum State {
+ HourHigh,
+ HourLow09,
+ HourLow03,
+ MinuteColon,
+ MinuteHigh,
+ MinuteLow,
+ SecondColon,
+ SecondHigh,
+ SecondLow,
+ MilliStop,
+ MilliHigh,
+ MilliMiddle,
+ MilliLow,
+ Done,
+ Error,
+ }
+ let next_state = |valid: bool, next: State| -> State { if valid { next } else { State::Error } };
+
+ let state = self.chars().fold(State::HourHigh, |state, c| {
+ match state {
+ // Step 1 "HH"
+ State::HourHigh => {
+ match c {
+ '0' | '1' => State::HourLow09,
+ '2' => State::HourLow03,
+ _ => State::Error,
+ }
+ },
+ State::HourLow09 => next_state(c.is_digit(10), State::MinuteColon),
+ State::HourLow03 => next_state(c.is_digit(4), State::MinuteColon),
+
+ // Step 2 ":"
+ State::MinuteColon => next_state(c == ':', State::MinuteHigh),
+
+ // Step 3 "mm"
+ State::MinuteHigh => next_state(c.is_digit(6), State::MinuteLow),
+ State::MinuteLow => next_state(c.is_digit(10), State::SecondColon),
+
+ // Step 4.1 ":"
+ State::SecondColon => next_state(c == ':', State::SecondHigh),
+ // Step 4.2 "ss"
+ State::SecondHigh => next_state(c.is_digit(6), State::SecondLow),
+ State::SecondLow => next_state(c.is_digit(10), State::MilliStop),
+
+ // Step 4.3.1 "."
+ State::MilliStop => next_state(c == '.', State::MilliHigh),
+ // Step 4.3.2 "SSS"
+ State::MilliHigh => next_state(c.is_digit(6), State::MilliMiddle),
+ State::MilliMiddle => next_state(c.is_digit(10), State::MilliLow),
+ State::MilliLow => next_state(c.is_digit(10), State::Done),
+
+ _ => State::Error,
+ }
+ });
+
+ match state {
+ State::Done |
+ // Step 4 (optional)
+ State::SecondColon |
+ // Step 4.3 (optional)
+ State::MilliStop |
+ // Step 4.3.2 (only 1 digit required)
+ State::MilliMiddle | State::MilliLow => true,
+ _ => false
+ }
+ }
}
impl Borrow<str> for DOMString {
diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs
index 7f995671d8d..0725fafcaac 100755
--- a/components/script/dom/htmlinputelement.rs
+++ b/components/script/dom/htmlinputelement.rs
@@ -895,6 +895,13 @@ impl HTMLInputElement {
textinput.set_content("#000000".into());
}
}
+ atom!("time") => {
+ let mut textinput = self.textinput.borrow_mut();
+
+ if ! textinput.single_line_content().is_valid_time_string() {
+ *textinput.single_line_content_mut() = "".into();
+ }
+ }
// TODO: Implement more value sanitization algorithms for different types of inputs
_ => ()
}
diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json
index 32fd7e9e58e..a7ac7615441 100644
--- a/tests/wpt/metadata/MANIFEST.json
+++ b/tests/wpt/metadata/MANIFEST.json
@@ -543020,7 +543020,7 @@
"testharness"
],
"html/semantics/forms/the-input-element/type-change-state.html": [
- "95e8bfd7d2f14068b0d3e41e3f017da3647bc382",
+ "d731573ee091b7e658ea0b1ded46a764e8165f6c",
"testharness"
],
"html/semantics/forms/the-input-element/url.html": [
diff --git a/tests/wpt/metadata/html/semantics/forms/the-input-element/time-2.html.ini b/tests/wpt/metadata/html/semantics/forms/the-input-element/time-2.html.ini
deleted file mode 100644
index 3d6a79f4c24..00000000000
--- a/tests/wpt/metadata/html/semantics/forms/the-input-element/time-2.html.ini
+++ /dev/null
@@ -1,23 +0,0 @@
-[time-2.html]
- type: testharness
- [Invalid value: fraction should have one, two or three ASCII digits. Value should be empty]
- expected: FAIL
-
- [Invalid value: hour should have two ASCII digits. Value should be empty]
- expected: FAIL
-
- [Invalid value: minutes should have two ASCII digits. Value should be empty]
- expected: FAIL
-
- [Invalid value: seconds should have two ASCII digits. Value should be empty]
- expected: FAIL
-
- [Invalid value: hour > 23. Value should be empty]
- expected: FAIL
-
- [Invalid value: minute > 59. Value should be empty]
- expected: FAIL
-
- [Invalid value: second > 59. Value should be empty]
- expected: FAIL
-
diff --git a/tests/wpt/metadata/html/semantics/forms/the-input-element/time.html.ini b/tests/wpt/metadata/html/semantics/forms/the-input-element/time.html.ini
index a9d391f1797..8c6c3d92631 100644
--- a/tests/wpt/metadata/html/semantics/forms/the-input-element/time.html.ini
+++ b/tests/wpt/metadata/html/semantics/forms/the-input-element/time.html.ini
@@ -69,9 +69,6 @@
[ empty value of stepUp]
expected: FAIL
- [set value on not time format value]
- expected: FAIL
-
[stepUp on step value with fractional seconds]
expected: FAIL
diff --git a/tests/wpt/metadata/html/semantics/forms/the-input-element/type-change-state.html.ini b/tests/wpt/metadata/html/semantics/forms/the-input-element/type-change-state.html.ini
index c090fb26995..cc3c76ce1ab 100644
--- a/tests/wpt/metadata/html/semantics/forms/the-input-element/type-change-state.html.ini
+++ b/tests/wpt/metadata/html/semantics/forms/the-input-element/type-change-state.html.ini
@@ -15,9 +15,6 @@
[change state from hidden to week]
expected: FAIL
- [change state from hidden to time]
- expected: FAIL
-
[change state from hidden to number]
expected: FAIL
@@ -39,9 +36,6 @@
[change state from text to week]
expected: FAIL
- [change state from text to time]
- expected: FAIL
-
[change state from text to number]
expected: FAIL
@@ -63,9 +57,6 @@
[change state from search to week]
expected: FAIL
- [change state from search to time]
- expected: FAIL
-
[change state from search to number]
expected: FAIL
@@ -87,9 +78,6 @@
[change state from tel to week]
expected: FAIL
- [change state from tel to time]
- expected: FAIL
-
[change state from tel to number]
expected: FAIL
@@ -120,9 +108,6 @@
[change state from url to week]
expected: FAIL
- [change state from url to time]
- expected: FAIL
-
[change state from url to number]
expected: FAIL
@@ -162,9 +147,6 @@
[change state from email to week]
expected: FAIL
- [change state from email to time]
- expected: FAIL
-
[change state from email to number]
expected: FAIL
@@ -186,9 +168,6 @@
[change state from password to week]
expected: FAIL
- [change state from password to time]
- expected: FAIL
-
[change state from password to number]
expected: FAIL
@@ -222,9 +201,6 @@
[change state from datetime to week]
expected: FAIL
- [change state from datetime to time]
- expected: FAIL
-
[change state from datetime to number]
expected: FAIL
@@ -264,9 +240,6 @@
[change state from date to week]
expected: FAIL
- [change state from date to time]
- expected: FAIL
-
[change state from date to number]
expected: FAIL
@@ -306,9 +279,6 @@
[change state from month to week]
expected: FAIL
- [change state from month to time]
- expected: FAIL
-
[change state from month to number]
expected: FAIL
@@ -348,57 +318,12 @@
[change state from week to month]
expected: FAIL
- [change state from week to time]
- expected: FAIL
-
[change state from week to number]
expected: FAIL
[change state from week to range]
expected: FAIL
- [change state from time to hidden]
- expected: FAIL
-
- [change state from time to checkbox]
- expected: FAIL
-
- [change state from time to radio]
- expected: FAIL
-
- [change state from time to submit]
- expected: FAIL
-
- [change state from time to image]
- expected: FAIL
-
- [change state from time to reset]
- expected: FAIL
-
- [change state from time to button]
- expected: FAIL
-
- [change state from time to email]
- expected: FAIL
-
- [change state from time to datetime]
- expected: FAIL
-
- [change state from time to date]
- expected: FAIL
-
- [change state from time to month]
- expected: FAIL
-
- [change state from time to week]
- expected: FAIL
-
- [change state from time to number]
- expected: FAIL
-
- [change state from time to range]
- expected: FAIL
-
[change state from number to hidden]
expected: FAIL
@@ -435,9 +360,6 @@
[change state from number to week]
expected: FAIL
- [change state from number to time]
- expected: FAIL
-
[change state from number to range]
expected: FAIL
@@ -477,9 +399,6 @@
[change state from range to week]
expected: FAIL
- [change state from range to time]
- expected: FAIL
-
[change state from range to number]
expected: FAIL
@@ -498,9 +417,6 @@
[change state from checkbox to week]
expected: FAIL
- [change state from checkbox to time]
- expected: FAIL
-
[change state from checkbox to number]
expected: FAIL
@@ -522,9 +438,6 @@
[change state from radio to week]
expected: FAIL
- [change state from radio to time]
- expected: FAIL
-
[change state from radio to number]
expected: FAIL
@@ -546,9 +459,6 @@
[change state from submit to week]
expected: FAIL
- [change state from submit to time]
- expected: FAIL
-
[change state from submit to number]
expected: FAIL
@@ -570,9 +480,6 @@
[change state from image to week]
expected: FAIL
- [change state from image to time]
- expected: FAIL
-
[change state from image to number]
expected: FAIL
@@ -594,9 +501,6 @@
[change state from reset to week]
expected: FAIL
- [change state from reset to time]
- expected: FAIL
-
[change state from reset to number]
expected: FAIL
@@ -618,9 +522,6 @@
[change state from button to week]
expected: FAIL
- [change state from button to time]
- expected: FAIL
-
[change state from button to number]
expected: FAIL
@@ -681,9 +582,6 @@
[change state from datetime-local to week]
expected: FAIL
- [change state from datetime-local to time]
- expected: FAIL
-
[change state from datetime-local to number]
expected: FAIL
@@ -699,9 +597,6 @@
[change state from week to datetime-local]
expected: FAIL
- [change state from time to datetime-local]
- expected: FAIL
-
[change state from number to datetime-local]
expected: FAIL
@@ -726,3 +621,120 @@
[change state from button to datetime-local]
expected: FAIL
+
+ [change state from datetime-local to text]
+ expected: FAIL
+
+ [change state from datetime-local to search]
+ expected: FAIL
+
+ [change state from datetime-local to tel]
+ expected: FAIL
+
+ [change state from datetime-local to url]
+ expected: FAIL
+
+ [change state from datetime-local to password]
+ expected: FAIL
+
+
+ [change state from date to text]
+ expected: FAIL
+
+ [change state from date to search]
+ expected: FAIL
+
+ [change state from date to tel]
+ expected: FAIL
+
+ [change state from date to url]
+ expected: FAIL
+
+ [change state from date to password]
+ expected: FAIL
+
+
+ [change state from month to text]
+ expected: FAIL
+
+ [change state from month to search]
+ expected: FAIL
+
+ [change state from month to tel]
+ expected: FAIL
+
+ [change state from month to url]
+ expected: FAIL
+
+ [change state from month to password]
+ expected: FAIL
+
+
+ [change state from week to text]
+ expected: FAIL
+
+ [change state from week to search]
+ expected: FAIL
+
+ [change state from week to tel]
+ expected: FAIL
+
+ [change state from week to url]
+ expected: FAIL
+
+ [change state from week to password]
+ expected: FAIL
+
+
+ [change state from number to text]
+ expected: FAIL
+
+ [change state from number to search]
+ expected: FAIL
+
+ [change state from number to tel]
+ expected: FAIL
+
+ [change state from number to url]
+ expected: FAIL
+
+ [change state from number to password]
+ expected: FAIL
+
+
+ [change state from color to datetime-local]
+ expected: FAIL
+
+ [change state from color to date]
+ expected: FAIL
+
+ [change state from color to month]
+ expected: FAIL
+
+ [change state from color to week]
+ expected: FAIL
+
+ [change state from color to number]
+ expected: FAIL
+
+ [change state from color to range]
+ expected: FAIL
+
+
+ [change state from time to range]
+ expected: FAIL
+
+ [change state from range to text]
+ expected: FAIL
+
+ [change state from range to search]
+ expected: FAIL
+
+ [change state from range to tel]
+ expected: FAIL
+
+ [change state from range to url]
+ expected: FAIL
+
+ [change state from range to password]
+ expected: FAIL
diff --git a/tests/wpt/metadata/html/semantics/forms/the-input-element/valueMode.html.ini b/tests/wpt/metadata/html/semantics/forms/the-input-element/valueMode.html.ini
index eaf6e37bccc..8c54f4d21d9 100644
--- a/tests/wpt/metadata/html/semantics/forms/the-input-element/valueMode.html.ini
+++ b/tests/wpt/metadata/html/semantics/forms/the-input-element/valueMode.html.ini
@@ -24,12 +24,6 @@
[value IDL attribute of input type week with value attribute]
expected: FAIL
- [value IDL attribute of input type time without value attribute]
- expected: FAIL
-
- [value IDL attribute of input type time with value attribute]
- expected: FAIL
-
[value IDL attribute of input type number without value attribute]
expected: FAIL
diff --git a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/type-change-state.html b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/type-change-state.html
index ed64cf789a1..82d36cda481 100644
--- a/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/type-change-state.html
+++ b/tests/wpt/web-platform-tests/html/semantics/forms/the-input-element/type-change-state.html
@@ -15,16 +15,16 @@
{ type: "url", sanitizedValue: "foobar" },
{ type: "email", sanitizedValue: "foobar" },
{ type: "password", sanitizedValue: " foobar " },
- { type: "datetime-local", sanitizedValue: "" },
- { type: "date", sanitizedValue: "" },
- { type: "month", sanitizedValue: "" },
- { type: "week", sanitizedValue: "" },
- { type: "time", sanitizedValue: "" },
- { type: "number", sanitizedValue: "" },
- { type: "range", sanitizedValue: "50" },
- { type: "color", sanitizedValue: "#000000" },
- { type: "checkbox" },
- { type: "radio" },
+ { type: "datetime-local", sanitizedValue: "", overridesSanitization: true },
+ { type: "date", sanitizedValue: "", overridesSanitization: true },
+ { type: "month", sanitizedValue: "", overridesSanitization: true },
+ { type: "week", sanitizedValue: "", overridesSanitization: true },
+ { type: "time", sanitizedValue: "", overridesSanitization: true },
+ { type: "number", sanitizedValue: "", overridesSanitization: true },
+ { type: "range", sanitizedValue: "50", overridesSanitization: true },
+ { type: "color", sanitizedValue: "#000000", overridesSanitization: true },
+ { type: "checkbox", defaultValue: "on" },
+ { type: "radio", defaultValue: "on" },
{ type: "file" },
{ type: "submit" },
{ type: "image" },
@@ -36,26 +36,39 @@
if (types[i] != types[j]) {
test(function() {
var input = document.createElement("input");
+ var expected = " foo\rbar ";
input.type = types[i].type;
if (types[i].type === "file") {
assert_throws("INVALID_STATE_ERR", function() {
- input.value = " foo\rbar ";
+ input.value = expected;
});
assert_equals(input.value, "");
} else if (types[j].type === "file") {
- input.value = " foo\rbar ";
+ input.value = expected;
input.type = types[j].type; // change state
assert_equals(input.value, "");
} else {
- input.value = " foo\rbar ";
+ input.value = expected;
input.type = types[j].type; // change state
- if (types[i].type !== "color" && (types[j].sanitizedValue || types[j].sanitizedValue === "")) {
- assert_equals(input.value, types[j].sanitizedValue, "input.value should be " + types[j].sanitizedValue + " after change of state");
- } else if (types[i].sanitizedValue || types[i].sanitizedValue === "") {
- assert_equals(input.value, types[i].sanitizedValue, "input.value should be " + types[i].sanitizedValue + " after change of state");
- } else {
- assert_equals(input.value, " foo\rbar ", "input.value should be ' foo\\rbar ' after change of state");
+
+ // type[i] sanitization
+ if (types[i].sanitizedValue || types[i].sanitizedValue === "") {
+ expected = types[i].sanitizedValue;
}
+
+ // type[j] sanitization
+ if (types[j].sanitizedValue || types[j].sanitizedValue === "") {
+ if ((expected !== "" && !types[i].overridesSanitization) || types[j].overridesSanitization) {
+ expected = types[j].sanitizedValue;
+ }
+ }
+
+ // type[j] defaultValue
+ if (expected === "" && types[j].defaultValue) {
+ expected = types[j].defaultValue;
+ }
+
+ assert_equals(input.value, expected, "input.value should be '" + expected + "' after change of state");
}
}, "change state from " + types[i].type + " to " + types[j].type);
}