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