Move readyState from TextTrack to HTMLTrackElement
[WebKit-https.git] / Source / WebCore / html / HTMLTrackElement.cpp
1 /*
2  * Copyright (C) 2011 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27
28 #if ENABLE(VIDEO_TRACK)
29 #include "HTMLTrackElement.h"
30
31 #include "Event.h"
32 #include "HTMLMediaElement.h"
33 #include "HTMLNames.h"
34 #include "Logging.h"
35 #include "RuntimeEnabledFeatures.h"
36 #include "ScriptEventListener.h"
37
38 using namespace std;
39
40 namespace WebCore {
41
42 using namespace HTMLNames;
43
44 inline HTMLTrackElement::HTMLTrackElement(const QualifiedName& tagName, Document* document)
45     : HTMLElement(tagName, document)
46     , m_readyState(HTMLTrackElement::NONE)
47 {
48     LOG(Media, "HTMLTrackElement::HTMLTrackElement - %p", this);
49     ASSERT(hasTagName(trackTag));
50 }
51
52 HTMLTrackElement::~HTMLTrackElement()
53 {
54     if (m_track)
55         m_track->clearClient();
56 }
57
58 PassRefPtr<HTMLTrackElement> HTMLTrackElement::create(const QualifiedName& tagName, Document* document)
59 {
60     return adoptRef(new HTMLTrackElement(tagName, document));
61 }
62
63 void HTMLTrackElement::insertedIntoTree(bool deep)
64 {
65     HTMLElement::insertedIntoTree(deep);
66
67     if (HTMLMediaElement* parent = mediaElement())
68         parent->trackWasAdded(this);
69 }
70
71 void HTMLTrackElement::willRemove()
72 {
73     if (HTMLMediaElement* parent = mediaElement())
74         parent->trackWillBeRemoved(this);
75
76     HTMLElement::willRemove();
77 }
78
79 void HTMLTrackElement::parseMappedAttribute(Attribute* attribute)
80 {
81     const QualifiedName& attrName = attribute->name();
82
83     if (attrName == onloadAttr)
84         setAttributeEventListener(eventNames().loadEvent, createAttributeEventListener(this, attribute));
85     else if (attrName == onerrorAttr)
86         setAttributeEventListener(eventNames().errorEvent, createAttributeEventListener(this, attribute));
87     else
88         HTMLElement::parseMappedAttribute(attribute);
89 }
90
91 void HTMLTrackElement::attributeChanged(Attribute* attr, bool preserveDecls)
92 {
93     HTMLElement::attributeChanged(attr, preserveDecls);
94
95     const QualifiedName& attrName = attr->name();
96     if (attrName == srcAttr) {
97         if (!getAttribute(srcAttr).isEmpty() && mediaElement())
98             scheduleLoad();
99
100     // 4.8.10.12.3 Sourcing out-of-band text tracks
101     // As the kind, label, and srclang attributes are set, changed, or removed, the text track must update accordingly...
102     } else if (attrName == kindAttr)
103         track()->setKind(attr->value());
104     else if (attrName == labelAttr)
105         track()->setLabel(attr->value());
106     else if (attrName == srclangAttr)
107         track()->setLanguage(attr->value());
108 }
109
110 KURL HTMLTrackElement::src() const
111 {
112     return document()->completeURL(getAttribute(srcAttr));
113 }
114
115 void HTMLTrackElement::setSrc(const String& url)
116 {
117     setAttribute(srcAttr, url);
118 }
119
120 String HTMLTrackElement::kind()
121 {
122     return track()->kind();
123 }
124
125 void HTMLTrackElement::setKind(const String& kind)
126 {
127     setAttribute(kindAttr, kind);
128 }
129
130 String HTMLTrackElement::srclang() const
131 {
132     return getAttribute(srclangAttr);
133 }
134
135 void HTMLTrackElement::setSrclang(const String& srclang)
136 {
137     setAttribute(srclangAttr, srclang);
138 }
139
140 String HTMLTrackElement::label() const
141 {
142     return getAttribute(labelAttr);
143 }
144
145 void HTMLTrackElement::setLabel(const String& label)
146 {
147     setAttribute(labelAttr, label);
148 }
149
150 bool HTMLTrackElement::isDefault() const
151 {
152     return fastHasAttribute(defaultAttr);
153 }
154
155 void HTMLTrackElement::setIsDefault(bool isDefault)
156 {
157     setBooleanAttribute(defaultAttr, isDefault);
158 }
159
160 LoadableTextTrack* HTMLTrackElement::ensureTrack()
161 {
162     if (!RuntimeEnabledFeatures::webkitVideoTrackEnabled())
163         return 0;
164
165     if (!m_track) {
166         // The kind attribute is an enumerated attribute, limited only to know values. It defaults to 'subtitles' if missing or invalid.
167         String kind = getAttribute(kindAttr);
168         if (!TextTrack::isValidKindKeyword(kind))
169             kind = TextTrack::subtitlesKeyword();
170         m_track = LoadableTextTrack::create(this, kind, label(), srclang(), isDefault());
171     }
172     return m_track.get();
173 }
174
175 TextTrack* HTMLTrackElement::track()
176 {
177     return ensureTrack();
178 }
179
180 bool HTMLTrackElement::isURLAttribute(Attribute* attribute) const
181 {
182     return attribute->name() == srcAttr || HTMLElement::isURLAttribute(attribute);
183 }
184
185 void HTMLTrackElement::scheduleLoad()
186 {
187     if (!mediaElement())
188         return;
189
190     if (!fastHasAttribute(srcAttr))
191         return;
192
193     ensureTrack()->scheduleLoad(getNonEmptyURLAttribute(srcAttr));
194 }
195
196 bool HTMLTrackElement::canLoadUrl(LoadableTextTrack*, const KURL& url)
197 {
198     HTMLMediaElement* parent = mediaElement();
199     if (!parent)
200         return false;
201
202     if (!parent->isSafeToLoadURL(url, HTMLMediaElement::Complain))
203         return false;
204     
205     return dispatchBeforeLoadEvent(url.string());
206 }
207
208 void HTMLTrackElement::didCompleteLoad(LoadableTextTrack*, bool loadingFailed)
209 {
210     loadingFailed ? setReadyState(HTMLTrackElement::ERROR) : setReadyState(HTMLTrackElement::LOADED);
211
212     ExceptionCode ec = 0;
213     dispatchEvent(Event::create(loadingFailed ? eventNames().errorEvent : eventNames().loadEvent, false, false), ec);
214 }
215
216 void HTMLTrackElement::setReadyState(ReadyState state)
217 {
218     m_readyState = state;
219     if (HTMLMediaElement* parent = mediaElement())
220         return parent->textTrackReadyStateChanged(m_track.get());
221 }
222     
223 void HTMLTrackElement::textTrackKindChanged(TextTrack* track)
224 {
225     if (HTMLMediaElement* parent = mediaElement())
226         return parent->textTrackKindChanged(track);
227 }
228
229 void HTMLTrackElement::textTrackModeChanged(TextTrack* track)
230 {
231     if (HTMLMediaElement* parent = mediaElement())
232         return parent->textTrackModeChanged(track);
233 }
234
235 void HTMLTrackElement::textTrackAddCues(TextTrack* track, const TextTrackCueList* cues)
236 {
237     if (HTMLMediaElement* parent = mediaElement())
238         return parent->textTrackAddCues(track, cues);
239 }
240     
241 void HTMLTrackElement::textTrackRemoveCues(TextTrack* track, const TextTrackCueList* cues)
242 {
243     if (HTMLMediaElement* parent = mediaElement())
244         return parent->textTrackAddCues(track, cues);
245 }
246     
247 void HTMLTrackElement::textTrackAddCue(TextTrack* track, PassRefPtr<TextTrackCue> cue)
248 {
249     if (HTMLMediaElement* parent = mediaElement())
250         return parent->textTrackAddCue(track, cue);
251 }
252     
253 void HTMLTrackElement::textTrackRemoveCue(TextTrack* track, PassRefPtr<TextTrackCue> cue)
254 {
255     if (HTMLMediaElement* parent = mediaElement())
256         return parent->textTrackRemoveCue(track, cue);
257 }
258
259 HTMLMediaElement* HTMLTrackElement::mediaElement() const
260 {
261     Element* parent = parentElement();
262     if (parent && parent->isMediaElement())
263         return static_cast<HTMLMediaElement*>(parentNode());
264
265     return 0;
266 }
267
268 #if ENABLE(MICRODATA)
269 String HTMLTrackElement::itemValueText() const
270 {
271     return getURLAttribute(srcAttr);
272 }
273
274 void HTMLTrackElement::setItemValueText(const String& value, ExceptionCode& ec)
275 {
276     setAttribute(srcAttr, value, ec);
277 }
278 #endif
279
280 }
281
282 #endif