VTTCue: Support 'auto' for line

Since the setter is no longer limitting the value to [0, 100] we need to
store an additional flag for the 'auto' value.
Minor updates to VTTCue::calculateComputedLinePosition to match updated
spec. (this is now where the line value is checked against the above
range.)

BUG=448000

Review URL: https://codereview.chromium.org/850363005

git-svn-id: svn://svn.chromium.org/blink/trunk@188723 bbb929c8-8fbe-4397-9dbb-9b2b20218538
diff --git a/LayoutTests/media/track/opera/interfaces/VTTCue/line-expected.txt b/LayoutTests/media/track/opera/interfaces/VTTCue/line-expected.txt
deleted file mode 100644
index 97ac175..0000000
--- a/LayoutTests/media/track/opera/interfaces/VTTCue/line-expected.txt
+++ /dev/null
@@ -1,5 +0,0 @@
- This is a testharness.js-based test.
-FAIL VTTCue.line, script-created cue assert_equals: expected -2 but got -1
-PASS VTTCue.line, parsed cue 
-Harness: the test ran to completion.
-
diff --git a/LayoutTests/media/track/opera/interfaces/VTTCue/line.html b/LayoutTests/media/track/opera/interfaces/VTTCue/line.html
index 7df65eb..cc98992 100644
--- a/LayoutTests/media/track/opera/interfaces/VTTCue/line.html
+++ b/LayoutTests/media/track/opera/interfaces/VTTCue/line.html
@@ -8,31 +8,37 @@
     var video = document.createElement('video');
     document.body.appendChild(video);
     var c1 = new VTTCue(0, 1, 'text1');
-    assert_equals(c1.line, -1);
+    assert_equals(c1.line, 'auto');
     var track = document.createElement('track');
     var t = track.track;
     t.addCue(c1);
-    assert_equals(c1.line, -1);
+    assert_equals(c1.line, 'auto');
     video.appendChild(track);
-    assert_equals(c1.line, -1);
+    assert_equals(c1.line, 'auto');
     t.mode = 'showing';
-    assert_equals(c1.line, -1);
+    assert_equals(c1.line, 'auto');
     var c2 = new VTTCue(0, 1, 'text2');
     var track2 = document.createElement('track');
     var t2 = track2.track;
     t2.addCue(c2);
-    assert_equals(c2.line, -1);
+    assert_equals(c2.line, 'auto');
     video.appendChild(track2);
     t2.mode = 'showing';
-    assert_equals(c2.line, -2);
-    assert_equals(c1.line, -1);
+    assert_equals(c2.line, 'auto');
+    assert_equals(c1.line, 'auto');
     c1.line = -5;
     assert_equals(c1.line, -5);
-    assert_equals(c2.line, -2);
+    assert_equals(c2.line, 'auto');
     c1.line = 0;
     c1.snapToLines = false;
     assert_equals(c1.line, 0);
-    assert_equals(c2.line, -2);
+    assert_equals(c2.line, 'auto');
+    assert_throws(new TypeError, function() { c1.line = 'auto\0'; });
+    assert_throws(new TypeError, function() { c1.line = NaN; });
+    assert_throws(new TypeError, function() { c1.line = Infinity; });
+    assert_equals(c1.line, 0);
+    c1.line = -1;
+    assert_equals(c1.line, -1);
 }, document.title+', script-created cue');
 
 var t_parsed = async_test(document.title+', parsed cue');
@@ -44,7 +50,7 @@
         var c1 = t.track.cues[0];
         var c2 = t.track.cues[1];
         var c3 = t.track.cues[2];
-        assert_equals(c1.line, -1);
+        assert_equals(c1.line, 'auto');
         assert_equals(c2.line, 0);
         assert_equals(c3.line, 0);
 
