Validate the BCP47-ness of the language string passed to TrackBase::setLanguage()
authorwilander@apple.com <wilander@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 4 Jan 2017 19:21:42 +0000 (19:21 +0000)
committerwilander@apple.com <wilander@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 4 Jan 2017 19:21:42 +0000 (19:21 +0000)
https://bugs.webkit.org/show_bug.cgi?id=123926

Reviewed by Jer Noble.

LayoutTests/imported/w3c:

* web-platform-tests/html/dom/reflection-embedded-expected.txt:
    Expected text change since we now have console warnings for
    invalid language tags.
* web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/srclang-expected.txt:
    Expected text change since we now have console warnings for
    invalid language tags.
* web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/language-expected.txt:
    Expected text change since we now have console warnings for
    invalid language tags.

Source/WebCore:

Test: media/media-source/only-bcp47-language-tags-accepted-as-valid.html

* html/HTMLMediaElement.cpp:
(WebCore::HTMLMediaElement::configureTextTrackGroup):
    Log message now includes the valid BCP 47 language too.
(WebCore::HTMLMediaElement::setSelectedTextTrack):
    Now sets preferred language to the valid BCP 47 language.
* html/track/TextTrack.cpp:
(WebCore::TextTrack::setLanguage):
    Removed fixme and aligned comments with new behavior.
* html/track/TrackBase.cpp:
(WebCore::TrackBase::TrackBase):
    Initializes m_validBCP47Language with language parameter.
(WebCore::isValidBCP47LanguageTag):
    New convenience function.
(WebCore::TrackBase::setLanguage):
    Sets m_validBCP47Language if the incoming tag is valid.
    Produces a console warning if the tag is invalid.
    The member m_language is set to the incoming tag regardless.
(WebCore::TrackBase::validBCP47Language):
    New getter for valid language tag. To be used internally.
* html/track/TrackBase.h:
    New AtomicString member m_validBCP47Language.
(WebCore::TrackBase::setLanguage): Deleted.
* html/track/VideoTrack.cpp:
(WebCore::VideoTrack::setLanguage):
    Removed fixme and aligned comments with new behavior.
* page/CaptionUserPreferences.cpp:
(WebCore::trackDisplayName):
    Now uses the getter for BCP 47 language.
(WebCore::CaptionUserPreferences::textTrackLanguageSelectionScore):
    Now uses the getter for BCP 47 language.
* page/CaptionUserPreferencesMediaAF.cpp:
(WebCore::buildDisplayStringForTrackBase):
    Now uses the getter for BCP 47 language.
(WebCore::CaptionUserPreferencesMediaAF::textTrackSelectionScore):
    Now uses the getter for BCP 47 language.
(WebCore::textTrackCompare):
    Now uses the getter for BCP 47 language.
(WebCore::CaptionUserPreferencesMediaAF::sortedTrackListForMenu):
    Now uses the getter for BCP 47 language.

LayoutTests:

* media/media-source/only-bcp47-language-tags-accepted-as-valid-expected.txt: Added.
* media/media-source/only-bcp47-language-tags-accepted-as-valid.html: Added.
* media/track/w3c/interfaces/HTMLTrackElement/srclang-expected.txt:
    Expected text change since we now have console warnings for
    invalid language tags.
* media/track/w3c/interfaces/TextTrack/language-expected.txt:
    Expected text change since we now have console warnings for
    invalid language tags.
* platform/ios-simulator-wk2/imported/w3c/web-platform-tests/html/dom/reflection-embedded-expected.txt:
    Expected text change since we now have console warnings for
    invalid language tags.
* platform/ios-simulator/imported/w3c/web-platform-tests/html/dom/reflection-embedded-expected.txt:
    Expected text change since we now have console warnings for
    invalid language tags.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@210280 268f45cc-cd09-0410-ab3c-d52691b4dbfc

19 files changed:
LayoutTests/ChangeLog
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/html/dom/reflection-embedded-expected.txt
LayoutTests/imported/w3c/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/srclang-expected.txt
LayoutTests/imported/w3c/web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/language-expected.txt
LayoutTests/media/media-source/only-bcp47-language-tags-accepted-as-valid-expected.txt [new file with mode: 0644]
LayoutTests/media/media-source/only-bcp47-language-tags-accepted-as-valid.html [new file with mode: 0644]
LayoutTests/media/track/w3c/interfaces/HTMLTrackElement/srclang-expected.txt
LayoutTests/media/track/w3c/interfaces/TextTrack/language-expected.txt
LayoutTests/platform/ios-simulator-wk2/imported/w3c/web-platform-tests/html/dom/reflection-embedded-expected.txt
LayoutTests/platform/ios-simulator/imported/w3c/web-platform-tests/html/dom/reflection-embedded-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/html/HTMLMediaElement.cpp
Source/WebCore/html/track/TextTrack.cpp
Source/WebCore/html/track/TrackBase.cpp
Source/WebCore/html/track/TrackBase.h
Source/WebCore/html/track/VideoTrack.cpp
Source/WebCore/page/CaptionUserPreferences.cpp
Source/WebCore/page/CaptionUserPreferencesMediaAF.cpp

index f863df1..30111b8 100644 (file)
@@ -1,3 +1,25 @@
+2017-01-04  John Wilander  <wilander@apple.com>
+
+        Validate the BCP47-ness of the language string passed to TrackBase::setLanguage()
+        https://bugs.webkit.org/show_bug.cgi?id=123926
+
+        Reviewed by Jer Noble.
+
+        * media/media-source/only-bcp47-language-tags-accepted-as-valid-expected.txt: Added.
+        * media/media-source/only-bcp47-language-tags-accepted-as-valid.html: Added.
+        * media/track/w3c/interfaces/HTMLTrackElement/srclang-expected.txt:
+            Expected text change since we now have console warnings for
+            invalid language tags.
+        * media/track/w3c/interfaces/TextTrack/language-expected.txt:
+            Expected text change since we now have console warnings for
+            invalid language tags.
+        * platform/ios-simulator-wk2/imported/w3c/web-platform-tests/html/dom/reflection-embedded-expected.txt:
+            Expected text change since we now have console warnings for
+            invalid language tags.
+        * platform/ios-simulator/imported/w3c/web-platform-tests/html/dom/reflection-embedded-expected.txt:
+            Expected text change since we now have console warnings for
+            invalid language tags.
+
 2017-01-04  Joseph Pecoraro  <pecoraro@apple.com>
 
         Web Inspector: Cross Origin importScripts() scripts lack source URL, causes issues with Inspector showing Resource
