OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2011 Google Inc. All rights reserved. |
3 * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved. | 3 * Copyright (C) 2011, 2012, 2013 Apple Inc. All rights reserved. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions are | 6 * modification, are permitted provided that the following conditions are |
7 * met: | 7 * met: |
8 * | 8 * |
9 * * Redistributions of source code must retain the above copyright | 9 * * Redistributions of source code must retain the above copyright |
10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 DEFINE_STATIC_LOCAL(const AtomicString, closed, ("hidden", AtomicString::Con
structFromLiteral)); | 88 DEFINE_STATIC_LOCAL(const AtomicString, closed, ("hidden", AtomicString::Con
structFromLiteral)); |
89 return closed; | 89 return closed; |
90 } | 90 } |
91 | 91 |
92 const AtomicString& TextTrack::showingKeyword() | 92 const AtomicString& TextTrack::showingKeyword() |
93 { | 93 { |
94 DEFINE_STATIC_LOCAL(const AtomicString, ended, ("showing", AtomicString::Con
structFromLiteral)); | 94 DEFINE_STATIC_LOCAL(const AtomicString, ended, ("showing", AtomicString::Con
structFromLiteral)); |
95 return ended; | 95 return ended; |
96 } | 96 } |
97 | 97 |
98 TextTrack::TextTrack(Document& document, TextTrackClient* client, const AtomicSt
ring& kind, const AtomicString& label, const AtomicString& language, const Atomi
cString& id, TextTrackType type) | 98 TextTrack::TextTrack(Document& document, const AtomicString& kind, const AtomicS
tring& label, const AtomicString& language, const AtomicString& id, TextTrackTyp
e type) |
99 : TrackBase(TrackBase::TextTrack, label, language, id) | 99 : TrackBase(TrackBase::TextTrack, label, language, id) |
100 , m_cues(nullptr) | 100 , m_cues(nullptr) |
101 , m_regions(nullptr) | 101 , m_regions(nullptr) |
102 , m_document(&document) | 102 , m_document(&document) |
103 , m_trackList(0) | 103 , m_trackList(0) |
104 , m_mode(disabledKeyword()) | 104 , m_mode(disabledKeyword()) |
105 , m_client(client) | |
106 , m_trackType(type) | 105 , m_trackType(type) |
107 , m_readinessState(NotLoaded) | 106 , m_readinessState(NotLoaded) |
108 , m_trackIndex(invalidTrackIndex) | 107 , m_trackIndex(invalidTrackIndex) |
109 , m_renderedTrackIndex(invalidTrackIndex) | 108 , m_renderedTrackIndex(invalidTrackIndex) |
110 , m_hasBeenConfigured(false) | 109 , m_hasBeenConfigured(false) |
111 { | 110 { |
112 ScriptWrappable::init(this); | 111 ScriptWrappable::init(this); |
113 setKind(kind); | 112 setKind(kind); |
114 } | 113 } |
115 | 114 |
116 TextTrack::~TextTrack() | 115 TextTrack::~TextTrack() |
117 { | 116 { |
| 117 ASSERT(!m_trackList); |
| 118 |
118 if (m_cues) { | 119 if (m_cues) { |
119 if (m_client) | |
120 m_client->textTrackRemoveCues(this, m_cues.get()); | |
121 | |
122 for (size_t i = 0; i < m_cues->length(); ++i) | 120 for (size_t i = 0; i < m_cues->length(); ++i) |
123 m_cues->item(i)->setTrack(0); | 121 m_cues->item(i)->setTrack(0); |
124 } | 122 } |
125 | 123 |
126 if (m_regions) { | 124 if (m_regions) { |
127 for (size_t i = 0; i < m_regions->length(); ++i) | 125 for (size_t i = 0; i < m_regions->length(); ++i) |
128 m_regions->item(i)->setTrack(0); | 126 m_regions->item(i)->setTrack(0); |
129 } | 127 } |
130 clearClient(); | |
131 } | 128 } |
132 | 129 |
133 bool TextTrack::isValidKindKeyword(const AtomicString& value) | 130 bool TextTrack::isValidKindKeyword(const AtomicString& value) |
134 { | 131 { |
135 if (value == subtitlesKeyword()) | 132 if (value == subtitlesKeyword()) |
136 return true; | 133 return true; |
137 if (value == captionsKeyword()) | 134 if (value == captionsKeyword()) |
138 return true; | 135 return true; |
139 if (value == descriptionsKeyword()) | 136 if (value == descriptionsKeyword()) |
140 return true; | 137 return true; |
141 if (value == chaptersKeyword()) | 138 if (value == chaptersKeyword()) |
142 return true; | 139 return true; |
143 if (value == metadataKeyword()) | 140 if (value == metadataKeyword()) |
144 return true; | 141 return true; |
145 | 142 |
146 return false; | 143 return false; |
147 } | 144 } |
148 | 145 |
149 void TextTrack::setTrackList(TextTrackList* trackList) | 146 void TextTrack::setTrackList(TextTrackList* trackList) |
150 { | 147 { |
151 // NOTE: We are using m_trackList->owner() instead of m_client here because | 148 if (!trackList && mediaElement() && m_cues) |
152 // when a HTMLTrackElement is reparented, HTMLTrackElement::textTrackRemoveC
ues() | 149 mediaElement()->textTrackRemoveCues(this, m_cues.get()); |
153 // will forward the call to the new parent instead of the element the track
is being | 150 |
154 // removed from. | |
155 if (!trackList && m_trackList && m_trackList->owner() && m_cues) | |
156 m_trackList->owner()->textTrackRemoveCues(this, m_cues.get()); | |
157 m_trackList = trackList; | 151 m_trackList = trackList; |
| 152 invalidateTrackIndex(); |
158 } | 153 } |
159 | 154 |
160 void TextTrack::setKind(const AtomicString& newKind) | 155 void TextTrack::setKind(const AtomicString& newKind) |
161 { | 156 { |
162 AtomicString oldKind = kind(); | 157 AtomicString oldKind = kind(); |
163 TrackBase::setKind(newKind); | 158 TrackBase::setKind(newKind); |
164 | 159 |
165 if (m_client && oldKind != kind()) | 160 if (mediaElement() && oldKind != kind()) |
166 m_client->textTrackKindChanged(this); | 161 mediaElement()->textTrackKindChanged(this); |
167 } | 162 } |
168 | 163 |
169 void TextTrack::setMode(const AtomicString& mode) | 164 void TextTrack::setMode(const AtomicString& mode) |
170 { | 165 { |
171 ASSERT(mode == disabledKeyword() || mode == hiddenKeyword() || mode == showi
ngKeyword()); | 166 ASSERT(mode == disabledKeyword() || mode == hiddenKeyword() || mode == showi
ngKeyword()); |
172 | 167 |
173 // On setting, if the new value isn't equal to what the attribute would curr
ently | 168 // On setting, if the new value isn't equal to what the attribute would curr
ently |
174 // return, the new value must be processed as follows ... | 169 // return, the new value must be processed as follows ... |
175 if (m_mode == mode) | 170 if (m_mode == mode) |
176 return; | 171 return; |
177 | 172 |
178 // If mode changes to disabled, remove this track's cues from the client | 173 // If mode changes to disabled, remove this track's cues from the client |
179 // because they will no longer be accessible from the cues() function. | 174 // because they will no longer be accessible from the cues() function. |
180 if (mode == disabledKeyword() && m_client && m_cues) | 175 if (mode == disabledKeyword() && mediaElement() && m_cues) |
181 m_client->textTrackRemoveCues(this, m_cues.get()); | 176 mediaElement()->textTrackRemoveCues(this, m_cues.get()); |
182 | 177 |
183 if (mode != showingKeyword() && m_cues) | 178 if (mode != showingKeyword() && m_cues) |
184 for (size_t i = 0; i < m_cues->length(); ++i) | 179 for (size_t i = 0; i < m_cues->length(); ++i) |
185 m_cues->item(i)->removeDisplayTree(); | 180 m_cues->item(i)->removeDisplayTree(); |
186 | 181 |
187 m_mode = mode; | 182 m_mode = mode; |
188 | 183 |
189 if (m_client) | 184 if (mediaElement()) |
190 m_client->textTrackModeChanged(this); | 185 mediaElement()->textTrackModeChanged(this); |
191 } | 186 } |
192 | 187 |
193 TextTrackCueList* TextTrack::cues() | 188 TextTrackCueList* TextTrack::cues() |
194 { | 189 { |
195 // 4.8.10.12.5 If the text track mode ... is not the text track disabled mod
e, | 190 // 4.8.10.12.5 If the text track mode ... is not the text track disabled mod
e, |
196 // then the cues attribute must return a live TextTrackCueList object ... | 191 // then the cues attribute must return a live TextTrackCueList object ... |
197 // Otherwise, it must return null. When an object is returned, the | 192 // Otherwise, it must return null. When an object is returned, the |
198 // same object must be returned each time. | 193 // same object must be returned each time. |
199 // http://www.whatwg.org/specs/web-apps/current-work/#dom-texttrack-cues | 194 // http://www.whatwg.org/specs/web-apps/current-work/#dom-texttrack-cues |
200 if (m_mode != disabledKeyword()) | 195 if (m_mode != disabledKeyword()) |
201 return ensureTextTrackCueList(); | 196 return ensureTextTrackCueList(); |
202 return 0; | 197 return 0; |
203 } | 198 } |
204 | 199 |
205 void TextTrack::removeAllCues() | 200 void TextTrack::removeAllCues() |
206 { | 201 { |
207 if (!m_cues) | 202 if (!m_cues) |
208 return; | 203 return; |
209 | 204 |
210 if (m_client) | 205 if (mediaElement()) |
211 m_client->textTrackRemoveCues(this, m_cues.get()); | 206 mediaElement()->textTrackRemoveCues(this, m_cues.get()); |
212 | 207 |
213 for (size_t i = 0; i < m_cues->length(); ++i) | 208 for (size_t i = 0; i < m_cues->length(); ++i) |
214 m_cues->item(i)->setTrack(0); | 209 m_cues->item(i)->setTrack(0); |
215 | 210 |
216 m_cues = nullptr; | 211 m_cues = nullptr; |
217 } | 212 } |
218 | 213 |
219 TextTrackCueList* TextTrack::activeCues() const | 214 TextTrackCueList* TextTrack::activeCues() const |
220 { | 215 { |
221 // 4.8.10.12.5 If the text track mode ... is not the text track disabled mod
e, | 216 // 4.8.10.12.5 If the text track mode ... is not the text track disabled mod
e, |
(...skipping 25 matching lines...) Expand all Loading... |
247 // 1. If the given cue is in a text track list of cues, then remove cue from
that text track | 242 // 1. If the given cue is in a text track list of cues, then remove cue from
that text track |
248 // list of cues. | 243 // list of cues. |
249 TextTrack* cueTrack = cue->track(); | 244 TextTrack* cueTrack = cue->track(); |
250 if (cueTrack && cueTrack != this) | 245 if (cueTrack && cueTrack != this) |
251 cueTrack->removeCue(cue.get(), ASSERT_NO_EXCEPTION); | 246 cueTrack->removeCue(cue.get(), ASSERT_NO_EXCEPTION); |
252 | 247 |
253 // 2. Add cue to the method's TextTrack object's text track's text track lis
t of cues. | 248 // 2. Add cue to the method's TextTrack object's text track's text track lis
t of cues. |
254 cue->setTrack(this); | 249 cue->setTrack(this); |
255 ensureTextTrackCueList()->add(cue); | 250 ensureTextTrackCueList()->add(cue); |
256 | 251 |
257 if (m_client) | 252 if (mediaElement()) |
258 m_client->textTrackAddCue(this, cue.get()); | 253 mediaElement()->textTrackAddCue(this, cue.get()); |
259 } | 254 } |
260 | 255 |
261 void TextTrack::removeCue(TextTrackCue* cue, ExceptionState& exceptionState) | 256 void TextTrack::removeCue(TextTrackCue* cue, ExceptionState& exceptionState) |
262 { | 257 { |
263 if (!cue) | 258 if (!cue) |
264 return; | 259 return; |
265 | 260 |
266 // 4.8.10.12.5 Text track API | 261 // 4.8.10.12.5 Text track API |
267 | 262 |
268 // The removeCue(cue) method of TextTrack objects, when invoked, must run th
e following steps: | 263 // The removeCue(cue) method of TextTrack objects, when invoked, must run th
e following steps: |
269 | 264 |
270 // 1. If the given cue is not currently listed in the method's TextTrack | 265 // 1. If the given cue is not currently listed in the method's TextTrack |
271 // object's text track's text track list of cues, then throw a NotFoundError
exception. | 266 // object's text track's text track list of cues, then throw a NotFoundError
exception. |
272 if (cue->track() != this) { | 267 if (cue->track() != this) { |
273 exceptionState.throwDOMException(NotFoundError, "The specified cue is no
t listed in the TextTrack's list of cues."); | 268 exceptionState.throwDOMException(NotFoundError, "The specified cue is no
t listed in the TextTrack's list of cues."); |
274 return; | 269 return; |
275 } | 270 } |
276 | 271 |
277 // 2. Remove cue from the method's TextTrack object's text track's text trac
k list of cues. | 272 // 2. Remove cue from the method's TextTrack object's text track's text trac
k list of cues. |
278 if (!m_cues || !m_cues->remove(cue)) { | 273 if (!m_cues || !m_cues->remove(cue)) { |
279 exceptionState.throwDOMException(InvalidStateError, "Failed to remove th
e specified cue."); | 274 exceptionState.throwDOMException(InvalidStateError, "Failed to remove th
e specified cue."); |
280 return; | 275 return; |
281 } | 276 } |
282 | 277 |
283 cue->setTrack(0); | 278 cue->setTrack(0); |
284 if (m_client) | 279 if (mediaElement()) |
285 m_client->textTrackRemoveCue(this, cue); | 280 mediaElement()->textTrackRemoveCue(this, cue); |
286 } | 281 } |
287 | 282 |
288 VTTRegionList* TextTrack::ensureVTTRegionList() | 283 VTTRegionList* TextTrack::ensureVTTRegionList() |
289 { | 284 { |
290 if (!m_regions) | 285 if (!m_regions) |
291 m_regions = VTTRegionList::create(); | 286 m_regions = VTTRegionList::create(); |
292 | 287 |
293 return m_regions.get(); | 288 return m_regions.get(); |
294 } | 289 } |
295 | 290 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 if (!m_regions || !m_regions->remove(region)) { | 346 if (!m_regions || !m_regions->remove(region)) { |
352 exceptionState.throwDOMException(InvalidStateError, "Failed to remove th
e specified region."); | 347 exceptionState.throwDOMException(InvalidStateError, "Failed to remove th
e specified region."); |
353 return; | 348 return; |
354 } | 349 } |
355 | 350 |
356 region->setTrack(0); | 351 region->setTrack(0); |
357 } | 352 } |
358 | 353 |
359 void TextTrack::cueWillChange(TextTrackCue* cue) | 354 void TextTrack::cueWillChange(TextTrackCue* cue) |
360 { | 355 { |
361 if (!m_client) | 356 if (!mediaElement()) |
362 return; | 357 return; |
363 | 358 |
364 // The cue may need to be repositioned in the media element's interval tree,
may need to | 359 // The cue may need to be repositioned in the media element's interval tree,
may need to |
365 // be re-rendered, etc, so remove it before the modification... | 360 // be re-rendered, etc, so remove it before the modification... |
366 m_client->textTrackRemoveCue(this, cue); | 361 mediaElement()->textTrackRemoveCue(this, cue); |
367 } | 362 } |
368 | 363 |
369 void TextTrack::cueDidChange(TextTrackCue* cue) | 364 void TextTrack::cueDidChange(TextTrackCue* cue) |
370 { | 365 { |
371 if (!m_client) | 366 if (!mediaElement()) |
372 return; | 367 return; |
373 | 368 |
374 // Make sure the TextTrackCueList order is up-to-date. | 369 // Make sure the TextTrackCueList order is up-to-date. |
375 ensureTextTrackCueList()->updateCueIndex(cue); | 370 ensureTextTrackCueList()->updateCueIndex(cue); |
376 | 371 |
377 // ... and add it back again. | 372 // ... and add it back again. |
378 m_client->textTrackAddCue(this, cue); | 373 mediaElement()->textTrackAddCue(this, cue); |
379 } | 374 } |
380 | 375 |
381 int TextTrack::trackIndex() | 376 int TextTrack::trackIndex() |
382 { | 377 { |
383 ASSERT(m_trackList); | 378 ASSERT(m_trackList); |
384 | 379 |
385 if (m_trackIndex == invalidTrackIndex) | 380 if (m_trackIndex == invalidTrackIndex) |
386 m_trackIndex = m_trackList->getTrackIndex(this); | 381 m_trackIndex = m_trackList->getTrackIndex(this); |
387 | 382 |
388 return m_trackIndex; | 383 return m_trackIndex; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
426 const AtomicString& TextTrack::interfaceName() const | 421 const AtomicString& TextTrack::interfaceName() const |
427 { | 422 { |
428 return EventTargetNames::TextTrack; | 423 return EventTargetNames::TextTrack; |
429 } | 424 } |
430 | 425 |
431 ExecutionContext* TextTrack::executionContext() const | 426 ExecutionContext* TextTrack::executionContext() const |
432 { | 427 { |
433 return m_document; | 428 return m_document; |
434 } | 429 } |
435 | 430 |
| 431 HTMLMediaElement* TextTrack::mediaElement() |
| 432 { |
| 433 return m_trackList ? m_trackList->owner() : 0; |
| 434 } |
| 435 |
436 } // namespace WebCore | 436 } // namespace WebCore |
OLD | NEW |