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
46namespace WebCore {
47
48using namespace HTMLNames;
49
50class Document;
51class ISOWebVTTCue;
52class VTTScanner;
53
54class WebVTTParserClient {
55public:
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
64class WebVTTCueData final : public RefCounted<WebVTTCueData> {
65public:
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
88private:
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
99class WebVTTParser final {
100 WTF_MAKE_FAST_ALLOCATED;
101public:
102 enum ParseState {
103 Initial,
104 Header,
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 parseFileHeader(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
161protected:
162 ScriptExecutionContext* m_scriptExecutionContext;
163 ParseState m_state;
164
165private:
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