index 42dacd6..07496bd 100644 (file)
@@ -1,3 +1,20 @@
+2017-01-04  John Wilander  <wilander@apple.com>
+
+        Validate the BCP47-ness of the language string passed to TrackBase::setLanguage()
+        https://bugs.webkit.org/show_bug.cgi?id=123926
+
+        Reviewed by Jer Noble.
+
+        * web-platform-tests/html/dom/reflection-embedded-expected.txt:
+            Expected text change since we now have console warnings for
+            invalid language tags.
+        * web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/HTMLElement/HTMLTrackElement/srclang-expected.txt:
+            Expected text change since we now have console warnings for
+            invalid language tags.
+        * web-platform-tests/html/semantics/embedded-content/media-elements/interfaces/TextTrack/language-expected.txt:
+            Expected text change since we now have console warnings for
+            invalid language tags.
+
 2017-01-03  Chris Dumez  <cdumez@apple.com>
 
         Make setting Event's cancelBubble to false a no-op
index 89e331b..9fd6f18 100644 (file)
@@ -6,6 +6,32 @@ Blocked access to external URL http://site.example/
 Blocked access to external URL http://site.example/path???@#l
 Blocked access to external URL http://site.example/
 Blocked access to external URL http://site.example/path???@#l
+CONSOLE MESSAGE: line 707: The language contains a null character and is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language 'undefined' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language '7' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language '1.5' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language 'true' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language 'false' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language '[object Object]' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language 'Infinity' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language '-Infinity' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language contains a null character and is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language 'null' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language 'test-toString' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language 'test-valueOf' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language contains a null character and is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language 'undefined' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language '7' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language '1.5' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language 'true' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language 'false' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language '[object Object]' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language 'Infinity' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language '-Infinity' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language contains a null character and is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language 'null' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language 'test-toString' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language 'test-valueOf' is not a valid BCP 47 language tag.
 Implementers looking to fix bugs might want to use the original version of this suite's test framework, which conveniently aggregates similar errors and only reports failures. This file is (part of) the authoritative conformance test suite, and is suitable for incorporation into automated test suites.
 
 
index 7b598ec..1c7a41b 100644 (file)
@@ -1,3 +1,9 @@
+CONSOLE MESSAGE: line 43: The language contains a null character and is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 64: The language ' foo 
+' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language ' foo 
+' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language contains a null character and is not a valid BCP 47 language tag.
 
 PASS HTMLTrackElement.srclang missing value 
 PASS HTMLTrackElement.srclang empty string content attribute 
index 133658c..214a719 100644 (file)
@@ -1,3 +1,5 @@
+CONSOLE MESSAGE: line 1380: The language contains a null character and is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 26: The language contains a null character and is not a valid BCP 47 language tag.
 
 PASS TextTrack.language 
 PASS TextTrack.language, \u0000 
