1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef TrackListBase_h 6#define TrackListBase_h 7 8#include "core/events/EventTarget.h" 9 10#include "core/html/HTMLMediaElement.h" 11#include "core/html/track/TrackEvent.h" 12 13namespace blink { 14 15template<class T> 16class TrackListBase : public RefCountedWillBeGarbageCollectedFinalized<TrackListBase<T> >, public EventTargetWithInlineData { 17 REFCOUNTED_EVENT_TARGET(TrackListBase); 18 WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(TrackListBase); 19public: 20 explicit TrackListBase(HTMLMediaElement* mediaElement) 21 : m_mediaElement(mediaElement) 22 { 23 } 24 25 virtual ~TrackListBase() 26 { 27#if !ENABLE(OILPAN) 28 ASSERT(m_tracks.isEmpty()); 29 ASSERT(!m_mediaElement); 30#endif 31 } 32 33 unsigned length() const { return m_tracks.size(); } 34 T* anonymousIndexedGetter(unsigned index) const 35 { 36 if (index >= m_tracks.size()) 37 return 0; 38 return m_tracks[index].get(); 39 } 40 41 T* getTrackById(const String& id) const 42 { 43 for (unsigned i = 0; i < m_tracks.size(); ++i) { 44 if (m_tracks[i]->id() == id) 45 return m_tracks[i].get(); 46 } 47 48 return 0; 49 } 50 51 DEFINE_ATTRIBUTE_EVENT_LISTENER(change); 52 DEFINE_ATTRIBUTE_EVENT_LISTENER(addtrack); 53 DEFINE_ATTRIBUTE_EVENT_LISTENER(removetrack); 54 55 // EventTarget interface 56 virtual ExecutionContext* executionContext() const OVERRIDE 57 { 58 if (m_mediaElement) 59 return m_mediaElement->executionContext(); 60 return 0; 61 } 62 63#if !ENABLE(OILPAN) 64 void shutdown() 65 { 66 removeAll(); 67 m_mediaElement = nullptr; 68 } 69#endif 70 71 void add(PassRefPtrWillBeRawPtr<T> prpTrack) 72 { 73 RefPtrWillBeRawPtr<T> track = prpTrack; 74 75 track->setMediaElement(m_mediaElement); 76 m_tracks.append(track); 77 scheduleTrackEvent(EventTypeNames::addtrack, track.release()); 78 } 79 80 void remove(blink::WebMediaPlayer::TrackId trackId) 81 { 82 for (unsigned i = 0; i < m_tracks.size(); ++i) { 83 if (m_tracks[i]->trackId() != trackId) 84 continue; 85 86 m_tracks[i]->setMediaElement(0); 87 scheduleTrackEvent(EventTypeNames::removetrack, m_tracks[i]); 88 m_tracks.remove(i); 89 return; 90 } 91 ASSERT_NOT_REACHED(); 92 } 93 94 void removeAll() 95 { 96 for (unsigned i = 0; i < m_tracks.size(); ++i) 97 m_tracks[i]->setMediaElement(0); 98 99 m_tracks.clear(); 100 } 101 102 void scheduleChangeEvent() 103 { 104 RefPtrWillBeRawPtr<Event> event = Event::create(EventTypeNames::change); 105 event->setTarget(this); 106 m_mediaElement->scheduleEvent(event); 107 } 108 109 Node* owner() const { return m_mediaElement; } 110 111 void trace(Visitor* visitor) 112 { 113 visitor->trace(m_tracks); 114 visitor->trace(m_mediaElement); 115 EventTargetWithInlineData::trace(visitor); 116 } 117 118private: 119 void scheduleTrackEvent(const AtomicString& eventName, PassRefPtrWillBeRawPtr<T> track) 120 { 121 TrackEventInit initializer; 122 initializer.track = track; 123 initializer.bubbles = false; 124 initializer.cancelable = false; 125 RefPtrWillBeRawPtr<Event> event = TrackEvent::create(eventName, initializer); 126 event->setTarget(this); 127 m_mediaElement->scheduleEvent(event); 128 } 129 130 WillBeHeapVector<RefPtrWillBeMember<T> > m_tracks; 131 RawPtrWillBeMember<HTMLMediaElement> m_mediaElement; 132}; 133 134} 135 136#endif 137