diff --git a/LayoutTests/media/track/opera/track/webvtt/parsing/001.html b/LayoutTests/media/track/opera/track/webvtt/parsing/001.html
index 2bd8b7c..f003b42 100644
--- a/LayoutTests/media/track/opera/track/webvtt/parsing/001.html
+++ b/LayoutTests/media/track/opera/track/webvtt/parsing/001.html
@@ -14,7 +14,7 @@
 "pauseOnExit":false,
 //"vertical":"", (not supported)
 "snapToLines":true,
-"line":-1,
+"line":"auto",
 "position":50,
 "size":100,
 "align":"middle"
@@ -93,4 +93,4 @@
     document.body.removeChild(elm);
 }
 
-</script>
\ No newline at end of file
+</script>
diff --git a/LayoutTests/media/track/track-add-remove-cue-expected.txt b/LayoutTests/media/track/track-add-remove-cue-expected.txt
index b4bf2da..11896d9 100644
--- a/LayoutTests/media/track/track-add-remove-cue-expected.txt
+++ b/LayoutTests/media/track/track-add-remove-cue-expected.txt
@@ -18,7 +18,7 @@
 EXPECTED (textCue.pauseOnExit == 'false') OK
 EXPECTED (textCue.vertical == '') OK
 EXPECTED (textCue.snapToLines == 'true') OK
-EXPECTED (textCue.line == '-1') OK
+EXPECTED (textCue.line == 'auto') OK
 EXPECTED (textCue.position == '50') OK
 EXPECTED (textCue.size == '100') OK
 EXPECTED (textCue.align == 'middle') OK
@@ -44,7 +44,7 @@
 EXPECTED (newCue.pauseOnExit == 'false') OK
 EXPECTED (newCue.vertical == '') OK
 EXPECTED (newCue.snapToLines == 'true') OK
-EXPECTED (newCue.line == '-1') OK
+EXPECTED (newCue.line == 'auto') OK
 EXPECTED (newCue.position == '50') OK
 EXPECTED (newCue.size == '100') OK
 EXPECTED (newCue.align == 'middle') OK
diff --git a/LayoutTests/media/track/track-add-remove-cue.html b/LayoutTests/media/track/track-add-remove-cue.html
index 4eb01f1..82e5b7f 100644
--- a/LayoutTests/media/track/track-add-remove-cue.html
+++ b/LayoutTests/media/track/track-add-remove-cue.html
@@ -31,7 +31,7 @@
                 testExpected("textCue.pauseOnExit", false);
                 testExpected("textCue.vertical", "");
                 testExpected("textCue.snapToLines", true);
-                testExpected("textCue.line", -1);
+                testExpected("textCue.line", "auto");
                 testExpected("textCue.position", 50);
                 testExpected("textCue.size", 100);
                 testExpected("textCue.align", "middle");
@@ -59,7 +59,7 @@
                 testExpected("newCue.pauseOnExit", false);
                 testExpected("newCue.vertical", "");
                 testExpected("newCue.snapToLines", true);
-                testExpected("newCue.line", -1);
+                testExpected("newCue.line", "auto");
                 testExpected("newCue.position", 50);
                 testExpected("newCue.size", 100);
                 testExpected("newCue.align", "middle");
diff --git a/LayoutTests/media/track/track-cue-mutable-expected.txt b/LayoutTests/media/track/track-cue-mutable-expected.txt
index aacffdf..ea9d78f 100644
--- a/LayoutTests/media/track/track-cue-mutable-expected.txt
+++ b/LayoutTests/media/track/track-cue-mutable-expected.txt
@@ -7,7 +7,7 @@
 EXPECTED (textCue.pauseOnExit == 'false') OK
 EXPECTED (textCue.vertical == '') OK
 EXPECTED (textCue.snapToLines == 'true') OK
-EXPECTED (textCue.line == '-1') OK
+EXPECTED (textCue.line == 'auto') OK
 EXPECTED (textCue.position == '50') OK
 EXPECTED (textCue.size == '100') OK
 EXPECTED (textCue.align == 'middle') OK
@@ -32,13 +32,17 @@
 RUN(textCue.snapToLines = false)
 EXPECTED (textCue.snapToLines == 'false') OK
 