diff --git a/LayoutTests/media/media-source/only-bcp47-language-tags-accepted-as-valid-expected.txt b/LayoutTests/media/media-source/only-bcp47-language-tags-accepted-as-valid-expected.txt
new file mode 100644 (file)
index 0000000..a11aa4a
--- /dev/null
@@ -0,0 +1,302 @@
+CONSOLE MESSAGE: line 176: The language 'a' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 106: The language 'a' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language 'a' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language '1' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 106: The language '1' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language '1' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language 'ab-abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 106: The language 'ab-abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language 'ab-abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language '1a' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 106: The language '1a' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language '1a' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language '-a' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 106: The language '-a' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language '-a' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language 'a-' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 106: The language 'a-' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language 'a-' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language 'a1' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 106: The language 'a1' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language 'a1' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language 'aa1' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 106: The language 'aa1' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language 'aa1' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language 'aaaa' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 106: The language 'aaaa' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language 'aaaa' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language 'aaa1' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 106: The language 'aaa1' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language 'aaa1' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language 'inv-alid-char space' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 106: The language 'inv-alid-char space' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language 'inv-alid-char space' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language 'inv-alid-char–longDash' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 106: The language 'inv-alid-char–longDash' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language 'inv-alid-char–longDash' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language 'inv-alid-char-PÃ¥lska' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 106: The language 'inv-alid-char-PÃ¥lska' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language 'inv-alid-char-PÃ¥lska' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language 'inv-alid-char-*' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 106: The language 'inv-alid-char-*' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language 'inv-alid-char-*' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language 'inv-alid-char-' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 106: The language 'inv-alid-char-' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 176: The language 'inv-alid-char-' is not a valid BCP 47 language tag.
+Test that only BCP47 language tags are accepted as valid but still reflected.
+
+
+RUN(video.src = URL.createObjectURL(source))
+EVENT(sourceopen)
+RUN(source.duration = loader.duration())
+RUN(sourceBuffer = source.addSourceBuffer(loader.type()))
+RUN(sourceBuffer.appendBuffer(loader.initSegment()))
+EVENT(update)
+Append a partial media segment.
+RUN(sourceBuffer.appendBuffer(loader.mediaSegment(0).slice(0, loader.mediaSegment(0).byteLength / 2)))
+EVENT(update)
+EXPECTED (videoTrack.language == 'en-GB-oed') OK
+EXPECTED (textTrack.track.language == 'en-GB-oed') OK
+EXPECTED (audioTrack.language == 'en-GB-oed') OK
+EXPECTED (videoTrack.language == 'i-ami') OK
+EXPECTED (textTrack.track.language == 'i-ami') OK
+EXPECTED (audioTrack.language == 'i-ami') OK
+EXPECTED (videoTrack.language == 'i-bnn') OK
+EXPECTED (textTrack.track.language == 'i-bnn') OK
+EXPECTED (audioTrack.language == 'i-bnn') OK
+EXPECTED (videoTrack.language == 'i-default') OK
+EXPECTED (textTrack.track.language == 'i-default') OK
+EXPECTED (audioTrack.language == 'i-default') OK
+EXPECTED (videoTrack.language == 'i-enochian') OK
+EXPECTED (textTrack.track.language == 'i-enochian') OK
+EXPECTED (audioTrack.language == 'i-enochian') OK
+EXPECTED (videoTrack.language == 'i-hak') OK
+EXPECTED (textTrack.track.language == 'i-hak') OK
+EXPECTED (audioTrack.language == 'i-hak') OK
+EXPECTED (videoTrack.language == 'i-klingon') OK
+EXPECTED (textTrack.track.language == 'i-klingon') OK
+EXPECTED (audioTrack.language == 'i-klingon') OK
+EXPECTED (videoTrack.language == 'i-lux') OK
+EXPECTED (textTrack.track.language == 'i-lux') OK
+EXPECTED (audioTrack.language == 'i-lux') OK
+EXPECTED (videoTrack.language == 'i-mingo') OK
+EXPECTED (textTrack.track.language == 'i-mingo') OK
+EXPECTED (audioTrack.language == 'i-mingo') OK
+EXPECTED (videoTrack.language == 'i-navajo') OK
+EXPECTED (textTrack.track.language == 'i-navajo') OK
+EXPECTED (audioTrack.language == 'i-navajo') OK
+EXPECTED (videoTrack.language == 'i-pwn') OK
+EXPECTED (textTrack.track.language == 'i-pwn') OK
+EXPECTED (audioTrack.language == 'i-pwn') OK
+EXPECTED (videoTrack.language == 'i-tao') OK
+EXPECTED (textTrack.track.language == 'i-tao') OK
+EXPECTED (audioTrack.language == 'i-tao') OK
+EXPECTED (videoTrack.language == 'i-tay') OK
+EXPECTED (textTrack.track.language == 'i-tay') OK
+EXPECTED (audioTrack.language == 'i-tay') OK
+EXPECTED (videoTrack.language == 'i-tsu') OK
+EXPECTED (textTrack.track.language == 'i-tsu') OK
+EXPECTED (audioTrack.language == 'i-tsu') OK
+EXPECTED (videoTrack.language == 'sgn-BE-FR') OK
+EXPECTED (textTrack.track.language == 'sgn-BE-FR') OK
+EXPECTED (audioTrack.language == 'sgn-BE-FR') OK
+EXPECTED (videoTrack.language == 'sgn-BE-NL') OK
+EXPECTED (textTrack.track.language == 'sgn-BE-NL') OK
+EXPECTED (audioTrack.language == 'sgn-BE-NL') OK
+EXPECTED (videoTrack.language == 'sgn-CH-DE') OK
+EXPECTED (textTrack.track.language == 'sgn-CH-DE') OK
+EXPECTED (audioTrack.language == 'sgn-CH-DE') OK
+EXPECTED (videoTrack.language == 'art-lojban') OK
+EXPECTED (textTrack.track.language == 'art-lojban') OK
+EXPECTED (audioTrack.language == 'art-lojban') OK
+EXPECTED (videoTrack.language == 'cel-gaulish') OK
+EXPECTED (textTrack.track.language == 'cel-gaulish') OK
+EXPECTED (audioTrack.language == 'cel-gaulish') OK
+EXPECTED (videoTrack.language == 'no-bok') OK
+EXPECTED (textTrack.track.language == 'no-bok') OK
+EXPECTED (audioTrack.language == 'no-bok') OK
+EXPECTED (videoTrack.language == 'no-nyn') OK
+EXPECTED (textTrack.track.language == 'no-nyn') OK
+EXPECTED (audioTrack.language == 'no-nyn') OK
+EXPECTED (videoTrack.language == 'zh-guoyu') OK
+EXPECTED (textTrack.track.language == 'zh-guoyu') OK
+EXPECTED (audioTrack.language == 'zh-guoyu') OK
+EXPECTED (videoTrack.language == 'zh-hakka') OK
+EXPECTED (textTrack.track.language == 'zh-hakka') OK
+EXPECTED (audioTrack.language == 'zh-hakka') OK
+EXPECTED (videoTrack.language == 'zh-min') OK
+EXPECTED (textTrack.track.language == 'zh-min') OK
+EXPECTED (audioTrack.language == 'zh-min') OK
+EXPECTED (videoTrack.language == 'zh-min-nan') OK
+EXPECTED (textTrack.track.language == 'zh-min-nan') OK
+EXPECTED (audioTrack.language == 'zh-min-nan') OK
+EXPECTED (videoTrack.language == 'zh-xiang') OK
+EXPECTED (textTrack.track.language == 'zh-xiang') OK
+EXPECTED (audioTrack.language == 'zh-xiang') OK
+EXPECTED (videoTrack.language == 'de') OK
+EXPECTED (textTrack.track.language == 'de') OK
+EXPECTED (audioTrack.language == 'de') OK
+EXPECTED (videoTrack.language == 'fr') OK
+EXPECTED (textTrack.track.language == 'fr') OK
+EXPECTED (audioTrack.language == 'fr') OK
+EXPECTED (videoTrack.language == 'ja') OK
+EXPECTED (textTrack.track.language == 'ja') OK
+EXPECTED (audioTrack.language == 'ja') OK
+EXPECTED (videoTrack.language == 'zh-Hant') OK
+EXPECTED (textTrack.track.language == 'zh-Hant') OK
+EXPECTED (audioTrack.language == 'zh-Hant') OK
+EXPECTED (videoTrack.language == 'zh-Han') OK
+EXPECTED (textTrack.track.language == 'zh-Han') OK
+EXPECTED (audioTrack.language == 'zh-Han') OK
+EXPECTED (videoTrack.language == 'sr-Cyrl') OK
+EXPECTED (textTrack.track.language == 'sr-Cyrl') OK
+EXPECTED (audioTrack.language == 'sr-Cyrl') OK
+EXPECTED (videoTrack.language == 'sr-Latn') OK
+EXPECTED (textTrack.track.language == 'sr-Latn') OK
+EXPECTED (audioTrack.language == 'sr-Latn') OK
+EXPECTED (videoTrack.language == 'zh-cmn-Hans-CN') OK
+EXPECTED (textTrack.track.language == 'zh-cmn-Hans-CN') OK
+EXPECTED (audioTrack.language == 'zh-cmn-Hans-CN') OK
+EXPECTED (videoTrack.language == 'cmn-Hans-CN') OK
+EXPECTED (textTrack.track.language == 'cmn-Hans-CN') OK
+EXPECTED (audioTrack.language == 'cmn-Hans-CN') OK
+EXPECTED (videoTrack.language == 'zh-yue-HK') OK
+EXPECTED (textTrack.track.language == 'zh-yue-HK') OK
+EXPECTED (audioTrack.language == 'zh-yue-HK') OK
+EXPECTED (videoTrack.language == 'yue-HK') OK
+EXPECTED (textTrack.track.language == 'yue-HK') OK
+EXPECTED (audioTrack.language == 'yue-HK') OK
+EXPECTED (videoTrack.language == 'zh-Hans-CN') OK
+EXPECTED (textTrack.track.language == 'zh-Hans-CN') OK
+EXPECTED (audioTrack.language == 'zh-Hans-CN') OK
+EXPECTED (videoTrack.language == 'sr-Latn-RS') OK
+EXPECTED (textTrack.track.language == 'sr-Latn-RS') OK
+EXPECTED (audioTrack.language == 'sr-Latn-RS') OK
+EXPECTED (videoTrack.language == 'sl-rozaj') OK
+EXPECTED (textTrack.track.language == 'sl-rozaj') OK
+EXPECTED (audioTrack.language == 'sl-rozaj') OK
+EXPECTED (videoTrack.language == 'sl-rozaj-biske') OK
+EXPECTED (textTrack.track.language == 'sl-rozaj-biske') OK
+EXPECTED (audioTrack.language == 'sl-rozaj-biske') OK
+EXPECTED (videoTrack.language == 'sl-nedis') OK
+EXPECTED (textTrack.track.language == 'sl-nedis') OK
+EXPECTED (audioTrack.language == 'sl-nedis') OK
+EXPECTED (videoTrack.language == 'de-CH-1901') OK
+EXPECTED (textTrack.track.language == 'de-CH-1901') OK
+EXPECTED (audioTrack.language == 'de-CH-1901') OK
+EXPECTED (videoTrack.language == 'sl-IT-nedis') OK
+EXPECTED (textTrack.track.language == 'sl-IT-nedis') OK
+EXPECTED (audioTrack.language == 'sl-IT-nedis') OK
+EXPECTED (videoTrack.language == 'hy-Latn-IT-arevela') OK
+EXPECTED (textTrack.track.language == 'hy-Latn-IT-arevela') OK
+EXPECTED (audioTrack.language == 'hy-Latn-IT-arevela') OK
+EXPECTED (videoTrack.language == 'en-US') OK
+EXPECTED (textTrack.track.language == 'en-US') OK
+EXPECTED (audioTrack.language == 'en-US') OK
+EXPECTED (videoTrack.language == 'es-419') OK
+EXPECTED (textTrack.track.language == 'es-419') OK
+EXPECTED (audioTrack.language == 'es-419') OK
+EXPECTED (videoTrack.language == 'de-CH-x-phonebk') OK
+EXPECTED (textTrack.track.language == 'de-CH-x-phonebk') OK
+EXPECTED (audioTrack.language == 'de-CH-x-phonebk') OK
+EXPECTED (videoTrack.language == 'az-Arab-x-AZE-derbend') OK
+EXPECTED (textTrack.track.language == 'az-Arab-x-AZE-derbend') OK
+EXPECTED (audioTrack.language == 'az-Arab-x-AZE-derbend') OK
+EXPECTED (videoTrack.language == 'x-whatever') OK
+EXPECTED (textTrack.track.language == 'x-whatever') OK
+EXPECTED (audioTrack.language == 'x-whatever') OK
+EXPECTED (videoTrack.language == 'qaa-Qaaa-QM-x-southern') OK
+EXPECTED (textTrack.track.language == 'qaa-Qaaa-QM-x-southern') OK
+EXPECTED (audioTrack.language == 'qaa-Qaaa-QM-x-southern') OK
+EXPECTED (videoTrack.language == 'de-Qaaa') OK
+EXPECTED (textTrack.track.language == 'de-Qaaa') OK
+EXPECTED (audioTrack.language == 'de-Qaaa') OK
+EXPECTED (videoTrack.language == 'sr-Latn-QM') OK
+EXPECTED (textTrack.track.language == 'sr-Latn-QM') OK
+EXPECTED (audioTrack.language == 'sr-Latn-QM') OK
+EXPECTED (videoTrack.language == 'sr-Qaaa-RS') OK
+EXPECTED (textTrack.track.language == 'sr-Qaaa-RS') OK
+EXPECTED (audioTrack.language == 'sr-Qaaa-RS') OK
+EXPECTED (videoTrack.language == 'zh-Hant-CN-x-private1-private2') OK
+EXPECTED (textTrack.track.language == 'zh-Hant-CN-x-private1-private2') OK
+EXPECTED (audioTrack.language == 'zh-Hant-CN-x-private1-private2') OK
+EXPECTED (videoTrack.language == 'de-DE') OK
+EXPECTED (textTrack.track.language == 'de-DE') OK
+EXPECTED (audioTrack.language == 'de-DE') OK
+EXPECTED (videoTrack.language == 'de-de') OK
+EXPECTED (textTrack.track.language == 'de-de') OK
+EXPECTED (audioTrack.language == 'de-de') OK
+EXPECTED (videoTrack.language == 'de-Latn-DE') OK
+EXPECTED (textTrack.track.language == 'de-Latn-DE') OK
+EXPECTED (audioTrack.language == 'de-Latn-DE') OK
+EXPECTED (videoTrack.language == 'de-Latf-DE') OK
+EXPECTED (textTrack.track.language == 'de-Latf-DE') OK
+EXPECTED (audioTrack.language == 'de-Latf-DE') OK
+EXPECTED (videoTrack.language == 'de-DE-x-goethe') OK
+EXPECTED (textTrack.track.language == 'de-DE-x-goethe') OK
+EXPECTED (audioTrack.language == 'de-DE-x-goethe') OK
+EXPECTED (videoTrack.language == 'de-Latn-DE-1996') OK
+EXPECTED (textTrack.track.language == 'de-Latn-DE-1996') OK
+EXPECTED (audioTrack.language == 'de-Latn-DE-1996') OK
+EXPECTED (videoTrack.language == 'de-Deva-DE') OK
+EXPECTED (textTrack.track.language == 'de-Deva-DE') OK
+EXPECTED (audioTrack.language == 'de-Deva-DE') OK
+EXPECTED (videoTrack.language == 'en-US-u-islamcal') OK
+EXPECTED (textTrack.track.language == 'en-US-u-islamcal') OK
+EXPECTED (audioTrack.language == 'en-US-u-islamcal') OK
+EXPECTED (videoTrack.language == 'zh-CN-a-myext-x-private') OK
+EXPECTED (textTrack.track.language == 'zh-CN-a-myext-x-private') OK
+EXPECTED (audioTrack.language == 'zh-CN-a-myext-x-private') OK
+EXPECTED (videoTrack.language == 'en-a-myext-b-another') OK
+EXPECTED (textTrack.track.language == 'en-a-myext-b-another') OK
+EXPECTED (audioTrack.language == 'en-a-myext-b-another') OK
+EXPECTED (videoTrack.language == 'zh-Latn-CN-variant1-a-extend1-x-wadegile-private1') OK
+EXPECTED (textTrack.track.language == 'zh-Latn-CN-variant1-a-extend1-x-wadegile-private1') OK
+EXPECTED (audioTrack.language == 'zh-Latn-CN-variant1-a-extend1-x-wadegile-private1') OK
+EXPECTED (videoTrack.language == 'a') OK
+EXPECTED (textTrack.track.language == 'a') OK
+EXPECTED (audioTrack.language == 'a') OK
+EXPECTED (videoTrack.language == '1') OK
+EXPECTED (textTrack.track.language == '1') OK
+EXPECTED (audioTrack.language == '1') OK
+EXPECTED (videoTrack.language == 'ab-abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij') OK
+EXPECTED (textTrack.track.language == 'ab-abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij') OK
+EXPECTED (audioTrack.language == 'ab-abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij') OK
+EXPECTED (videoTrack.language == '1a') OK
+EXPECTED (textTrack.track.language == '1a') OK
+EXPECTED (audioTrack.language == '1a') OK
+EXPECTED (videoTrack.language == '-a') OK
+EXPECTED (textTrack.track.language == '-a') OK
+EXPECTED (audioTrack.language == '-a') OK
+EXPECTED (videoTrack.language == 'a-') OK
+EXPECTED (textTrack.track.language == 'a-') OK
+EXPECTED (audioTrack.language == 'a-') OK
+EXPECTED (videoTrack.language == 'a1') OK
+EXPECTED (textTrack.track.language == 'a1') OK
+EXPECTED (audioTrack.language == 'a1') OK
+EXPECTED (videoTrack.language == 'aa1') OK
+EXPECTED (textTrack.track.language == 'aa1') OK
+EXPECTED (audioTrack.language == 'aa1') OK
+EXPECTED (videoTrack.language == 'aaaa') OK
+EXPECTED (textTrack.track.language == 'aaaa') OK
+EXPECTED (audioTrack.language == 'aaaa') OK
+EXPECTED (videoTrack.language == 'aaa1') OK
+EXPECTED (textTrack.track.language == 'aaa1') OK
+EXPECTED (audioTrack.language == 'aaa1') OK
+EXPECTED (videoTrack.language == 'inv-alid-char space') OK
+EXPECTED (textTrack.track.language == 'inv-alid-char space') OK
+EXPECTED (audioTrack.language == 'inv-alid-char space') OK
+EXPECTED (videoTrack.language == 'inv-alid-char–longDash') OK
+EXPECTED (textTrack.track.language == 'inv-alid-char–longDash') OK
+EXPECTED (audioTrack.language == 'inv-alid-char–longDash') OK
+EXPECTED (videoTrack.language == 'inv-alid-char-PÃ¥lska') OK
+EXPECTED (textTrack.track.language == 'inv-alid-char-PÃ¥lska') OK
+EXPECTED (audioTrack.language == 'inv-alid-char-PÃ¥lska') OK
+EXPECTED (videoTrack.language == 'inv-alid-char-*') OK
+EXPECTED (textTrack.track.language == 'inv-alid-char-*') OK
+EXPECTED (audioTrack.language == 'inv-alid-char-*') OK
+EXPECTED (videoTrack.language == 'inv-alid-char-') OK
+EXPECTED (textTrack.track.language == 'inv-alid-char-') OK
+EXPECTED (audioTrack.language == 'inv-alid-char-') OK
+END OF TEST
+
diff --git a/LayoutTests/media/media-source/only-bcp47-language-tags-accepted-as-valid.html b/LayoutTests/media/media-source/only-bcp47-language-tags-accepted-as-valid.html
new file mode 100644 (file)
index 0000000..f5da3b3
--- /dev/null
@@ -0,0 +1,131 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <title>Test that only BCP47 language tags are accepted as valid but still reflected</title>
+        <!--
+        <script src="media-controls.js"></script>
+        <script src="media-file.js"></script>
+        -->
+        <script src="media-source-loader.js"></script>
+        <script src="../video-test.js"></script>
+        <script>
+            var loader;
+            var source;
+            var sourceBuffer;
+
+            function mediaDataLoadingFailed() {
+                failTest('Media data loading failed');
+            }
+
+            function mediaDataLoaded() {
+                source = new MediaSource();
+                waitForEvent('sourceopen', sourceOpen, false, false, source);
+                waitForEventAndFail('error');
+                run('video.src = URL.createObjectURL(source)');
+            }
+
+            function sourceOpen() {
+                run('source.duration = loader.duration()');
+                run('sourceBuffer = source.addSourceBuffer(loader.type())');
+                waitForEventOn(sourceBuffer, 'update', sourceInitialized, false, true);
+                run('sourceBuffer.appendBuffer(loader.initSegment())');
+            }
+
+            function sourceInitialized() {
+                waitForEventOn(sourceBuffer, 'update', startBCP74Test, false, true);
+                consoleWrite('Append a partial media segment.')
+                run('sourceBuffer.appendBuffer(loader.mediaSegment(0).slice(0, loader.mediaSegment(0).byteLength / 2))');
+            }
+
+            if (window.testRunner)
+                testRunner.dumpAsText();
+
+            var validLanguageTags = [
+                // Grandfathered, irregular, https://tools.ietf.org/html/bcp47#section-2.1
+                "en-GB-oed", "i-ami", "i-bnn", "i-default",
+                "i-enochian", "i-hak", "i-klingon", "i-lux",
+                "i-mingo", "i-navajo", "i-pwn", "i-tao",
+                "i-tay", "i-tsu", "sgn-BE-FR", "sgn-BE-NL",
+                "sgn-CH-DE",
+                // Grandfathered, regular, https://tools.ietf.org/html/bcp47#section-2.1
+                "art-lojban", "cel-gaulish", "no-bok", "no-nyn",
+                "zh-guoyu", "zh-hakka", "zh-min", "zh-min-nan",
+                "zh-xiang",
+                // Other examples from the spec, mainly https://tools.ietf.org/html/bcp47#appendix-A
+                "de", "fr", "ja", "zh-Hant",
+                "zh-Han", "sr-Cyrl", "sr-Latn", "zh-cmn-Hans-CN",
+                "cmn-Hans-CN", "zh-yue-HK", "yue-HK", "zh-Hans-CN",
+                "sr-Latn-RS", "sl-rozaj", "sl-rozaj-biske", "sl-nedis",
+                "de-CH-1901", "sl-IT-nedis", "hy-Latn-IT-arevela", "en-US",
+                "es-419", "de-CH-x-phonebk", "az-Arab-x-AZE-derbend", "x-whatever",
+                "qaa-Qaaa-QM-x-southern", "de-Qaaa", "sr-Latn-QM", "sr-Qaaa-RS",
+                "zh-Hant-CN-x-private1-private2", "de-DE", "de-de", "de-Latn-DE",
+                "de-Latf-DE", "de-DE-x-goethe", "de-Latn-DE-1996", "de-Deva-DE",
+                "en-US-u-islamcal", "zh-CN-a-myext-x-private", "en-a-myext-b-another",
+                "zh-Latn-CN-variant1-a-extend1-x-wadegile-private1"
+            ];
+
+            var invalidLanguageTags = [
+                // Invalid length, less than 2 or over 100
+                "a", "1", "ab-abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij",
+                // Invalid first characters
+                "1a", "-a",
+                // Invalid second characters
+                "a-", "a1",
+                // Invalid third characters
+                "aa1",
+                // Invalid fourth characters
+                "aaaa", "aaa1",
+                // Invalid characters beyond the fourth
+                "inv-alid-char space", "inv-alid-char–longDash", "inv-alid-char-Pålska",
+                "inv-alid-char-*", "inv-alid-char-"
+            ];
+
+            var videoTrack;
+            var audioTrack;
+            var textTrack;
+            function startBCP74Test () {
+                videoTrack = video.videoTracks[0];
+                audioTrack = video.audioTracks[0];
+                // Access text track language through the element's srclang attribute
+                // since the DOM property is read-only.
+                textTrack = document.getElementById("textTrack");
+                for (var i = 0; i < validLanguageTags.length; i++) {
+                    videoTrack.language = validLanguageTags[i];
+                    testExpected("videoTrack.language", validLanguageTags[i]);
+                    textTrack.setAttribute("srclang", validLanguageTags[i]);
+                    testExpected("textTrack.track.language", validLanguageTags[i]);
+                    audioTrack.language = validLanguageTags[i];
+                    testExpected("audioTrack.language", validLanguageTags[i]);
+                }
+                var notOverwritten = "not-overwritten";
+                for (var i = 0; i < invalidLanguageTags.length; i++) {
+                    // These are accepted in the web page layer but will produce console warnings
+                    videoTrack.language = invalidLanguageTags[i];
+                    testExpected("videoTrack.language", invalidLanguageTags[i]);
+                    textTrack.setAttribute("srclang", invalidLanguageTags[i]);
+                    testExpected("textTrack.track.language", invalidLanguageTags[i]);
+                    audioTrack.language = invalidLanguageTags[i];
+                    testExpected("audioTrack.language", invalidLanguageTags[i]);
+                }
+                endTest();
+            }
+
+            function runTest()
+            {
+                findMediaElement();
+
+                loader = new MediaSourceLoader('content/test-fragmented-manifest.json');
+                loader.onload = mediaDataLoaded;
+                loader.onerror = mediaDataLoadingFailed;
+            }
+        </script>
+    </head>
+
+    <body onload="runTest()">
+        <p>Test that only BCP47 language tags are accepted as valid but still reflected.</p>
+        <video controls>
+            <track id="textTrack" kind="captions" src="../track/captions-webvtt/captions-fast.vtt" />
+        </video>
+    </body>
+</html>
index 7b598ec..1c7a41b 100644 (file)
@@ -1,3 +1,9 @@
+CONSOLE MESSAGE: line 43: The language contains a null character and is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 64: The language ' foo 
+' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language ' foo 
+' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language contains a null character and is not a valid BCP 47 language tag.
 
 PASS HTMLTrackElement.srclang missing value 
 PASS HTMLTrackElement.srclang empty string content attribute 
