1 | /* |
2 | * Copyright (C) 2011, 2013 Google Inc. All rights reserved. |
3 | * Copyright (C) 2013 Cable Television Labs, Inc. |
4 | * Copyright (C) 2014 Apple Inc. All rights reserved. |
5 | * |
6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions are |
8 | * met: |
9 | * |
10 | * * Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. |
12 | * * Redistributions in binary form must reproduce the above |
13 | * copyright notice, this list of conditions and the following disclaimer |
14 | * in the documentation and/or other materials provided with the |
15 | * distribution. |
16 | * * Neither the name of Google Inc. nor the names of its |
17 | * contributors may be used to endorse or promote products derived from |
18 | * this software without specific prior written permission. |
19 | * |
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
23 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
24 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
25 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
26 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
27 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
28 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
31 | */ |
32 | |
33 | #pragma once |
34 | |
35 | #if ENABLE(VIDEO_TRACK) |
36 | |
37 | #include "BufferedLineReader.h" |
38 | #include "DocumentFragment.h" |
39 | #include "HTMLNames.h" |
40 | #include "TextResourceDecoder.h" |
41 | #include "VTTRegion.h" |
42 | #include <memory> |
43 | #include <wtf/MediaTime.h> |
44 | #include <wtf/text/StringBuilder.h> |
45 | |
46 | namespace WebCore { |
47 | |
48 | using namespace HTMLNames; |
49 | |
50 | class Document; |
51 | class ISOWebVTTCue; |
52 | class VTTScanner; |
53 | |
54 | class WebVTTParserClient { |
55 | public: |
56 | virtual ~WebVTTParserClient() = default; |
57 | |
58 | virtual void newCuesParsed() = 0; |
59 | virtual void newRegionsParsed() = 0; |
60 | virtual void newStyleSheetsParsed() = 0; |
61 | virtual void fileFailedToParse() = 0; |
62 | }; |
63 | |
64 | class WebVTTCueData final : public RefCounted<WebVTTCueData> { |
65 | public: |
66 | |
67 | static Ref<WebVTTCueData> create() { return adoptRef(*new WebVTTCueData()); } |
68 | ~WebVTTCueData() = default; |
69 | |
70 | MediaTime startTime() const { return m_startTime; } |
71 | void setStartTime(const MediaTime& startTime) { m_startTime = startTime; } |
72 | |
73 | MediaTime endTime() const { return m_endTime; } |
74 | void setEndTime(const MediaTime& endTime) { m_endTime = endTime; } |
75 | |
76 | String id() const { return m_id; } |
77 | void setId(String id) { m_id = id; } |
78 | |
79 | String content() const { return m_content; } |
80 | void setContent(String content) { m_content = content; } |
81 | |
82 | String settings() const { return m_settings; } |
83 | void setSettings(String settings) { m_settings = settings; } |
84 | |
85 | MediaTime originalStartTime() const { return m_originalStartTime; } |
86 | void setOriginalStartTime(const MediaTime& time) { m_originalStartTime = time; } |
87 | |
88 | private: |
89 | WebVTTCueData() = default; |
90 | |
91 | MediaTime m_startTime; |
92 | MediaTime m_endTime; |
93 | MediaTime m_originalStartTime; |
94 | String m_id; |
95 | String m_content; |
96 | String m_settings; |
97 | }; |
98 | |
99 | class WebVTTParser final { |
100 | WTF_MAKE_FAST_ALLOCATED; |
101 | public: |
102 | enum ParseState { |
103 | Initial, |
104 | , |
105 | Id, |
106 | TimingsAndSettings, |
107 | CueText, |
108 | Region, |
109 | Style, |
110 | BadCue, |
111 | Finished |
112 | }; |
113 | |
114 | WebVTTParser(WebVTTParserClient*, ScriptExecutionContext*); |
115 | |
116 | static inline bool isRecognizedTag(const AtomicString& tagName) |
117 | { |
118 | return tagName == iTag |
119 | || tagName == bTag |
120 | || tagName == uTag |
121 | || tagName == rubyTag |
122 | || tagName == rtTag; |
123 | } |
124 | |
125 | static inline bool isASpace(UChar c) |
126 | { |
127 | // WebVTT space characters are U+0020 SPACE, U+0009 CHARACTER |
128 | // TABULATION (tab), U+000A LINE FEED (LF), U+000C FORM FEED (FF), and |
129 | // U+000D CARRIAGE RETURN (CR). |
130 | return c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\r'; |
131 | } |
132 | |
133 | static inline bool isValidSettingDelimiter(UChar c) |
134 | { |
135 | // ... a WebVTT cue consists of zero or more of the following components, in any order, separated from each other by one or more |
136 | // U+0020 SPACE characters or U+0009 CHARACTER TABULATION (tab) characters. |
137 | return c == ' ' || c == '\t'; |
138 | } |
139 | static bool collectTimeStamp(const String&, MediaTime&); |
140 | |
141 | // Useful functions for parsing percentage settings. |
142 | static bool parseFloatPercentageValue(VTTScanner& valueScanner, float&); |
143 | static bool parseFloatPercentageValuePair(VTTScanner& valueScanner, char, FloatPoint&); |
144 | |
145 | // Input data to the parser to parse. |
146 | void parseBytes(const char*, unsigned); |
147 | void (String&&); |
148 | void parseCueData(const ISOWebVTTCue&); |
149 | void flush(); |
150 | void fileFinished(); |
151 | |
152 | // Transfers ownership of last parsed cues to caller. |
153 | void getNewCues(Vector<RefPtr<WebVTTCueData>>&); |
154 | void getNewRegions(Vector<RefPtr<VTTRegion>>&); |
155 | |
156 | Vector<String> getStyleSheets(); |
157 | |
158 | // Create the DocumentFragment representation of the WebVTT cue text. |
159 | static Ref<DocumentFragment> createDocumentFragmentFromCueText(Document&, const String&); |
160 | |
161 | protected: |
162 | ScriptExecutionContext* m_scriptExecutionContext; |
163 | ParseState m_state; |
164 | |
165 | private: |
166 | void parse(); |
167 | void flushPendingCue(); |
168 | bool hasRequiredFileIdentifier(const String&); |
169 | ParseState collectCueId(const String&); |
170 | ParseState collectTimingsAndSettings(const String&); |
171 | ParseState collectCueText(const String&); |
172 | ParseState recoverCue(const String&); |
173 | ParseState ignoreBadCue(const String&); |
174 | ParseState collectRegionSettings(const String&); |
175 | ParseState collectWebVTTBlock(const String&); |
176 | ParseState checkAndRecoverCue(const String& line); |
177 | ParseState collectStyleSheet(const String&); |
178 | bool checkAndCreateRegion(const String& line); |
179 | bool checkAndStoreRegion(const String& line); |
180 | bool checkStyleSheet(const String& line); |
181 | bool checkAndStoreStyleSheet(const String& line); |
182 | |
183 | void createNewCue(); |
184 | void resetCueValues(); |
185 | |
186 | static bool collectTimeStamp(VTTScanner& input, MediaTime& timeStamp); |
187 | |
188 | BufferedLineReader m_lineReader; |
189 | RefPtr<TextResourceDecoder> m_decoder; |
190 | String m_currentId; |
191 | MediaTime m_currentStartTime; |
192 | MediaTime m_currentEndTime; |
193 | StringBuilder m_currentContent; |
194 | String m_previousLine; |
195 | String m_currentSettings; |
196 | RefPtr<VTTRegion> m_currentRegion; |
197 | String m_currentStyleSheet; |
198 | |
199 | WebVTTParserClient* m_client; |
200 | |
201 | Vector<RefPtr<WebVTTCueData>> m_cuelist; |
202 | Vector<RefPtr<VTTRegion>> m_regionList; |
203 | Vector<String> m_styleSheets; |
204 | }; |
205 | |
206 | } // namespace WebCore |
207 | |
208 | #endif // ENABLE(VIDEO_TRACK) |
209 | |