-On setting, if the text track cue snap-to-lines flag is not set, and the new value is negative or greater than 100, then throw an IndexSizeError exception.
-http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#dom-texttrackcue-line
-TEST(textCue.line = -2) THROWS(DOMException.INDEX_SIZE_ERR: Failed to set the 'line' property on 'VTTCue': The snap-to-lines flag is not set, and the value provided (-2) is not between 0 and 100.) OK
-TEST(textCue.line = 102) THROWS(DOMException.INDEX_SIZE_ERR: Failed to set the 'line' property on 'VTTCue': The snap-to-lines flag is not set, and the value provided (102) is not between 0 and 100.) OK
-EXPECTED (textCue.line == '-1') OK
+On setting, the text track cue line position must be set to the new value; if the new value is the string 'auto', then it must be interpreted as the special value auto.
+http://dev.w3.org/html5/webvtt/#dfn-vttcue-line
+EXPECTED (textCue.line == 'auto') OK
+TEST(textCue.line = 'gazonk') THROWS("TypeError: Failed to set the 'line' property on 'VTTCue': 'gazonk' is not a valid enum value.") OK
+EXPECTED (textCue.line == 'auto') OK
 RUN(textCue.line = 42)
 EXPECTED (textCue.line == '42') OK
+RUN(textCue.line = -2)
+EXPECTED (textCue.line == '-2') OK
+RUN(textCue.line = 102)
+EXPECTED (textCue.line == '102') OK
 RUN(textCue.snapToLines = true)
 RUN(textCue.line = -2)
 EXPECTED (textCue.line == '-2') OK
diff --git a/LayoutTests/media/track/track-cue-mutable.html b/LayoutTests/media/track/track-cue-mutable.html
index 698bfb8..decac85 100644
--- a/LayoutTests/media/track/track-cue-mutable.html
+++ b/LayoutTests/media/track/track-cue-mutable.html
@@ -28,7 +28,7 @@
                 testExpected("textCue.pauseOnExit", false);
                 testExpected("textCue.vertical", "");
                 testExpected("textCue.snapToLines", true);
-                testExpected("textCue.line", -1);
+                testExpected("textCue.line", "auto");
                 testExpected("textCue.position", 50);
                 testExpected("textCue.size", 100);
                 testExpected("textCue.align", "middle");
@@ -57,13 +57,17 @@
                 run("textCue.snapToLines = false");
                 testExpected("textCue.snapToLines", false);
 
-                logSpecURL("http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#dom-texttrackcue-line",
-                            "On setting, if the text track cue snap-to-lines flag is not set, and the new value is negative or greater than 100, then throw an IndexSizeError exception.");
-                testDOMException("textCue.line = -2", "DOMException.INDEX_SIZE_ERR");
-                testDOMException("textCue.line = 102", "DOMException.INDEX_SIZE_ERR");
-                testExpected("textCue.line", -1);
+                logSpecURL("http://dev.w3.org/html5/webvtt/#dfn-vttcue-line",
+                           "On setting, the text track cue line position must be set to the new value; if the new value is the string 'auto', then it must be interpreted as the special value auto.");
+                testExpected("textCue.line", "auto");
+                testException("textCue.line = 'gazonk'", '"TypeError: Failed to set the \'line\' property on \'VTTCue\': \'gazonk\' is not a valid enum value."');
+                testExpected("textCue.line", "auto");
                 run("textCue.line = 42");
                 testExpected("textCue.line", 42);
+                run("textCue.line = -2");
+                testExpected("textCue.line", -2);
+                run("textCue.line = 102");
+                testExpected("textCue.line", 102);
                 run("textCue.snapToLines = true");
                 run("textCue.line = -2");
                 testExpected("textCue.line", -2);