index 133658c..214a719 100644 (file)
@@ -1,3 +1,5 @@
+CONSOLE MESSAGE: line 1380: The language contains a null character and is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 26: The language contains a null character and is not a valid BCP 47 language tag.
 
 PASS TextTrack.language 
 PASS TextTrack.language, \u0000 
index 89e331b..9fd6f18 100644 (file)
@@ -6,6 +6,32 @@ Blocked access to external URL http://site.example/
 Blocked access to external URL http://site.example/path???@#l
 Blocked access to external URL http://site.example/
 Blocked access to external URL http://site.example/path???@#l
+CONSOLE MESSAGE: line 707: The language contains a null character and is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language 'undefined' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language '7' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language '1.5' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language 'true' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language 'false' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language '[object Object]' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language 'Infinity' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language '-Infinity' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language contains a null character and is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language 'null' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language 'test-toString' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language 'test-valueOf' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language contains a null character and is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language 'undefined' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language '7' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language '1.5' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language 'true' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language 'false' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language '[object Object]' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language 'Infinity' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language '-Infinity' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language contains a null character and is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language 'null' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language 'test-toString' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language 'test-valueOf' is not a valid BCP 47 language tag.
 Implementers looking to fix bugs might want to use the original version of this suite's test framework, which conveniently aggregates similar errors and only reports failures. This file is (part of) the authoritative conformance test suite, and is suitable for incorporation into automated test suites.
 
 
