HTMLMediaElement.h revision 2daae5fd11344eaa88a0d92b0f6d65f8d2255c00
1/*
2 * Copyright (C) 2007, 2008, 2009, 2010 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 "ActiveDOMObject.h"
33#include "MediaCanStartListener.h"
34#include "MediaPlayer.h"
35
36#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
37#include "MediaPlayerProxy.h"
38#endif
39
40namespace WebCore {
41
42class Event;
43class HTMLSourceElement;
44class MediaControls;
45class MediaError;
46class KURL;
47class TimeRanges;
48#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
49class Widget;
50#endif
51
52// FIXME: The inheritance from MediaPlayerClient here should be private inheritance.
53// But it can't be until the Chromium WebMediaPlayerClientImpl class is fixed so it
54// no longer depends on typecasting a MediaPlayerClient to an HTMLMediaElement.
55
56class HTMLMediaElement : public HTMLElement, public MediaPlayerClient, private MediaCanStartListener, private ActiveDOMObject {
57public:
58    MediaPlayer* player() const { return m_player.get(); }
59
60    virtual bool isVideo() const = 0;
61    virtual bool hasVideo() const { return false; }
62    virtual bool hasAudio() const;
63
64    void rewind(float timeDelta);
65    void returnToRealtime();
66
67    // Eventually overloaded in HTMLVideoElement
68    virtual bool supportsFullscreen() const { return false; };
69
70    virtual bool supportsSave() const;
71
72    PlatformMedia platformMedia() const;
73#if USE(ACCELERATED_COMPOSITING)
74    PlatformLayer* platformLayer() const;
75#endif
76
77    void scheduleLoad();
78
79    MediaPlayer::MovieLoadType movieLoadType() const;
80
81    bool inActiveDocument() const { return m_inActiveDocument; }
82
83// DOM API
84// error state
85    PassRefPtr<MediaError> error() const;
86
87// network state
88    void setSrc(const String&);
89    String currentSrc() const;
90
91    enum NetworkState { NETWORK_EMPTY, NETWORK_IDLE, NETWORK_LOADING, NETWORK_NO_SOURCE };
92    NetworkState networkState() const;
93
94    String preload() const;
95    void setPreload(const String&);
96
97    PassRefPtr<TimeRanges> buffered() const;
98    void load(bool isUserGesture, ExceptionCode&);
99    String canPlayType(const String& mimeType) const;
100
101// ready state
102    enum ReadyState { HAVE_NOTHING, HAVE_METADATA, HAVE_CURRENT_DATA, HAVE_FUTURE_DATA, HAVE_ENOUGH_DATA };
103    ReadyState readyState() const;
104    bool seeking() const;
105
106// playback state
107    float currentTime() const;
108    void setCurrentTime(float, ExceptionCode&);
109    float startTime() const;
110    float duration() const;
111    bool paused() const;
112    float defaultPlaybackRate() const;
113    void setDefaultPlaybackRate(float);
114    float playbackRate() const;
115    void setPlaybackRate(float);
116    bool webkitPreservesPitch() const;
117    void setWebkitPreservesPitch(bool);
118    PassRefPtr<TimeRanges> played();
119    PassRefPtr<TimeRanges> seekable() const;
120    bool ended() const;
121    bool autoplay() const;
122    void setAutoplay(bool b);
123    bool loop() const;
124    void setLoop(bool b);
125    void play(bool isUserGesture);
126    void pause(bool isUserGesture);
127
128// captions
129    bool webkitHasClosedCaptions() const;
130    bool webkitClosedCaptionsVisible() const;
131    void setWebkitClosedCaptionsVisible(bool);
132
133#if ENABLE(MEDIA_STATISTICS)
134// Statistics
135    unsigned webkitAudioDecodedByteCount() const;
136    unsigned webkitVideoDecodedByteCount() const;
137#endif
138
139// controls
140    bool controls() const;
141    void setControls(bool);
142    float volume() const;
143    void setVolume(float, ExceptionCode&);
144    bool muted() const;
145    void setMuted(bool);
146    void togglePlayState();
147    void beginScrubbing();
148    void endScrubbing();
149
150    bool canPlay() const;
151
152    float percentLoaded() const;
153
154#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
155    void allocateMediaPlayerIfNecessary();
156    void setNeedWidgetUpdate(bool needWidgetUpdate) { m_needWidgetUpdate = needWidgetUpdate; }
157    void deliverNotification(MediaPlayerProxyNotificationType notification);
158    void setMediaPlayerProxy(WebMediaPlayerProxy* proxy);
159    void getPluginProxyParams(KURL& url, Vector<String>& names, Vector<String>& values);
160    virtual void finishParsingChildren();
161    void createMediaPlayerProxy();
162    void updateWidget(PluginCreationOption);
163#endif
164
165    bool hasSingleSecurityOrigin() const { return !m_player || m_player->hasSingleSecurityOrigin(); }
166
167    bool isFullscreen() const;
168    void enterFullscreen();
169    void exitFullscreen();
170
171    bool hasClosedCaptions() const;
172    bool closedCaptionsVisible() const;
173    void setClosedCaptionsVisible(bool);
174
175    MediaControls* mediaControls();
176
177    bool processingUserGesture() const;
178
179    void sourceWillBeRemoved(HTMLSourceElement*);
180    void sourceWasAdded(HTMLSourceElement*);
181
182    void privateBrowsingStateDidChange();
183
184    // Restrictions to change default behaviors.
185    enum BehaviorRestrictionFlags {
186        NoRestrictions = 0,
187        RequireUserGestureForLoadRestriction = 1 << 0,
188        RequireUserGestureForRateChangeRestriction = 1 << 1,
189        RequireUserGestureForFullScreenRestriction = 1 << 2
190    };
191    typedef unsigned BehaviorRestrictions;
192
193    bool requireUserGestureForLoad() const { return m_restrictions & RequireUserGestureForLoadRestriction; }
194    bool requireUserGestureForRateChange() const { return m_restrictions & RequireUserGestureForRateChangeRestriction; }
195    bool requireUserGestureForFullScreen() const { return m_restrictions & RequireUserGestureForFullScreenRestriction; }
196
197    void setBehaviorRestrictions(BehaviorRestrictions restrictions) { m_restrictions = restrictions; }
198
199    // Media cache management.
200    static void getSitesInMediaCache(Vector<String>&);
201    static void clearMediaCache();
202    static void clearMediaCacheForSite(const String&);
203
204protected:
205    HTMLMediaElement(const QualifiedName&, Document*);
206    virtual ~HTMLMediaElement();
207
208    virtual void parseMappedAttribute(Attribute*);
209    virtual bool isURLAttribute(Attribute*) const;
210    virtual void attach();
211
212    virtual void willMoveToNewOwnerDocument();
213    virtual void didMoveToNewOwnerDocument();
214
215    enum DisplayMode { Unknown, None, Poster, PosterWaitingForVideo, Video };
216    DisplayMode displayMode() const { return m_displayMode; }
217    virtual void setDisplayMode(DisplayMode mode) { m_displayMode = mode; }
218
219private:
220    virtual void attributeChanged(Attribute*, bool preserveDecls);
221    virtual bool rendererIsNeeded(RenderStyle*);
222    virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
223    virtual void insertedIntoDocument();
224    virtual void removedFromDocument();
225    virtual void recalcStyle(StyleChange);
226
227    virtual void defaultEventHandler(Event*);
228
229    // ActiveDOMObject functions.
230    virtual bool canSuspend() const;
231    virtual void suspend(ReasonForSuspension);
232    virtual void resume();
233    virtual void stop();
234    virtual bool hasPendingActivity() const;
235
236    virtual void mediaVolumeDidChange();
237
238    virtual void updateDisplayState() { }
239
240    void setReadyState(MediaPlayer::ReadyState);
241    void setNetworkState(MediaPlayer::NetworkState);
242
243    virtual Document* mediaPlayerOwningDocument();
244    virtual void mediaPlayerNetworkStateChanged(MediaPlayer*);
245    virtual void mediaPlayerReadyStateChanged(MediaPlayer*);
246    virtual void mediaPlayerTimeChanged(MediaPlayer*);
247    virtual void mediaPlayerVolumeChanged(MediaPlayer*);
248    virtual void mediaPlayerMuteChanged(MediaPlayer*);
249    virtual void mediaPlayerDurationChanged(MediaPlayer*);
250    virtual void mediaPlayerRateChanged(MediaPlayer*);
251    virtual void mediaPlayerPlaybackStateChanged(MediaPlayer*);
252    virtual void mediaPlayerSawUnsupportedTracks(MediaPlayer*);
253    virtual void mediaPlayerRepaint(MediaPlayer*);
254    virtual void mediaPlayerSizeChanged(MediaPlayer*);
255#if USE(ACCELERATED_COMPOSITING)
256    virtual bool mediaPlayerRenderingCanBeAccelerated(MediaPlayer*);
257    virtual void mediaPlayerRenderingModeChanged(MediaPlayer*);
258#endif
259    virtual void mediaPlayerEngineUpdated(MediaPlayer*);
260    virtual void mediaPlayerFirstVideoFrameAvailable(MediaPlayer*);
261
262    void loadTimerFired(Timer<HTMLMediaElement>*);
263    void asyncEventTimerFired(Timer<HTMLMediaElement>*);
264    void progressEventTimerFired(Timer<HTMLMediaElement>*);
265    void playbackProgressTimerFired(Timer<HTMLMediaElement>*);
266    void startPlaybackProgressTimer();
267    void startProgressEventTimer();
268    void stopPeriodicTimers();
269
270    void seek(float time, ExceptionCode&);
271    void finishSeek();
272    void checkIfSeekNeeded();
273    void addPlayedRange(float start, float end);
274
275    void scheduleTimeupdateEvent(bool periodicEvent);
276    void scheduleEvent(const AtomicString& eventName);
277
278    // loading
279    void selectMediaResource();
280    void loadResource(const KURL&, ContentType&);
281    void scheduleNextSourceChild();
282    void loadNextSourceChild();
283    void userCancelledLoad();
284    bool havePotentialSourceChild();
285    void noneSupported();
286    void mediaEngineError(PassRefPtr<MediaError> err);
287    void cancelPendingEventsAndCallbacks();
288    void waitForSourceChange();
289
290    enum InvalidSourceAction { DoNothing, Complain };
291    bool isSafeToLoadURL(const KURL&, InvalidSourceAction);
292    KURL selectNextSourceChild(ContentType*, InvalidSourceAction);
293
294    // These "internal" functions do not check user gesture restrictions.
295    void loadInternal();
296    void playInternal();
297    void pauseInternal();
298
299    void prepareForLoad();
300    void allowVideoRendering();
301
302    bool processingMediaPlayerCallback() const { return m_processingMediaPlayerCallback > 0; }
303    void beginProcessingMediaPlayerCallback() { ++m_processingMediaPlayerCallback; }
304    void endProcessingMediaPlayerCallback() { ASSERT(m_processingMediaPlayerCallback); --m_processingMediaPlayerCallback; }
305
306    void updateVolume();
307    void updatePlayState();
308    bool potentiallyPlaying() const;
309    bool endedPlayback() const;
310    bool stoppedDueToErrors() const;
311    bool pausedForUserInteraction() const;
312    bool couldPlayIfEnoughData() const;
313
314    float minTimeSeekable() const;
315    float maxTimeSeekable() const;
316
317    // Pauses playback without changing any states or generating events
318    void setPausedInternal(bool);
319
320    virtual void mediaCanStart();
321
322    void setShouldDelayLoadEvent(bool);
323
324    void invalidateCachedTime();
325    void refreshCachedTime() const;
326
327    bool hasMediaControls();
328    void ensureMediaControls();
329
330    virtual void* preDispatchEventHandler(Event*);
331
332    Timer<HTMLMediaElement> m_loadTimer;
333    Timer<HTMLMediaElement> m_asyncEventTimer;
334    Timer<HTMLMediaElement> m_progressEventTimer;
335    Timer<HTMLMediaElement> m_playbackProgressTimer;
336    Vector<RefPtr<Event> > m_pendingEvents;
337    RefPtr<TimeRanges> m_playedTimeRanges;
338
339    float m_playbackRate;
340    float m_defaultPlaybackRate;
341    bool m_webkitPreservesPitch;
342    NetworkState m_networkState;
343    ReadyState m_readyState;
344    ReadyState m_readyStateMaximum;
345    String m_currentSrc;
346
347    RefPtr<MediaError> m_error;
348
349    float m_volume;
350    float m_lastSeekTime;
351
352    unsigned m_previousProgress;
353    double m_previousProgressTime;
354
355    // the last time a timeupdate event was sent (wall clock)
356    double m_lastTimeUpdateEventWallTime;
357
358    // the last time a timeupdate event was sent in movie time
359    float m_lastTimeUpdateEventMovieTime;
360
361    // loading state
362    enum LoadState { WaitingForSource, LoadingFromSrcAttr, LoadingFromSourceElement };
363    LoadState m_loadState;
364    HTMLSourceElement* m_currentSourceNode;
365    Node* m_nextChildNodeToConsider;
366    Node* sourceChildEndOfListValue() { return static_cast<Node*>(this); }
367
368    OwnPtr<MediaPlayer> m_player;
369#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
370    RefPtr<Widget> m_proxyWidget;
371#endif
372
373    BehaviorRestrictions m_restrictions;
374
375    MediaPlayer::Preload m_preload;
376
377    DisplayMode m_displayMode;
378
379    // Counter incremented while processing a callback from the media player, so we can avoid
380    // calling the media engine recursively.
381    int m_processingMediaPlayerCallback;
382
383    mutable float m_cachedTime;
384    mutable double m_cachedTimeWallClockUpdateTime;
385    mutable double m_minimumWallClockTimeToCacheMediaTime;
386
387    bool m_playing : 1;
388    bool m_isWaitingUntilMediaCanStart : 1;
389    bool m_shouldDelayLoadEvent : 1;
390    bool m_haveFiredLoadedData : 1;
391    bool m_inActiveDocument : 1;
392    bool m_autoplaying : 1;
393    bool m_muted : 1;
394    bool m_paused : 1;
395    bool m_seeking : 1;
396
397    // data has not been loaded since sending a "stalled" event
398    bool m_sentStalledEvent : 1;
399
400    // time has not changed since sending an "ended" event
401    bool m_sentEndEvent : 1;
402
403    bool m_pausedInternal : 1;
404
405    // Not all media engines provide enough information about a file to be able to
406    // support progress events so setting m_sendProgressEvents disables them
407    bool m_sendProgressEvents : 1;
408
409    bool m_isFullscreen : 1;
410    bool m_closedCaptionsVisible : 1;
411    bool m_mouseOver : 1;
412
413#if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
414    bool m_needWidgetUpdate : 1;
415#endif
416
417    bool m_dispatchingCanPlayEvent : 1;
418    bool m_loadInitiatedByUserGesture : 1;
419    bool m_completelyLoaded : 1;
420};
421
422} //namespace
423
424#endif
425#endif
426