1 /* 2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 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 #include "core/dom/ActiveDOMObject.h" 30 #include "core/dom/GenericEventQueue.h" 31 #include "core/html/HTMLElement.h" 32 #include "core/html/MediaControllerInterface.h" 33 #include "core/html/track/TextTrack.h" 34 #include "core/html/track/TextTrackCue.h" 35 #include "core/platform/PODIntervalTree.h" 36 #include "core/platform/graphics/MediaPlayer.h" 37 #include "public/platform/WebMimeRegistry.h" 38 39 namespace WebKit { class WebLayer; } 40 41 namespace WebCore { 42 43 #if ENABLE(WEB_AUDIO) 44 class AudioSourceProvider; 45 class MediaElementAudioSourceNode; 46 #endif 47 class ContentType; 48 class Event; 49 class ExceptionState; 50 class HTMLSourceElement; 51 class HTMLTrackElement; 52 class KURL; 53 class MediaController; 54 class MediaControls; 55 class MediaError; 56 class HTMLMediaSource; 57 class TextTrackList; 58 class TimeRanges; 59 #if ENABLE(ENCRYPTED_MEDIA_V2) 60 class MediaKeys; 61 #endif 62 63 class InbandTextTrackPrivate; 64 65 typedef PODIntervalTree<double, TextTrackCue*> CueIntervalTree; 66 typedef CueIntervalTree::IntervalType CueInterval; 67 typedef Vector<CueInterval> CueList; 68 69 // FIXME: The inheritance from MediaPlayerClient here should be private inheritance. 70 // But it can't be until the Chromium WebMediaPlayerClientImpl class is fixed so it 71 // no longer depends on typecasting a MediaPlayerClient to an HTMLMediaElement. 72 73 class HTMLMediaElement : public HTMLElement, public MediaPlayerClient, public ActiveDOMObject, public MediaControllerInterface 74 , private TextTrackClient 75 { 76 public: 77 static WebKit::WebMimeRegistry::SupportsType supportsType(const ContentType&, const String& keySystem = String()); 78 79 MediaPlayer* player() const { return m_player.get(); } 80 81 virtual bool isVideo() const = 0; 82 virtual bool hasVideo() const { return false; } 83 virtual bool hasAudio() const; 84 85 // Eventually overloaded in HTMLVideoElement 86 virtual bool supportsFullscreen() const { return false; }; 87 88 virtual bool supportsSave() const; 89 90 WebKit::WebLayer* platformLayer() const; 91 92 enum DelayedActionType { 93 LoadMediaResource = 1 << 0, 94 LoadTextTrackResource = 1 << 1, 95 TextTrackChangesNotification = 1 << 2 96 }; 97 void scheduleDelayedAction(DelayedActionType); 98 99 bool inActiveDocument() const { return m_inActiveDocument; } 100 101 // DOM API 102 // error state 103 PassRefPtr<MediaError> error() const; 104 105 // network state 106 void setSrc(const String&); 107 const KURL& currentSrc() const { return m_currentSrc; } 108 109 enum NetworkState { NETWORK_EMPTY, NETWORK_IDLE, NETWORK_LOADING, NETWORK_NO_SOURCE }; 110 NetworkState networkState() const; 111 112 String preload() const; 113 void setPreload(const String&); 114 115 PassRefPtr<TimeRanges> buffered() const; 116 void load(); 117 String canPlayType(const String& mimeType, const String& keySystem = String(), const KURL& = KURL()) const; 118 119 // ready state 120 ReadyState readyState() const; 121 bool seeking() const; 122 123 // playback state 124 double currentTime() const; 125 void setCurrentTime(double, ExceptionState&); 126 double initialTime() const; 127 double startTime() const; 128 double duration() const; 129 bool paused() const; 130 double defaultPlaybackRate() const; 131 void setDefaultPlaybackRate(double); 132 double playbackRate() const; 133 void setPlaybackRate(double); 134 void updatePlaybackRate(); 135 bool webkitPreservesPitch() const; 136 void setWebkitPreservesPitch(bool); 137 PassRefPtr<TimeRanges> played(); 138 PassRefPtr<TimeRanges> seekable() const; 139 bool ended() const; 140 bool autoplay() const; 141 void setAutoplay(bool b); 142 bool loop() const; 143 void setLoop(bool b); 144 void play(); 145 void pause(); 146 147 // captions 148 bool webkitHasClosedCaptions() const; 149 bool webkitClosedCaptionsVisible() const; 150 void setWebkitClosedCaptionsVisible(bool); 151 152 // Statistics 153 unsigned webkitAudioDecodedByteCount() const; 154 unsigned webkitVideoDecodedByteCount() const; 155 156 // Media Source. 157 void closeMediaSource(); 158 159 void durationChanged(double duration); 160 161 void webkitGenerateKeyRequest(const String& keySystem, PassRefPtr<Uint8Array> initData, ExceptionState&); 162 void webkitGenerateKeyRequest(const String& keySystem, ExceptionState&); 163 void webkitAddKey(const String& keySystem, PassRefPtr<Uint8Array> key, PassRefPtr<Uint8Array> initData, const String& sessionId, ExceptionState&); 164 void webkitAddKey(const String& keySystem, PassRefPtr<Uint8Array> key, ExceptionState&); 165 void webkitCancelKeyRequest(const String& keySystem, const String& sessionId, ExceptionState&); 166 167 DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitkeyadded); 168 DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitkeyerror); 169 DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitkeymessage); 170 DEFINE_ATTRIBUTE_EVENT_LISTENER(webkitneedkey); 171 172 #if ENABLE(ENCRYPTED_MEDIA_V2) 173 MediaKeys* mediaKeys() const { return m_mediaKeys.get(); } 174 void setMediaKeys(MediaKeys*); 175 #endif 176 177 // controls 178 bool controls() const; 179 void setControls(bool); 180 double volume() const; 181 void setVolume(double, ExceptionState&); 182 bool muted() const; 183 void setMuted(bool); 184 185 void togglePlayState(); 186 void beginScrubbing(); 187 void endScrubbing(); 188 189 bool canPlay() const; 190 191 double percentLoaded() const; 192 193 PassRefPtr<TextTrack> addTextTrack(const String& kind, const String& label, const String& language, ExceptionState&); 194 PassRefPtr<TextTrack> addTextTrack(const String& kind, const String& label, ExceptionState& es) { return addTextTrack(kind, label, emptyString(), es); } 195 PassRefPtr<TextTrack> addTextTrack(const String& kind, ExceptionState& es) { return addTextTrack(kind, emptyString(), emptyString(), es); } 196 197 TextTrackList* textTracks(); 198 CueList currentlyActiveCues() const { return m_currentlyActiveCues; } 199 200 void addTrack(TextTrack*); 201 void removeTrack(TextTrack*); 202 void removeAllInbandTracks(); 203 void closeCaptionTracksChanged(); 204 void notifyMediaPlayerOfTextTrackChanges(); 205 206 virtual void didAddTrack(HTMLTrackElement*); 207 virtual void didRemoveTrack(HTMLTrackElement*); 208 209 virtual void mediaPlayerDidAddTrack(PassRefPtr<InbandTextTrackPrivate>) OVERRIDE; 210 virtual void mediaPlayerDidRemoveTrack(PassRefPtr<InbandTextTrackPrivate>) OVERRIDE; 211 212 struct TrackGroup { 213 enum GroupKind { CaptionsAndSubtitles, Description, Chapter, Metadata, Other }; 214 215 TrackGroup(GroupKind kind) 216 : visibleTrack(0) 217 , defaultTrack(0) 218 , kind(kind) 219 , hasSrcLang(false) 220 { 221 } 222 223 Vector<RefPtr<TextTrack> > tracks; 224 RefPtr<TextTrack> visibleTrack; 225 RefPtr<TextTrack> defaultTrack; 226 GroupKind kind; 227 bool hasSrcLang; 228 }; 229 230 void configureTextTrackGroupForLanguage(const TrackGroup&) const; 231 void configureTextTracks(); 232 void configureTextTrackGroup(const TrackGroup&); 233 234 bool textTracksAreReady() const; 235 void configureTextTrackDisplay(); 236 void updateTextTrackDisplay(); 237 238 // TextTrackClient 239 virtual void textTrackReadyStateChanged(TextTrack*); 240 virtual void textTrackKindChanged(TextTrack*); 241 virtual void textTrackModeChanged(TextTrack*); 242 virtual void textTrackAddCues(TextTrack*, const TextTrackCueList*); 243 virtual void textTrackRemoveCues(TextTrack*, const TextTrackCueList*); 244 virtual void textTrackAddCue(TextTrack*, PassRefPtr<TextTrackCue>); 245 virtual void textTrackRemoveCue(TextTrack*, PassRefPtr<TextTrackCue>); 246 247 // EventTarget function. 248 // Both Node (via HTMLElement) and ActiveDOMObject define this method, which 249 // causes an ambiguity error at compile time. This class's constructor 250 // ensures that both implementations return document, so return the result 251 // of one of them here. 252 virtual ScriptExecutionContext* scriptExecutionContext() const OVERRIDE { return HTMLElement::scriptExecutionContext(); } 253 254 bool hasSingleSecurityOrigin() const { return !m_player || m_player->hasSingleSecurityOrigin(); } 255 256 bool isFullscreen() const; 257 void enterFullscreen(); 258 void exitFullscreen(); 259 260 bool hasClosedCaptions() const; 261 bool closedCaptionsVisible() const; 262 void setClosedCaptionsVisible(bool); 263 264 MediaControls* mediaControls() const; 265 266 void sourceWasRemoved(HTMLSourceElement*); 267 void sourceWasAdded(HTMLSourceElement*); 268 269 bool isPlaying() const { return m_playing; } 270 271 virtual bool hasPendingActivity() const; 272 273 #if ENABLE(WEB_AUDIO) 274 MediaElementAudioSourceNode* audioSourceNode() { return m_audioSourceNode; } 275 void setAudioSourceNode(MediaElementAudioSourceNode*); 276 277 AudioSourceProvider* audioSourceProvider(); 278 #endif 279 280 enum InvalidURLAction { DoNothing, Complain }; 281 bool isSafeToLoadURL(const KURL&, InvalidURLAction); 282 283 const String& mediaGroup() const; 284 void setMediaGroup(const String&); 285 286 MediaController* controller() const; 287 void setController(PassRefPtr<MediaController>); 288 289 virtual bool dispatchEvent(PassRefPtr<Event>) OVERRIDE; 290 291 protected: 292 HTMLMediaElement(const QualifiedName&, Document*, bool); 293 virtual ~HTMLMediaElement(); 294 295 virtual void parseAttribute(const QualifiedName&, const AtomicString&) OVERRIDE; 296 virtual void finishParsingChildren(); 297 virtual bool isURLAttribute(const Attribute&) const OVERRIDE; 298 virtual void attach(const AttachContext& = AttachContext()) OVERRIDE; 299 300 virtual void didMoveToNewDocument(Document* oldDocument) OVERRIDE; 301 302 enum DisplayMode { Unknown, None, Poster, PosterWaitingForVideo, Video }; 303 DisplayMode displayMode() const { return m_displayMode; } 304 virtual void setDisplayMode(DisplayMode mode) { m_displayMode = mode; } 305 306 virtual bool isMediaElement() const { return true; } 307 308 // Restrictions to change default behaviors. 309 enum BehaviorRestrictionFlags { 310 NoRestrictions = 0, 311 RequireUserGestureForLoadRestriction = 1 << 0, 312 RequireUserGestureForRateChangeRestriction = 1 << 1, 313 RequireUserGestureForFullscreenRestriction = 1 << 2, 314 RequirePageConsentToLoadMediaRestriction = 1 << 3, 315 }; 316 typedef unsigned BehaviorRestrictions; 317 318 bool userGestureRequiredForLoad() const { return m_restrictions & RequireUserGestureForLoadRestriction; } 319 bool userGestureRequiredForRateChange() const { return m_restrictions & RequireUserGestureForRateChangeRestriction; } 320 bool userGestureRequiredForFullscreen() const { return m_restrictions & RequireUserGestureForFullscreenRestriction; } 321 bool pageConsentRequiredForLoad() const { return m_restrictions & RequirePageConsentToLoadMediaRestriction; } 322 323 void addBehaviorRestriction(BehaviorRestrictions restriction) { m_restrictions |= restriction; } 324 void removeBehaviorRestriction(BehaviorRestrictions restriction) { m_restrictions &= ~restriction; } 325 326 bool ignoreTrackDisplayUpdateRequests() const { return m_ignoreTrackDisplayUpdate > 0; } 327 void beginIgnoringTrackDisplayUpdateRequests(); 328 void endIgnoringTrackDisplayUpdateRequests(); 329 330 private: 331 void createMediaPlayer(); 332 333 virtual bool alwaysCreateUserAgentShadowRoot() const OVERRIDE { return true; } 334 virtual bool areAuthorShadowsAllowed() const OVERRIDE { return false; } 335 336 virtual bool hasCustomFocusLogic() const OVERRIDE; 337 virtual bool supportsFocus() const; 338 virtual bool isMouseFocusable() const; 339 virtual bool rendererIsNeeded(const NodeRenderingContext&); 340 virtual RenderObject* createRenderer(RenderStyle*); 341 virtual bool childShouldCreateRenderer(const NodeRenderingContext&) const OVERRIDE; 342 virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; 343 virtual void removedFrom(ContainerNode*) OVERRIDE; 344 virtual void didRecalcStyle(StyleChange); 345 346 virtual void didBecomeFullscreenElement(); 347 virtual void willStopBeingFullscreenElement(); 348 349 // ActiveDOMObject functions. 350 virtual bool canSuspend() const; 351 virtual void suspend(ReasonForSuspension); 352 virtual void resume(); 353 virtual void stop(); 354 355 virtual void updateDisplayState() { } 356 357 void setReadyState(MediaPlayer::ReadyState); 358 void setNetworkState(MediaPlayer::NetworkState); 359 360 virtual void mediaPlayerNetworkStateChanged() OVERRIDE; 361 virtual void mediaPlayerReadyStateChanged() OVERRIDE; 362 virtual void mediaPlayerTimeChanged() OVERRIDE; 363 virtual void mediaPlayerDurationChanged() OVERRIDE; 364 virtual void mediaPlayerPlaybackStateChanged() OVERRIDE; 365 virtual void mediaPlayerRepaint() OVERRIDE; 366 virtual void mediaPlayerSizeChanged() OVERRIDE; 367 virtual void mediaPlayerEngineUpdated() OVERRIDE; 368 369 virtual void mediaPlayerKeyAdded(const String& keySystem, const String& sessionId) OVERRIDE; 370 virtual void mediaPlayerKeyError(const String& keySystem, const String& sessionId, MediaPlayerClient::MediaKeyErrorCode, unsigned short systemCode) OVERRIDE; 371 virtual void mediaPlayerKeyMessage(const String& keySystem, const String& sessionId, const unsigned char* message, unsigned messageLength, const KURL& defaultURL) OVERRIDE; 372 virtual bool mediaPlayerKeyNeeded(const String& keySystem, const String& sessionId, const unsigned char* initData, unsigned initDataLength) OVERRIDE; 373 374 #if ENABLE(ENCRYPTED_MEDIA_V2) 375 virtual bool mediaPlayerKeyNeeded(Uint8Array*) OVERRIDE; 376 #endif 377 378 virtual CORSMode mediaPlayerCORSMode() const OVERRIDE; 379 380 virtual void mediaPlayerScheduleLayerUpdate() OVERRIDE; 381 382 void loadTimerFired(Timer<HTMLMediaElement>*); 383 void progressEventTimerFired(Timer<HTMLMediaElement>*); 384 void playbackProgressTimerFired(Timer<HTMLMediaElement>*); 385 void startPlaybackProgressTimer(); 386 void startProgressEventTimer(); 387 void stopPeriodicTimers(); 388 389 void seek(double time, ExceptionState&); 390 void finishSeek(); 391 void checkIfSeekNeeded(); 392 void addPlayedRange(double start, double end); 393 394 void scheduleTimeupdateEvent(bool periodicEvent); 395 void scheduleEvent(const AtomicString& eventName); 396 397 // loading 398 void selectMediaResource(); 399 void loadResource(const KURL&, ContentType&, const String& keySystem); 400 void scheduleNextSourceChild(); 401 void loadNextSourceChild(); 402 void userCancelledLoad(); 403 void clearMediaPlayer(int flags); 404 bool havePotentialSourceChild(); 405 void noneSupported(); 406 void mediaEngineError(PassRefPtr<MediaError> err); 407 void cancelPendingEventsAndCallbacks(); 408 void waitForSourceChange(); 409 void prepareToPlay(); 410 411 KURL selectNextSourceChild(ContentType*, String* keySystem, InvalidURLAction); 412 413 void mediaLoadingFailed(MediaPlayer::NetworkState); 414 415 void updateActiveTextTrackCues(double); 416 HTMLTrackElement* showingTrackWithSameKind(HTMLTrackElement*) const; 417 418 void markCaptionAndSubtitleTracksAsUnconfigured(); 419 420 // These "internal" functions do not check user gesture restrictions. 421 void loadInternal(); 422 void playInternal(); 423 void pauseInternal(); 424 425 void prepareForLoad(); 426 void allowVideoRendering(); 427 428 void updateVolume(); 429 void updatePlayState(); 430 bool potentiallyPlaying() const; 431 bool endedPlayback() const; 432 bool stoppedDueToErrors() const; 433 bool pausedForUserInteraction() const; 434 bool couldPlayIfEnoughData() const; 435 436 double minTimeSeekable() const; 437 double maxTimeSeekable() const; 438 439 // Pauses playback without changing any states or generating events 440 void setPausedInternal(bool); 441 442 void setPlaybackRateInternal(double); 443 444 void setShouldDelayLoadEvent(bool); 445 void invalidateCachedTime(); 446 void refreshCachedTime() const; 447 448 bool hasMediaControls() const; 449 bool createMediaControls(); 450 void configureMediaControls(); 451 452 void prepareMediaFragmentURI(); 453 void applyMediaFragmentURI(); 454 455 virtual void* preDispatchEventHandler(Event*); 456 457 void changeNetworkStateFromLoadingToIdle(); 458 459 void removeBehaviorsRestrictionsAfterFirstUserGesture(); 460 461 void updateMediaController(); 462 bool isBlocked() const; 463 bool isBlockedOnMediaController() const; 464 bool hasCurrentSrc() const { return !m_currentSrc.isEmpty(); } 465 bool isAutoplaying() const { return m_autoplaying; } 466 467 Timer<HTMLMediaElement> m_loadTimer; 468 Timer<HTMLMediaElement> m_progressEventTimer; 469 Timer<HTMLMediaElement> m_playbackProgressTimer; 470 RefPtr<TimeRanges> m_playedTimeRanges; 471 OwnPtr<GenericEventQueue> m_asyncEventQueue; 472 473 double m_playbackRate; 474 double m_defaultPlaybackRate; 475 bool m_webkitPreservesPitch; 476 NetworkState m_networkState; 477 ReadyState m_readyState; 478 ReadyState m_readyStateMaximum; 479 KURL m_currentSrc; 480 481 RefPtr<MediaError> m_error; 482 483 double m_volume; 484 double m_lastSeekTime; 485 486 unsigned m_previousProgress; 487 double m_previousProgressTime; 488 489 // Cached duration to suppress duplicate events if duration unchanged. 490 double m_duration; 491 492 // The last time a timeupdate event was sent (wall clock). 493 double m_lastTimeUpdateEventWallTime; 494 495 // The last time a timeupdate event was sent in movie time. 496 double m_lastTimeUpdateEventMovieTime; 497 498 // Loading state. 499 enum LoadState { WaitingForSource, LoadingFromSrcAttr, LoadingFromSourceElement }; 500 LoadState m_loadState; 501 RefPtr<HTMLSourceElement> m_currentSourceNode; 502 RefPtr<Node> m_nextChildNodeToConsider; 503 504 OwnPtr<MediaPlayer> m_player; 505 506 BehaviorRestrictions m_restrictions; 507 508 MediaPlayer::Preload m_preload; 509 510 DisplayMode m_displayMode; 511 512 RefPtr<HTMLMediaSource> m_mediaSource; 513 514 mutable double m_cachedTime; 515 mutable double m_cachedTimeWallClockUpdateTime; 516 mutable double m_minimumWallClockTimeToCacheMediaTime; 517 518 double m_fragmentStartTime; 519 double m_fragmentEndTime; 520 521 typedef unsigned PendingActionFlags; 522 PendingActionFlags m_pendingActionFlags; 523 524 bool m_playing : 1; 525 bool m_shouldDelayLoadEvent : 1; 526 bool m_haveFiredLoadedData : 1; 527 bool m_inActiveDocument : 1; 528 bool m_autoplaying : 1; 529 bool m_muted : 1; 530 bool m_paused : 1; 531 bool m_seeking : 1; 532 533 // data has not been loaded since sending a "stalled" event 534 bool m_sentStalledEvent : 1; 535 536 // time has not changed since sending an "ended" event 537 bool m_sentEndEvent : 1; 538 539 bool m_pausedInternal : 1; 540 541 // Not all media engines provide enough information about a file to be able to 542 // support progress events so setting m_sendProgressEvents disables them 543 bool m_sendProgressEvents : 1; 544 545 bool m_closedCaptionsVisible : 1; 546 547 bool m_dispatchingCanPlayEvent : 1; 548 bool m_loadInitiatedByUserGesture : 1; 549 bool m_completelyLoaded : 1; 550 bool m_havePreparedToPlay : 1; 551 bool m_parsingInProgress : 1; 552 553 bool m_tracksAreReady : 1; 554 bool m_haveVisibleTextTrack : 1; 555 bool m_processingPreferenceChange : 1; 556 double m_lastTextTrackUpdateTime; 557 558 RefPtr<TextTrackList> m_textTracks; 559 Vector<RefPtr<TextTrack> > m_textTracksWhenResourceSelectionBegan; 560 561 CueIntervalTree m_cueTree; 562 563 CueList m_currentlyActiveCues; 564 int m_ignoreTrackDisplayUpdate; 565 566 #if ENABLE(WEB_AUDIO) 567 // This is a weak reference, since m_audioSourceNode holds a reference to us. 568 // The value is set just after the MediaElementAudioSourceNode is created. 569 // The value is cleared in MediaElementAudioSourceNode::~MediaElementAudioSourceNode(). 570 MediaElementAudioSourceNode* m_audioSourceNode; 571 #endif 572 573 String m_mediaGroup; 574 friend class MediaController; 575 RefPtr<MediaController> m_mediaController; 576 577 friend class TrackDisplayUpdateScope; 578 579 #if ENABLE(ENCRYPTED_MEDIA_V2) 580 RefPtr<MediaKeys> m_mediaKeys; 581 #endif 582 }; 583 584 #ifndef NDEBUG 585 // Template specializations required by PodIntervalTree in debug mode. 586 template <> 587 struct ValueToString<double> { 588 static String string(const double value) 589 { 590 return String::number(value); 591 } 592 }; 593 594 template <> 595 struct ValueToString<TextTrackCue*> { 596 static String string(TextTrackCue* const& cue) 597 { 598 return String::format("%p id=%s interval=%f-->%f cue=%s)", cue, cue->id().utf8().data(), cue->startTime(), cue->endTime(), cue->text().utf8().data()); 599 } 600 }; 601 #endif 602 603 inline bool isMediaElement(Node* node) 604 { 605 return node && node->isElementNode() && toElement(node)->isMediaElement(); 606 } 607 608 inline HTMLMediaElement* toMediaElement(Node* node) 609 { 610 ASSERT_WITH_SECURITY_IMPLICATION(!node || isMediaElement(node)); 611 return static_cast<HTMLMediaElement*>(node); 612 } 613 614 } //namespace 615 616 #endif 617