• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007, 2008, 2009 Apple 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 #ifndef HTMLMediaElement_h
27 #define HTMLMediaElement_h
28 
29 #if ENABLE(VIDEO)
30 
31 #include "HTMLElement.h"
32 #include "MediaPlayer.h"
33 #include "Timer.h"
34 
35 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
36 #include "MediaPlayerProxy.h"
37 #endif
38 
39 namespace WebCore {
40 
41 class Event;
42 class HTMLSourceElement;
43 class MediaError;
44 class KURL;
45 class TimeRanges;
46 
47 class HTMLMediaElement : public HTMLElement, public MediaPlayerClient {
48 public:
49     HTMLMediaElement(const QualifiedName&, Document*);
50     virtual ~HTMLMediaElement();
51 
52     bool checkDTD(const Node* newChild);
53 
54     void attributeChanged(Attribute*, bool preserveDecls);
55     void parseMappedAttribute(MappedAttribute *);
56 
57     virtual bool rendererIsNeeded(RenderStyle*);
58     virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
59     virtual void insertedIntoDocument();
60     virtual void removedFromDocument();
61     virtual void attach();
62     virtual void recalcStyle(StyleChange);
63 
player()64     MediaPlayer* player() const { return m_player.get(); }
65 
isVideo()66     virtual bool isVideo() const { return false; }
hasVideo()67     virtual bool hasVideo() const { return false; }
68 
69     void rewind(float timeDelta);
70     void returnToRealtime();
71 
72     // Eventually overloaded in HTMLVideoElement
supportsFullscreen()73     virtual bool supportsFullscreen() const { return false; };
74     virtual bool supportsSave() const;
75 
76     void scheduleLoad();
77 
78     virtual void defaultEventHandler(Event*);
79 
80     // Pauses playback without changing any states or generating events
81     void setPausedInternal(bool);
82 
83     MediaPlayer::MovieLoadType movieLoadType() const;
84 
inActiveDocument()85     bool inActiveDocument() const { return m_inActiveDocument; }
86 
87 // DOM API
88 // error state
89     PassRefPtr<MediaError> error() const;
90 
91 // network state
92     KURL src() const;
93     void setSrc(const String&);
94     String currentSrc() const;
95 
96     enum NetworkState { NETWORK_EMPTY, NETWORK_IDLE, NETWORK_LOADING, NETWORK_LOADED, NETWORK_NO_SOURCE };
97     NetworkState networkState() const;
98     bool autobuffer() const;
99     void setAutobuffer(bool);
100 
101     PassRefPtr<TimeRanges> buffered() const;
102     void load(ExceptionCode&);
103     String canPlayType(const String& mimeType) const;
104 
105 // ready state
106     enum ReadyState { HAVE_NOTHING, HAVE_METADATA, HAVE_CURRENT_DATA, HAVE_FUTURE_DATA, HAVE_ENOUGH_DATA };
107     ReadyState readyState() const;
108     bool seeking() const;
109 
110 // playback state
111     float currentTime() const;
112     void setCurrentTime(float, ExceptionCode&);
113     float startTime() const;
114     float duration() const;
115     bool paused() const;
116     float defaultPlaybackRate() const;
117     void setDefaultPlaybackRate(float);
118     float playbackRate() const;
119     void setPlaybackRate(float);
120     bool webkitPreservesPitch() const;
121     void setWebkitPreservesPitch(bool);
122     PassRefPtr<TimeRanges> played() const;
123     PassRefPtr<TimeRanges> seekable() const;
124     bool ended() const;
125     bool autoplay() const;
126     void setAutoplay(bool b);
127     bool loop() const;
128     void setLoop(bool b);
129     void play();
130     void pause();
131 
132 // controls
133     bool controls() const;
134     void setControls(bool);
135     float volume() const;
136     void setVolume(float, ExceptionCode&);
137     bool muted() const;
138     void setMuted(bool);
139     void togglePlayState();
140     void beginScrubbing();
141     void endScrubbing();
142 
143     bool canPlay() const;
144 
145     float percentLoaded() const;
146 
147 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
setNeedWidgetUpdate(bool needWidgetUpdate)148     void setNeedWidgetUpdate(bool needWidgetUpdate) { m_needWidgetUpdate = needWidgetUpdate; }
149     void deliverNotification(MediaPlayerProxyNotificationType notification);
150     void setMediaPlayerProxy(WebMediaPlayerProxy* proxy);
151     String initialURL();
152     virtual void finishParsingChildren();
153 #endif
154 
hasSingleSecurityOrigin()155     bool hasSingleSecurityOrigin() const { return !m_player || m_player->hasSingleSecurityOrigin(); }
156 
157 protected:
158     float getTimeOffsetAttribute(const QualifiedName&, float valueOnError) const;
159     void setTimeOffsetAttribute(const QualifiedName&, float value);
160 
161     virtual void documentWillBecomeInactive();
162     virtual void documentDidBecomeActive();
163     virtual void mediaVolumeDidChange();
164 
165     void setReadyState(MediaPlayer::ReadyState);
166     void setNetworkState(MediaPlayer::NetworkState);
167 
168 private: // MediaPlayerClient
169     virtual void mediaPlayerNetworkStateChanged(MediaPlayer*);
170     virtual void mediaPlayerReadyStateChanged(MediaPlayer*);
171     virtual void mediaPlayerTimeChanged(MediaPlayer*);
172     virtual void mediaPlayerVolumeChanged(MediaPlayer*);
173     virtual void mediaPlayerDurationChanged(MediaPlayer*);
174     virtual void mediaPlayerRateChanged(MediaPlayer*);
175     virtual void mediaPlayerSawUnsupportedTracks(MediaPlayer*);
176     virtual void mediaPlayerRepaint(MediaPlayer*);
177     virtual void mediaPlayerSizeChanged(MediaPlayer*);
178 #if USE(ACCELERATED_COMPOSITING)
179     virtual bool mediaPlayerRenderingCanBeAccelerated(MediaPlayer*);
180     virtual GraphicsLayer* mediaPlayerGraphicsLayer(MediaPlayer*);
181 #endif
182 
183 private:
184     void loadTimerFired(Timer<HTMLMediaElement>*);
185     void asyncEventTimerFired(Timer<HTMLMediaElement>*);
186     void progressEventTimerFired(Timer<HTMLMediaElement>*);
187     void playbackProgressTimerFired(Timer<HTMLMediaElement>*);
188     void startPlaybackProgressTimer();
189     void startProgressEventTimer();
190     void stopPeriodicTimers();
191 
192     void seek(float time, ExceptionCode&);
193     void checkIfSeekNeeded();
194 
195     void scheduleTimeupdateEvent(bool periodicEvent);
196     void scheduleProgressEvent(const AtomicString& eventName);
197     void scheduleEvent(const AtomicString& eventName);
198     void enqueueEvent(RefPtr<Event> event);
199 
200     // loading
201     void selectMediaResource();
202     void loadResource(const KURL&, ContentType&);
203     void loadNextSourceChild();
204     void userCancelledLoad();
205     bool havePotentialSourceChild();
206     void noneSupported();
207     void mediaEngineError(PassRefPtr<MediaError> err);
208     void cancelPendingEventsAndCallbacks();
209 
210     enum InvalidSourceAction { DoNothing, Complain };
211     bool isSafeToLoadURL(const KURL&, InvalidSourceAction);
212     KURL selectNextSourceChild(ContentType*, InvalidSourceAction);
213 
214     // These "internal" functions do not check user gesture restrictions.
215     void loadInternal();
216     void playInternal();
217     void pauseInternal();
218 
219     bool processingUserGesture() const;
processingMediaPlayerCallback()220     bool processingMediaPlayerCallback() const { return m_processingMediaPlayerCallback > 0; }
beginProcessingMediaPlayerCallback()221     void beginProcessingMediaPlayerCallback() { ++m_processingMediaPlayerCallback; }
endProcessingMediaPlayerCallback()222     void endProcessingMediaPlayerCallback() { ASSERT(m_processingMediaPlayerCallback); --m_processingMediaPlayerCallback; }
223 
224     void updateVolume();
225     void updatePlayState();
226     bool potentiallyPlaying() const;
227     bool endedPlayback() const;
228     bool stoppedDueToErrors() const;
229     bool pausedForUserInteraction() const;
230 #if PLATFORM(ANDROID)
231     bool couldPlayIfEnoughData() const;
232 #endif
233 
234     float minTimeSeekable() const;
235     float maxTimeSeekable() const;
236 
237     // Restrictions to change default behaviors. This is a effectively a compile time choice at the moment
238     //  because there are no accessor methods.
239     enum BehaviorRestrictions {
240         NoRestrictions = 0,
241         RequireUserGestureForLoadRestriction = 1 << 0,
242         RequireUserGestureForRateChangeRestriction = 1 << 1,
243     };
244 
245 protected:
246     Timer<HTMLMediaElement> m_loadTimer;
247     Timer<HTMLMediaElement> m_asyncEventTimer;
248     Timer<HTMLMediaElement> m_progressEventTimer;
249     Timer<HTMLMediaElement> m_playbackProgressTimer;
250     Vector<RefPtr<Event> > m_pendingEvents;
251     RefPtr<TimeRanges> m_playedTimeRanges;
252 
253     float m_playbackRate;
254     float m_defaultPlaybackRate;
255     bool m_webkitPreservesPitch;
256     NetworkState m_networkState;
257     ReadyState m_readyState;
258     String m_currentSrc;
259 
260     RefPtr<MediaError> m_error;
261 
262     float m_volume;
263     float m_lastSeekTime;
264 
265     unsigned m_previousProgress;
266     double m_previousProgressTime;
267 
268     // the last time a timeupdate event was sent (wall clock)
269     double m_lastTimeUpdateEventWallTime;
270 
271     // the last time a timeupdate event was sent in movie time
272     float m_lastTimeUpdateEventMovieTime;
273 
274     // loading state
275     enum LoadState { WaitingForSource, LoadingFromSrcAttr, LoadingFromSourceElement };
276     LoadState m_loadState;
277     HTMLSourceElement *m_currentSourceNode;
278 
279     OwnPtr<MediaPlayer> m_player;
280 
281     BehaviorRestrictions m_restrictions;
282 
283     bool m_playing;
284 
285     // counter incremented while processing a callback from the media player, so we can avoid
286     //  calling the media engine recursively
287     int m_processingMediaPlayerCallback;
288 
289     bool m_processingLoad : 1;
290     bool m_delayingTheLoadEvent : 1;
291     bool m_haveFiredLoadedData : 1;
292     bool m_inActiveDocument : 1;
293     bool m_autoplaying : 1;
294     bool m_muted : 1;
295     bool m_paused : 1;
296     bool m_seeking : 1;
297 
298     // data has not been loaded since sending a "stalled" event
299     bool m_sentStalledEvent : 1;
300 
301     // time has not changed since sending an "ended" event
302     bool m_sentEndEvent : 1;
303 
304     bool m_pausedInternal : 1;
305 
306     // Not all media engines provide enough information about a file to be able to
307     // support progress events so setting m_sendProgressEvents disables them
308     bool m_sendProgressEvents : 1;
309 
310 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
311     bool m_needWidgetUpdate : 1;
312 #endif
313 };
314 
315 } //namespace
316 
317 #endif
318 #endif
319