diff --git a/LayoutTests/media/track/track-webvtt-tc013-settings-expected.txt b/LayoutTests/media/track/track-webvtt-tc013-settings-expected.txt
index 5a524a4..4401497 100644
--- a/LayoutTests/media/track/track-webvtt-tc013-settings-expected.txt
+++ b/LayoutTests/media/track/track-webvtt-tc013-settings-expected.txt
@@ -11,7 +11,7 @@
 EXPECTED (cues[1].position == '40') OK
 EXPECTED (cues[1].align == 'middle') OK
 EXPECTED (cues[1].vertical == 'rl') OK
-EXPECTED (cues[2].line == '-1') OK
+EXPECTED (cues[2].line == 'auto') OK
 EXPECTED (cues[2].position == '10') OK
 EXPECTED (cues[2].align == 'middle') OK
 EXPECTED (cues[2].vertical == '') OK
@@ -26,15 +26,15 @@
 EXPECTED (cues[0].position == '10') OK
 EXPECTED (cues[0].align == 'middle') OK
 EXPECTED (cues[0].vertical == '') OK
-EXPECTED (cues[1].line == '-1') OK
+EXPECTED (cues[1].line == 'auto') OK
 EXPECTED (cues[1].position == '50') OK
 EXPECTED (cues[1].align == 'end') OK
 EXPECTED (cues[1].vertical == '') OK
-EXPECTED (cues[2].line == '-1') OK
+EXPECTED (cues[2].line == 'auto') OK
 EXPECTED (cues[2].position == '50') OK
 EXPECTED (cues[2].align == 'middle') OK
 EXPECTED (cues[2].vertical == '') OK
-EXPECTED (cues[3].line == '-1') OK
+EXPECTED (cues[3].line == 'auto') OK
 EXPECTED (cues[3].position == '90') OK
 EXPECTED (cues[3].align == 'middle') OK
 EXPECTED (cues[3].vertical == 'lr') OK
