Home | History | Annotate | Download | only in html
      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 
     40 namespace WebCore {
     41 
     42 class Event;
     43 class HTMLSourceElement;
     44 class MediaControls;
     45 class MediaError;
     46 class KURL;
     47 class TimeRanges;
     48 #if ENABLE(PLUGIN_PROXY_FOR_VIDEO)
     49 class 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 
     56 class HTMLMediaElement : public HTMLElement, public MediaPlayerClient, private MediaCanStartListener, private ActiveDOMObject {
     57 public:
     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 
    204 protected:
    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 
    219 private:
    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 #if PLATFORM(ANDROID)
    422     double m_lastTouch;
    423 #endif
    424 };
    425 
    426 } //namespace
    427 
    428 #endif
    429 #endif
    430