index d148c0a..d969665 100644 (file)
@@ -6,6 +6,32 @@ Blocked access to external URL http://site.example/
 Blocked access to external URL http://site.example/path???@#l
 Blocked access to external URL http://site.example/
 Blocked access to external URL http://site.example/path???@#l
+CONSOLE MESSAGE: line 707: The language contains a null character and is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language 'undefined' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language '7' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language '1.5' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language 'true' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language 'false' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language '[object Object]' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language 'Infinity' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language '-Infinity' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language contains a null character and is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language 'null' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language 'test-toString' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 707: The language 'test-valueOf' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language contains a null character and is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language 'undefined' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language '7' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language '1.5' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language 'true' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language 'false' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language '[object Object]' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language 'Infinity' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language '-Infinity' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language contains a null character and is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language 'null' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language 'test-toString' is not a valid BCP 47 language tag.
+CONSOLE MESSAGE: line 1380: The language 'test-valueOf' is not a valid BCP 47 language tag.
 Implementers looking to fix bugs might want to use the original version of this suite's test framework, which conveniently aggregates similar errors and only reports failures. This file is (part of) the authoritative conformance test suite, and is suitable for incorporation into automated test suites.
 
 
index 869733c..363faad 100644 (file)
@@ -1,3 +1,52 @@
+2017-01-04  John Wilander  <wilander@apple.com>
+
+        Validate the BCP47-ness of the language string passed to TrackBase::setLanguage()
+        https://bugs.webkit.org/show_bug.cgi?id=123926
+
+        Reviewed by Jer Noble.
+
+        Test: media/media-source/only-bcp47-language-tags-accepted-as-valid.html
+
+        * html/HTMLMediaElement.cpp:
+        (WebCore::HTMLMediaElement::configureTextTrackGroup):
+            Log message now includes the valid BCP 47 language too.
+        (WebCore::HTMLMediaElement::setSelectedTextTrack):
+            Now sets preferred language to the valid BCP 47 language.
+        * html/track/TextTrack.cpp:
+        (WebCore::TextTrack::setLanguage):
+            Removed fixme and aligned comments with new behavior.
+        * html/track/TrackBase.cpp:
+        (WebCore::TrackBase::TrackBase):
+            Initializes m_validBCP47Language with language parameter.
+        (WebCore::isValidBCP47LanguageTag):
+            New convenience function.
+        (WebCore::TrackBase::setLanguage):
+            Sets m_validBCP47Language if the incoming tag is valid.
+            Produces a console warning if the tag is invalid.
+            The member m_language is set to the incoming tag regardless.
+        (WebCore::TrackBase::validBCP47Language):
+            New getter for valid language tag. To be used internally.
+        * html/track/TrackBase.h:
+            New AtomicString member m_validBCP47Language.
+        (WebCore::TrackBase::setLanguage): Deleted.
+        * html/track/VideoTrack.cpp:
+        (WebCore::VideoTrack::setLanguage):
+            Removed fixme and aligned comments with new behavior.
+        * page/CaptionUserPreferences.cpp:
+        (WebCore::trackDisplayName):
+            Now uses the getter for BCP 47 language.
+        (WebCore::CaptionUserPreferences::textTrackLanguageSelectionScore):
+            Now uses the getter for BCP 47 language.
+        * page/CaptionUserPreferencesMediaAF.cpp:
+        (WebCore::buildDisplayStringForTrackBase):
+            Now uses the getter for BCP 47 language.
+        (WebCore::CaptionUserPreferencesMediaAF::textTrackSelectionScore):
+            Now uses the getter for BCP 47 language.
+        (WebCore::textTrackCompare):
+            Now uses the getter for BCP 47 language.
+        (WebCore::CaptionUserPreferencesMediaAF::sortedTrackListForMenu):
+            Now uses the getter for BCP 47 language.
+
 2017-01-04  Joseph Pecoraro  <pecoraro@apple.com>
 
         Web Inspector: Cross Origin importScripts() scripts lack source URL, causes issues with Inspector showing Resource