diff --git a/LayoutTests/media/track/track-webvtt-tc013-settings.html b/LayoutTests/media/track/track-webvtt-tc013-settings.html
index b4163c2..f37cd7b 100644
--- a/LayoutTests/media/track/track-webvtt-tc013-settings.html
+++ b/LayoutTests/media/track/track-webvtt-tc013-settings.html
@@ -29,7 +29,7 @@
                         [
                             {
                                 property : "line",
-                                values : [100, 15, -1, 95],
+                                values : [100, 15, "auto", 95],
                             },
                             {
                                 property : "position",
@@ -51,7 +51,7 @@
                         [
                             {
                                 property : "line",
-                                values : [43, -1, -1, -1],
+                                values : [43, "auto", "auto", "auto"],
                             },
                             {
                                 property : "position",
@@ -81,4 +81,4 @@
             <track src="captions-webvtt/tc013-settings-bad-separation.vtt" onload="trackLoaded()">
         </video>
     </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/LayoutTests/media/track/track-webvtt-tc017-line-position-expected.txt b/LayoutTests/media/track/track-webvtt-tc017-line-position-expected.txt
index 496ff7e..8bb458c 100644
--- a/LayoutTests/media/track/track-webvtt-tc017-line-position-expected.txt
+++ b/LayoutTests/media/track/track-webvtt-tc017-line-position-expected.txt
@@ -20,17 +20,17 @@
 
 *** Testing text track 1
 EXPECTED (cues.length == '6') OK
-EXPECTED (cues[0].line == '-1') OK
+EXPECTED (cues[0].line == 'auto') OK
 EXPECTED (cues[0].snapToLines == 'true') OK
-EXPECTED (cues[1].line == '-1') OK
+EXPECTED (cues[1].line == 'auto') OK
 EXPECTED (cues[1].snapToLines == 'true') OK
-EXPECTED (cues[2].line == '-1') OK
+EXPECTED (cues[2].line == 'auto') OK
 EXPECTED (cues[2].snapToLines == 'true') OK
-EXPECTED (cues[3].line == '-1') OK
+EXPECTED (cues[3].line == 'auto') OK
 EXPECTED (cues[3].snapToLines == 'true') OK
-EXPECTED (cues[4].line == '-1') OK
+EXPECTED (cues[4].line == 'auto') OK
 EXPECTED (cues[4].snapToLines == 'true') OK
-EXPECTED (cues[5].line == '-1') OK
+EXPECTED (cues[5].line == 'auto') OK
 EXPECTED (cues[5].snapToLines == 'true') OK
 END OF TEST
 
diff --git a/LayoutTests/media/track/track-webvtt-tc017-line-position.html b/LayoutTests/media/track/track-webvtt-tc017-line-position.html
index 46ef8f1..cc2b238 100644
--- a/LayoutTests/media/track/track-webvtt-tc017-line-position.html
+++ b/LayoutTests/media/track/track-webvtt-tc017-line-position.html
@@ -51,7 +51,7 @@
                     [
                         {
                             property : "line",
-                            values : [-1, -1, -1, -1, -1, -1, -1],
+                            values : ["auto", "auto", "auto", "auto", "auto", "auto", "auto"],
                         },
                         {
                             property : "snapToLines",
@@ -72,4 +72,4 @@
             <track src="captions-webvtt/tc017-line-position-bad.vtt" onload="trackLoaded()">
         </video>
     </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/LayoutTests/media/track/track-webvtt-tc018-align-text-line-position-expected.txt b/LayoutTests/media/track/track-webvtt-tc018-align-text-line-position-expected.txt
index 10ab916..913f7d5 100644
--- a/LayoutTests/media/track/track-webvtt-tc018-align-text-line-position-expected.txt
+++ b/LayoutTests/media/track/track-webvtt-tc018-align-text-line-position-expected.txt
@@ -28,11 +28,11 @@
 EXPECTED (cues.length == '3') OK
 EXPECTED (cues[0].align == 'middle') OK
 EXPECTED (cues[0].position == '50') OK
-EXPECTED (cues[0].line == '-1') OK
+EXPECTED (cues[0].line == 'auto') OK
 EXPECTED (cues[0].snapToLines == 'true') OK
 EXPECTED (cues[1].align == 'end') OK
 EXPECTED (cues[1].position == '0') OK
-EXPECTED (cues[1].line == '-1') OK
+EXPECTED (cues[1].line == 'auto') OK
 EXPECTED (cues[1].snapToLines == 'true') OK
 EXPECTED (cues[2].align == 'middle') OK
 EXPECTED (cues[2].position == '60') OK
diff --git a/LayoutTests/media/track/track-webvtt-tc018-align-text-line-position.html b/LayoutTests/media/track/track-webvtt-tc018-align-text-line-position.html
index 594e6ee..57c6402 100644
--- a/LayoutTests/media/track/track-webvtt-tc018-align-text-line-position.html
+++ b/LayoutTests/media/track/track-webvtt-tc018-align-text-line-position.html
@@ -68,7 +68,7 @@
                         },
                         {
                             property : "line",
-                            values : [-1, -1, -3],
+                            values : ["auto", "auto", -3],
                         },
                         {
                             property : "snapToLines",
@@ -89,4 +89,4 @@
             <track src="captions-webvtt/tc018-align-text-line-position-bad.vtt" onload="trackLoaded()">
         </video>
     </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/LayoutTests/media/track/vtt-cue-exceptions-expected.txt b/LayoutTests/media/track/vtt-cue-exceptions-expected.txt
index 3b92900..bf9f891 100644
--- a/LayoutTests/media/track/vtt-cue-exceptions-expected.txt
+++ b/LayoutTests/media/track/vtt-cue-exceptions-expected.txt
@@ -3,8 +3,6 @@
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS cue.line = -1; threw exception IndexSizeError: Failed to set the 'line' property on 'VTTCue': The snap-to-lines flag is not set, and the value provided (-1) is not between 0 and 100..
-PASS cue.line = 101; threw exception IndexSizeError: Failed to set the 'line' property on 'VTTCue': The snap-to-lines flag is not set, and the value provided (101) is not between 0 and 100..
 PASS cue.position = -1; threw exception IndexSizeError: Failed to set the 'position' property on 'VTTCue': The value provided (-1) is outside the range [0, 100]..
 PASS cue.position = 101; threw exception IndexSizeError: Failed to set the 'position' property on 'VTTCue': The value provided (101) is outside the range [0, 100]..
 PASS cue.size = -1; threw exception IndexSizeError: Failed to set the 'size' property on 'VTTCue': The value provided (-1) is outside the range [0, 100]..
diff --git a/LayoutTests/media/track/vtt-cue-exceptions.html b/LayoutTests/media/track/vtt-cue-exceptions.html
index 626ea46..250beff2 100644
--- a/LayoutTests/media/track/vtt-cue-exceptions.html
+++ b/LayoutTests/media/track/vtt-cue-exceptions.html
@@ -14,9 +14,6 @@
             shouldThrow("cue." + property + " = 101;");
         }
 
-        cue.snapToLines = false;
-        testPercentage("line");
-
         testPercentage("position");
         testPercentage("size");
     </script>
diff --git a/Source/core/html/track/vtt/VTTCue.cpp b/Source/core/html/track/vtt/VTTCue.cpp
index 18669e8..9ec278a 100644
--- a/Source/core/html/track/vtt/VTTCue.cpp
+++ b/Source/core/html/track/vtt/VTTCue.cpp
@@ -32,6 +32,7 @@
 
 #include "bindings/core/v8/ExceptionMessages.h"
 #include "bindings/core/v8/ExceptionStatePlaceholder.h"
+#include "bindings/core/v8/UnionTypesCore.h"
 #include "core/CSSPropertyNames.h"
 #include "core/CSSValueKeywords.h"
 #include "core/dom/DocumentFragment.h"
@@ -55,7 +56,6 @@
 
 namespace blink {
 
-static const float undefinedPosition = -1;
 static const float undefinedSize = -1;
 
 static const CSSValueID displayWritingModeMap[] = {
@@ -70,6 +70,12 @@
 static_assert(WTF_ARRAY_LENGTH(displayAlignmentMap) == VTTCue::NumberOfAlignments,
     "displayAlignmentMap should have the same number of elements as VTTCue::NumberOfAlignments");
 
+static const String& autoKeyword()
+{
+    DEFINE_STATIC_LOCAL(const String, autoString, ("auto"));
+    return autoString;
+}
+
 static const String& startKeyword()
 {
     DEFINE_STATIC_LOCAL(const String, start, ("start"));
@@ -117,10 +123,15 @@
     return verticallr;
 }
 
-static bool isInvalidPercentage(double value, ExceptionState& exceptionState)
+static bool isInvalidPercentage(double value)
 {
     ASSERT(std::isfinite(value));
-    if (value < 0 || value > 100) {
+    return value < 0 || value > 100;
+}
+
+static bool isInvalidPercentage(double value, ExceptionState& exceptionState)
+{
+    if (isInvalidPercentage(value)) {
         exceptionState.throwDOMException(IndexSizeError, ExceptionMessages::indexOutsideRange<double>("value", value, 0, ExceptionMessages::InclusiveBound, 100, ExceptionMessages::InclusiveBound));
         return true;
     }
@@ -211,8 +222,8 @@
 VTTCue::VTTCue(Document& document, double startTime, double endTime, const String& text)
     : TextTrackCue(startTime, endTime)
     , m_text(text)
-    , m_linePosition(undefinedPosition)
-    , m_computedLinePosition(undefinedPosition)
+    , m_linePosition(std::numeric_limits<float>::quiet_NaN())
+    , m_computedLinePosition(std::numeric_limits<float>::quiet_NaN())
     , m_textPosition(50)
     , m_cueSize(100)
     , m_writingDirection(Horizontal)
@@ -306,20 +317,43 @@
     cueDidChange();
 }
 
-void VTTCue::setLine(double position, ExceptionState& exceptionState)
+bool VTTCue::lineIsAuto() const
 {
-    // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#dom-texttrackcue-line
-    // On setting, if the text track cue snap-to-lines flag is not set, and the new
-    // value is negative or greater than 100, then throw an IndexSizeError exception.
-    if (!m_snapToLines && (position < 0 || position > 100)) {
-        exceptionState.throwDOMException(IndexSizeError, "The snap-to-lines flag is not set, and the value provided (" + String::number(position) + ") is not between 0 and 100.");
+    return std::isnan(m_linePosition);
+}
+
+void VTTCue::line(DoubleOrAutoKeyword& result) const
+{
+    if (lineIsAuto())
+        result.setAutoKeyword(autoKeyword());
+    else
+        result.setDouble(m_linePosition);
+}
+
+void VTTCue::setLine(const DoubleOrAutoKeyword& position, ExceptionState& exceptionState)
+{
+    // FIXME: Expecting bindings code to handle this case: https://crbug.com/450252.
+    if (position.isDouble() && !std::isfinite(position.getAsDouble())) {
+        exceptionState.throwTypeError("The provided double value is non-finite.");
         return;
     }
 
-    // Otherwise, set the text track cue line position to the new value.
-    float floatPosition = narrowPrecisionToFloat(position);
-    if (m_linePosition == floatPosition)
-        return;
+    // http://dev.w3.org/html5/webvtt/#dfn-vttcue-line
+    // On setting, the text track cue line position must be set to the new
+    // value; if the new value is the string "auto", then it must be
+    // interpreted as the special value auto.
+    // ("auto" is translated to NaN.)
+    float floatPosition;
+    if (position.isAutoKeyword()) {
+        if (lineIsAuto())
+            return;
+        floatPosition = std::numeric_limits<float>::quiet_NaN();
+    } else {
+        ASSERT(position.isDouble());
+        floatPosition = narrowPrecisionToFloat(position.getAsDouble());
+        if (m_linePosition == floatPosition)
+            return;
+    }
 
     cueWillChange();
     m_linePosition = floatPosition;
@@ -472,36 +506,47 @@
 
 float VTTCue::calculateComputedLinePosition()
 {
-    // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-video-element.html#text-track-cue-computed-line-position
+    // http://dev.w3.org/html5/webvtt/#dfn-text-track-cue-computed-line-position
+    // A text track cue has a text track cue computed line position whose value
+    // is that returned by the following algorithm, which is defined in terms
+    // of the other aspects of the cue:
 
-    // If the text track cue line position is numeric, then that is the text
-    // track cue computed line position.
-    if (m_linePosition != undefinedPosition)
+    // 1. If the text track cue line position is numeric, the text track cue
+    //    snap-to-lines flag of the text track cue is not set, and the text
+    //    track cue line position is negative or greater than 100, then return
+    //    100 and abort these steps.
+    if (!lineIsAuto() && !m_snapToLines && isInvalidPercentage(m_linePosition))
+        return 100;
+
+    // 2. If the text track cue line position is numeric, return the value of
+    //    the text track cue line position and abort these steps. (Either the
+    //    text track cue snap-to-lines flag is set, so any value, not just
+    //    those in the range 0..100, is valid, or the value is in the range
+    //    0..100 and is thus valid regardless of the value of that flag.)
+    if (!lineIsAuto())
         return m_linePosition;
 
-    // If the text track cue snap-to-lines flag of the text track cue is not
-    // set, the text track cue computed line position is the value 100;
+    // 3. If the text track cue snap-to-lines flag of the text track cue is not
+    //    set, return the value 100 and abort these steps. (The text track cue
+    //    line position is the special value auto.)
     if (!m_snapToLines)
         return 100;
 
-    // Otherwise, it is the value returned by the following algorithm:
-
-    // If cue is not associated with a text track, return -1 and abort these
-    // steps.
+    // 4. Let cue be the text track cue.
+    // 5. If cue is not in a list of cues of a text track, or if that text
+    //    track is not in the list of text tracks of a media element, return -1
+    //    and abort these steps.
     if (!track())
         return -1;
 
-    // Let n be the number of text tracks whose text track mode is showing or
-    // showing by default and that are in the media element's list of text
-    // tracks before track.
+    // 6. Let track be the text track whose list of cues the cue is in.
+    // 7. Let n be the number of text tracks whose text track mode is showing
+    //    and that are in the media element's list of text tracks before track.
     int n = track()->trackIndexRelativeToRenderedTracks();
 
-    // Increment n by one.
+    // 8. Increment n by one. / 9. Negate n. / 10. Return n.
     n++;
-
-    // Negate n.
     n = -n;
-
     return n;
 }
 
@@ -788,7 +833,7 @@
     if (!m_snapToLines)
         UseCounter::count(document(), UseCounter::VTTCueRenderSnapToLinesFalse);
 
-    if (m_linePosition != undefinedPosition)
+    if (!lineIsAuto())
         UseCounter::count(document(), UseCounter::VTTCueRenderLineNotAuto);
 
     if (m_textPosition != 50)
@@ -829,6 +874,7 @@
 FloatPoint VTTCue::getPositionCoordinates() const
 {
     // This method is used for setting x and y when snap to lines is not set.
+    ASSERT(std::isfinite(m_computedLinePosition));
 
     if (m_writingDirection == Horizontal && m_displayDirection == CSSValueLtr)
         return FloatPoint(m_textPosition, m_computedLinePosition);
@@ -1038,7 +1084,7 @@
     if (m_regionId.isEmpty())
         return;
 
-    if (m_linePosition != undefinedPosition || m_cueSize != 100 || m_writingDirection != Horizontal)
+    if (!lineIsAuto() || m_cueSize != 100 || m_writingDirection != Horizontal)
         m_regionId = emptyString();
 }
 
diff --git a/Source/core/html/track/vtt/VTTCue.h b/Source/core/html/track/vtt/VTTCue.h
index 4bd2688..616783c 100644
--- a/Source/core/html/track/vtt/VTTCue.h
+++ b/Source/core/html/track/vtt/VTTCue.h
@@ -36,6 +36,7 @@
 namespace blink {
 
 class Document;
+class DoubleOrAutoKeyword;
 class ExecutionContext;
 class VTTCue;
 class VTTScanner;
@@ -76,8 +77,8 @@
     bool snapToLines() const { return m_snapToLines; }
     void setSnapToLines(bool);
 
-    double line() const { return m_linePosition; }
-    void setLine(double, ExceptionState&);
+    void line(DoubleOrAutoKeyword&) const;
+    void setLine(const DoubleOrAutoKeyword&, ExceptionState&);
 
     double position() const { return m_textPosition; }
     void setPosition(double, ExceptionState&);
@@ -156,6 +157,7 @@
     void copyVTTNodeToDOMTree(ContainerNode* vttNode, ContainerNode* root);
 
     FloatPoint getPositionCoordinates() const;
+    bool lineIsAuto() const;
 
     void calculateDisplayParameters();
 
diff --git a/Source/core/html/track/vtt/VTTCue.idl b/Source/core/html/track/vtt/VTTCue.idl
index 08ed799..5a3b0ad 100644
--- a/Source/core/html/track/vtt/VTTCue.idl
+++ b/Source/core/html/track/vtt/VTTCue.idl
@@ -27,6 +27,7 @@
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+enum AutoKeyword { "auto" };
 enum DirectionSetting { "" /* horizontal */, "rl", "lr" };
 enum AlignSetting { "start", "middle", "end", "left", "right" };
 
@@ -39,7 +40,7 @@
     [RuntimeEnabled=WebVTTRegions] attribute DOMString regionId;
     attribute DirectionSetting vertical;
     attribute boolean snapToLines;
-    [RaisesException=Setter] attribute double line;
+    [RaisesException=Setter] attribute (double or AutoKeyword) line;
     [RaisesException=Setter] attribute double position;
     [RaisesException=Setter] attribute double size;
     attribute AlignSetting align;