index 084efc7..cd4b5a2 100644 (file)
@@ -3774,7 +3774,7 @@ void HTMLMediaElement::configureTextTrackGroup(const TrackGroup& group)
             currentlyEnabledTracks.append(textTrack);
 
         int trackScore = captionPreferences ? captionPreferences->textTrackSelectionScore(textTrack.get(), this) : 0;
-        LOG(Media, "HTMLMediaElement::configureTextTrackGroup(%p) -  '%s' track with language '%s' has score %i", this, textTrack->kindKeyword().string().utf8().data(), textTrack->language().string().utf8().data(), trackScore);
+        LOG(Media, "HTMLMediaElement::configureTextTrackGroup(%p) -  '%s' track with language '%s' and BCP 47 language '%s' has score %d", this, textTrack->kindKeyword().string().utf8().data(), textTrack->language().string().utf8().data(), textTrack->validBCP47Language().string().utf8().data(), trackScore);
 
         if (trackScore) {
 
@@ -4005,8 +4005,8 @@ void HTMLMediaElement::setSelectedTextTrack(TextTrack* trackToSelect)
         displayMode = CaptionUserPreferences::Automatic;
     else {
         displayMode = CaptionUserPreferences::AlwaysOn;
-        if (trackToSelect->language().length())
-            captionPreferences.setPreferredLanguage(trackToSelect->language());
+        if (trackToSelect->validBCP47Language().length())
+            captionPreferences.setPreferredLanguage(trackToSelect->validBCP47Language());
     }
 
     captionPreferences.setCaptionDisplayMode(displayMode);
index 96bcd7e..30447c3 100644 (file)
@@ -556,7 +556,8 @@ void TextTrack::setLanguage(const AtomicString& language)
     // 11.1 language, on setting:
     // 1. If the value being assigned to this attribute is not an empty string or a BCP 47 language
     // tag[BCP47], then abort these steps.
-    // FIXME(123926): Validate the BCP47-ness of langague.
+    // BCP 47 validation is done in TrackBase::setLanguage() which is
+    // shared between all tracks that support setting language.
 
     // 2. Update this attribute to the new value.
     TrackBase::setLanguage(language);
index 7dd8ddb..2fd0bdb 100644 (file)
@@ -26,6 +26,9 @@
 #include "config.h"
 #include "TrackBase.h"
 
+#include "Language.h"
+#include <wtf/text/StringBuilder.h>
+
 #if ENABLE(VIDEO_TRACK)
 
 #include "HTMLMediaElement.h"
@@ -39,6 +42,7 @@ TrackBase::TrackBase(Type type, const AtomicString& id, const AtomicString& labe
     , m_id(id)
     , m_label(label)
     , m_language(language)
+    , m_validBCP47Language(language)
 {
     ASSERT(type != BaseTrack);
     m_type = type;
@@ -53,6 +57,83 @@ Element* TrackBase::element()
     return m_mediaElement;
 }
 
+// See: https://tools.ietf.org/html/bcp47#section-2.1
+static bool isValidBCP47LanguageTag(const String& languageTag)
+{
+    auto const length = languageTag.length();
+
+    // Max length picked as double the longest example tag in spec which is 49 characters:
+    // https://tools.ietf.org/html/bcp47#section-4.4.2
+    if (length < 2 || length > 100)
+        return false;
+
+    UChar firstChar = languageTag[0];
+
+    if (!isASCIIAlpha(firstChar))
+        return false;
+
+    UChar secondChar = languageTag[1];
+
+    if (length == 2)
+        return isASCIIAlpha(secondChar);
+
+    bool grandFatheredIrregularOrPrivateUse = (firstChar == 'i' || firstChar == 'x') && secondChar == '-';
+    unsigned nextCharIndexToCheck;
+
+    if (!grandFatheredIrregularOrPrivateUse) {
+        if (!isASCIIAlpha(secondChar))
+            return false;
+
+        if (length == 3)
+            return isASCIIAlpha(languageTag[2]);
+
+        if (isASCIIAlpha(languageTag[2])) {
+            if (languageTag[3] == '-')
+                nextCharIndexToCheck = 4;
+            else
+                return false;
+        } else if (languageTag[2] == '-')
+            nextCharIndexToCheck = 3;
+        else
+            return false;
+    } else
+        nextCharIndexToCheck = 2;
+
+    for (; nextCharIndexToCheck < length; ++nextCharIndexToCheck) {
+        UChar c = languageTag[nextCharIndexToCheck];
+        if (isASCIIAlphanumeric(c) || c == '-')
+            continue;
+        return false;
+    }
+    return true;
+}
+    
+void TrackBase::setLanguage(const AtomicString& language)
+{
+    if (!language.isEmpty() && !isValidBCP47LanguageTag(language)) {
+        String message;
+        if (language.contains((UChar)'\0'))
+            message = WTF::ASCIILiteral("The language contains a null character and is not a valid BCP 47 language tag.");
+        else {
+            StringBuilder stringBuilder;
+            stringBuilder.appendLiteral("The language '");
+            stringBuilder.append(language);
+            stringBuilder.appendLiteral("' is not a valid BCP 47 language tag.");
+            message = stringBuilder.toString();
+        }
+        if (auto element = this->element())
+            element->document().addConsoleMessage(MessageSource::Rendering, MessageLevel::Warning, message);
+    } else
+        m_validBCP47Language = language;
+    
+    m_language = language;
+}
+
+AtomicString TrackBase::validBCP47Language() const
+{
+    return m_validBCP47Language;
+}
+
 MediaTrackBase::MediaTrackBase(Type type, const AtomicString& id, const AtomicString& label, const AtomicString& language)
     : TrackBase(type, id, label, language)
 {
index d6c5e48..182500e 100644 (file)
@@ -54,8 +54,9 @@ public:
     AtomicString label() const { return m_label; }
     void setLabel(const AtomicString& label) { m_label = label; }
 
+    AtomicString validBCP47Language() const;
     AtomicString language() const { return m_language; }
-    virtual void setLanguage(const AtomicString& language) { m_language = language; }
+    virtual void setLanguage(const AtomicString&);
 
     virtual void clearClient() = 0;
 
@@ -83,6 +84,7 @@ private:
     AtomicString m_id;
     AtomicString m_label;
     AtomicString m_language;
+    AtomicString m_validBCP47Language;
 };
 
 class MediaTrackBase : public TrackBase {
index f80bc10..827009e 100644 (file)
@@ -205,7 +205,8 @@ void VideoTrack::setLanguage(const AtomicString& language)
     // 10.1 language, on setting:
     // 1. If the value being assigned to this attribute is not an empty string or a BCP 47 language
     // tag[BCP47], then abort these steps.
-    // FIXME(123926): Validate the BCP47-ness of langague.
+    // BCP 47 validation is done in TrackBase::setLanguage() which is
+    // shared between all tracks that support setting language.
 
     // 2. Update this attribute to the new value.
     MediaTrackBase::setLanguage(language);
index cfea10c..d2c391a 100644 (file)
@@ -203,11 +203,11 @@ static String trackDisplayName(TextTrack* track)
     if (track == TextTrack::captionMenuAutomaticItem())
         return textTrackAutomaticMenuItemText();
 
-    if (track->label().isEmpty() && track->language().isEmpty())
+    if (track->label().isEmpty() && track->validBCP47Language().isEmpty())
         return textTrackNoLabelText();
     if (!track->label().isEmpty())
         return track->label();
-    return track->language();
+    return track->validBCP47Language();
 }
 
 String CaptionUserPreferences::displayNameForTrack(TextTrack* track) const
@@ -240,11 +240,11 @@ Vector<RefPtr<TextTrack>> CaptionUserPreferences::sortedTrackListForMenu(TextTra
 
 static String trackDisplayName(AudioTrack* track)
 {
-    if (track->label().isEmpty() && track->language().isEmpty())
+    if (track->label().isEmpty() && track->validBCP47Language().isEmpty())
         return audioTrackNoLabelText();
     if (!track->label().isEmpty())
         return track->label();
-    return track->language();
+    return track->validBCP47Language();
 }
 
 String CaptionUserPreferences::displayNameForTrack(AudioTrack* track) const
@@ -283,11 +283,11 @@ int CaptionUserPreferences::textTrackSelectionScore(TextTrack* track, HTMLMediaE
 
 int CaptionUserPreferences::textTrackLanguageSelectionScore(TextTrack* track, const Vector<String>& preferredLanguages) const
 {
-    if (track->language().isEmpty())
+    if (track->validBCP47Language().isEmpty())
         return 0;
 
     bool exactMatch;
-    size_t languageMatchIndex = indexOfBestMatchingLanguageInList(track->language(), preferredLanguages, exactMatch);
+    size_t languageMatchIndex = indexOfBestMatchingLanguageInList(track->validBCP47Language(), preferredLanguages, exactMatch);
     if (languageMatchIndex >= preferredLanguages.size())
         return 0;
 
index 98b22ba..b66b95c 100644 (file)
@@ -614,7 +614,7 @@ static String languageIdentifier(const String& languageCode)
 static void buildDisplayStringForTrackBase(StringBuilder& displayName, const TrackBase& track)
 {
     String label = track.label();
-    String trackLanguageIdentifier = track.language();
+    String trackLanguageIdentifier = track.validBCP47Language();
 
     RetainPtr<CFLocaleRef> currentLocale = adoptCF(CFLocaleCreate(kCFAllocatorDefault, defaultLanguage().createCFString().get()));
     RetainPtr<CFStringRef> localeIdentifier = adoptCF(CFLocaleCreateCanonicalLocaleIdentifierFromString(kCFAllocatorDefault, trackLanguageIdentifier.createCFString().get()));
@@ -737,7 +737,7 @@ int CaptionUserPreferencesMediaAF::textTrackSelectionScore(TextTrack* track, HTM
         if (!mediaElement || !mediaElement->player())
             return 0;
 
-        String textTrackLanguage = track->language();
+        String textTrackLanguage = track->validBCP47Language();
         if (textTrackLanguage.isEmpty())
             return 0;
 
@@ -804,7 +804,7 @@ int CaptionUserPreferencesMediaAF::textTrackSelectionScore(TextTrack* track, HTM
 static bool textTrackCompare(const RefPtr<TextTrack>& a, const RefPtr<TextTrack>& b)
 {
     String preferredLanguageDisplayName = displayNameForLanguageLocale(languageIdentifier(defaultLanguage()));
-    String aLanguageDisplayName = displayNameForLanguageLocale(languageIdentifier(a->language()));
+    String aLanguageDisplayName = displayNameForLanguageLocale(languageIdentifier(a->validBCP47Language()));
     String bLanguageDisplayName = displayNameForLanguageLocale(languageIdentifier(b->language()));
 
     // Tracks in the user's preferred language are always at the top of the menu.
@@ -844,7 +844,7 @@ Vector<RefPtr<AudioTrack>> CaptionUserPreferencesMediaAF::sortedTrackListForMenu
     
     for (unsigned i = 0, length = trackList->length(); i < length; ++i) {
         AudioTrack* track = trackList->item(i);
-        String language = displayNameForLanguageLocale(track->language());
+        String language = displayNameForLanguageLocale(track->validBCP47Language());
         tracksForMenu.append(track);
     }
     
@@ -867,7 +867,7 @@ Vector<RefPtr<TextTrack>> CaptionUserPreferencesMediaAF::sortedTrackListForMenu(
 
     for (unsigned i = 0, length = trackList->length(); i < length; ++i) {
         TextTrack* track = trackList->item(i);
-        String language = displayNameForLanguageLocale(track->language());
+        String language = displayNameForLanguageLocale(track->validBCP47Language());
 
         if (displayMode == Manual) {
             LOG(Media, "CaptionUserPreferencesMediaAF::sortedTrackListForMenu - adding '%s' track with language '%s' because selection mode is 'manual'", track->kindKeyword().string().utf8().data(), language.utf8().data());