OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights
reserved. | 2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights
reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 19 matching lines...) Expand all Loading... |
30 #include "bindings/core/v8/ScriptController.h" | 30 #include "bindings/core/v8/ScriptController.h" |
31 #include "bindings/core/v8/ScriptEventListener.h" | 31 #include "bindings/core/v8/ScriptEventListener.h" |
32 #include "core/HTMLNames.h" | 32 #include "core/HTMLNames.h" |
33 #include "core/css/MediaList.h" | 33 #include "core/css/MediaList.h" |
34 #include "core/dom/Attribute.h" | 34 #include "core/dom/Attribute.h" |
35 #include "core/dom/ElementTraversal.h" | 35 #include "core/dom/ElementTraversal.h" |
36 #include "core/dom/ExceptionCode.h" | 36 #include "core/dom/ExceptionCode.h" |
37 #include "core/dom/Fullscreen.h" | 37 #include "core/dom/Fullscreen.h" |
38 #include "core/dom/shadow/ShadowRoot.h" | 38 #include "core/dom/shadow/ShadowRoot.h" |
39 #include "core/events/Event.h" | 39 #include "core/events/Event.h" |
| 40 #include "core/frame/FrameView.h" |
40 #include "core/frame/LocalFrame.h" | 41 #include "core/frame/LocalFrame.h" |
41 #include "core/frame/Settings.h" | 42 #include "core/frame/Settings.h" |
42 #include "core/frame/UseCounter.h" | 43 #include "core/frame/UseCounter.h" |
43 #include "core/frame/csp/ContentSecurityPolicy.h" | 44 #include "core/frame/csp/ContentSecurityPolicy.h" |
44 #include "core/html/HTMLMediaSource.h" | 45 #include "core/html/HTMLMediaSource.h" |
45 #include "core/html/HTMLSourceElement.h" | 46 #include "core/html/HTMLSourceElement.h" |
46 #include "core/html/HTMLTrackElement.h" | 47 #include "core/html/HTMLTrackElement.h" |
47 #include "core/html/MediaError.h" | 48 #include "core/html/MediaError.h" |
48 #include "core/html/MediaFragmentURIParser.h" | 49 #include "core/html/MediaFragmentURIParser.h" |
49 #include "core/html/TimeRanges.h" | 50 #include "core/html/TimeRanges.h" |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 if (contentMIMEType != "application/octet-stream" || contentTypeCodecs.isEmp
ty()) { | 247 if (contentMIMEType != "application/octet-stream" || contentTypeCodecs.isEmp
ty()) { |
247 WebMimeRegistry::SupportsType supported = Platform::current()->mimeRegis
try()->supportsMediaMIMEType(contentMIMEType, contentTypeCodecs); | 248 WebMimeRegistry::SupportsType supported = Platform::current()->mimeRegis
try()->supportsMediaMIMEType(contentMIMEType, contentTypeCodecs); |
248 return supported > WebMimeRegistry::IsNotSupported; | 249 return supported > WebMimeRegistry::IsNotSupported; |
249 } | 250 } |
250 | 251 |
251 return false; | 252 return false; |
252 } | 253 } |
253 | 254 |
254 } // anonymous namespace | 255 } // anonymous namespace |
255 | 256 |
| 257 class HTMLMediaElement::AutoplayHelperClientImpl : |
| 258 public AutoplayExperimentHelper::Client { |
| 259 |
| 260 public: |
| 261 static PassOwnPtrWillBeRawPtr<AutoplayHelperClientImpl> create(HTMLMediaElem
ent* element) |
| 262 { |
| 263 return adoptPtrWillBeNoop(new AutoplayHelperClientImpl(element)); |
| 264 } |
| 265 |
| 266 virtual ~AutoplayHelperClientImpl(); |
| 267 |
| 268 using RecordMetricsBehavior = AutoplayExperimentHelper::Client::RecordMetric
sBehavior; |
| 269 |
| 270 double currentTime() const override { return m_element->currentTime(); } |
| 271 double duration() const override { return m_element->duration(); } |
| 272 bool paused() const override { return m_element->paused(); } |
| 273 bool muted() const override { return m_element->muted(); } |
| 274 void setMuted(bool muted) override { m_element->setMuted(muted); } |
| 275 void playInternal() override { m_element->playInternal(); } |
| 276 bool isUserGestureRequiredForPlay() const override { return m_element->isUse
rGestureRequiredForPlay(); } |
| 277 void removeUserGestureRequirement() override { m_element->removeUserGestureR
equirement(); } |
| 278 void recordAutoplayMetric(AutoplayMetrics metric) override { m_element->reco
rdAutoplayMetric(metric); } |
| 279 bool shouldAutoplay(RecordMetricsBehavior behavior) override { return m_elem
ent->shouldAutoplay(behavior); } |
| 280 bool isHTMLVideoElement() const override { return m_element->isHTMLVideoElem
ent(); } |
| 281 bool isHTMLAudioElement() const override { return m_element->isHTMLAudioElem
ent(); } |
| 282 |
| 283 // Document |
| 284 bool isLegacyViewportType() override; |
| 285 PageVisibilityState pageVisibilityState() const override; |
| 286 String autoplayExperimentMode() const override; |
| 287 |
| 288 // LayoutObject |
| 289 void setRequestPositionUpdates(bool) override; |
| 290 IntRect absoluteBoundingBoxRect() const override; |
| 291 |
| 292 DEFINE_INLINE_VIRTUAL_TRACE() { |
| 293 visitor->trace(m_element); |
| 294 Client::trace(visitor); |
| 295 } |
| 296 |
| 297 private: |
| 298 AutoplayHelperClientImpl(HTMLMediaElement* element) : m_element(element) {} |
| 299 |
| 300 RawPtrWillBeMember<HTMLMediaElement> m_element; |
| 301 }; |
| 302 |
| 303 |
256 void HTMLMediaElement::recordAutoplayMetric(AutoplayMetrics metric) | 304 void HTMLMediaElement::recordAutoplayMetric(AutoplayMetrics metric) |
257 { | 305 { |
258 DEFINE_STATIC_LOCAL(EnumerationHistogram, autoplayHistogram, ("Blink.MediaEl
ement.Autoplay", NumberOfAutoplayMetrics)); | 306 DEFINE_STATIC_LOCAL(EnumerationHistogram, autoplayHistogram, ("Blink.MediaEl
ement.Autoplay", NumberOfAutoplayMetrics)); |
259 autoplayHistogram.count(metric); | 307 autoplayHistogram.count(metric); |
260 } | 308 } |
261 | 309 |
262 WebMimeRegistry::SupportsType HTMLMediaElement::supportsType(const ContentType&
contentType) | 310 WebMimeRegistry::SupportsType HTMLMediaElement::supportsType(const ContentType&
contentType) |
263 { | 311 { |
264 DEFINE_STATIC_LOCAL(const String, codecs, ("codecs")); | 312 DEFINE_STATIC_LOCAL(const String, codecs, ("codecs")); |
265 | 313 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 , m_seeking(false) | 382 , m_seeking(false) |
335 , m_sentStalledEvent(false) | 383 , m_sentStalledEvent(false) |
336 , m_sentEndEvent(false) | 384 , m_sentEndEvent(false) |
337 , m_closedCaptionsVisible(false) | 385 , m_closedCaptionsVisible(false) |
338 , m_havePreparedToPlay(false) | 386 , m_havePreparedToPlay(false) |
339 , m_tracksAreReady(true) | 387 , m_tracksAreReady(true) |
340 , m_processingPreferenceChange(false) | 388 , m_processingPreferenceChange(false) |
341 , m_remoteRoutesAvailable(false) | 389 , m_remoteRoutesAvailable(false) |
342 , m_playingRemotely(false) | 390 , m_playingRemotely(false) |
343 , m_isFinalizing(false) | 391 , m_isFinalizing(false) |
344 , m_initialPlayWithoutUserGesture(false) | |
345 , m_autoplayMediaCounted(false) | |
346 , m_inOverlayFullscreenVideo(false) | 392 , m_inOverlayFullscreenVideo(false) |
347 , m_audioTracks(AudioTrackList::create(*this)) | 393 , m_audioTracks(AudioTrackList::create(*this)) |
348 , m_videoTracks(VideoTrackList::create(*this)) | 394 , m_videoTracks(VideoTrackList::create(*this)) |
349 , m_textTracks(nullptr) | 395 , m_textTracks(nullptr) |
350 , m_audioSourceNode(nullptr) | 396 , m_audioSourceNode(nullptr) |
351 , m_autoplayHelper(*this) | 397 , m_autoplayHelperClient(AutoplayHelperClientImpl::create(this)) |
| 398 , m_autoplayHelper(AutoplayExperimentHelper::create(m_autoplayHelperClient)) |
352 { | 399 { |
353 #if ENABLE(OILPAN) | 400 #if ENABLE(OILPAN) |
354 ThreadState::current()->registerPreFinalizer(this); | 401 ThreadState::current()->registerPreFinalizer(this); |
355 #endif | 402 #endif |
356 ASSERT(RuntimeEnabledFeatures::mediaEnabled()); | 403 ASSERT(RuntimeEnabledFeatures::mediaEnabled()); |
357 | 404 |
358 WTF_LOG(Media, "HTMLMediaElement::HTMLMediaElement(%p)", this); | 405 WTF_LOG(Media, "HTMLMediaElement::HTMLMediaElement(%p)", this); |
359 | 406 |
360 if (document.settings() && document.settings()->mediaPlaybackRequiresUserGes
ture()) | 407 if (document.settings() && document.settings()->mediaPlaybackRequiresUserGes
ture()) |
361 m_userGestureRequiredForPlay = true; | 408 m_userGestureRequiredForPlay = true; |
362 | 409 |
363 setHasCustomStyleCallbacks(); | 410 setHasCustomStyleCallbacks(); |
364 addElementToDocumentMap(this, &document); | 411 addElementToDocumentMap(this, &document); |
365 | 412 |
366 UseCounter::count(document, UseCounter::HTMLMediaElement); | 413 UseCounter::count(document, UseCounter::HTMLMediaElement); |
367 } | 414 } |
368 | 415 |
369 HTMLMediaElement::~HTMLMediaElement() | 416 HTMLMediaElement::~HTMLMediaElement() |
370 { | 417 { |
371 WTF_LOG(Media, "HTMLMediaElement::~HTMLMediaElement(%p)", this); | 418 WTF_LOG(Media, "HTMLMediaElement::~HTMLMediaElement(%p)", this); |
372 | 419 |
373 #if !ENABLE(OILPAN) | 420 #if !ENABLE(OILPAN) |
| 421 // Destruction of the autoplay helper requires the client, so be sure that |
| 422 // this happens before the client is destructed. |
| 423 if (m_autoplayHelper) |
| 424 m_autoplayHelper.clear(); |
| 425 |
374 // HTMLMediaElement and m_asyncEventQueue always become unreachable | 426 // HTMLMediaElement and m_asyncEventQueue always become unreachable |
375 // together. So HTMLMediaElement and m_asyncEventQueue are destructed in | 427 // together. So HTMLMediaElement and m_asyncEventQueue are destructed in |
376 // the same GC. We don't need to close it explicitly in Oilpan. | 428 // the same GC. We don't need to close it explicitly in Oilpan. |
377 m_asyncEventQueue->close(); | 429 m_asyncEventQueue->close(); |
378 | 430 |
379 setShouldDelayLoadEvent(false); | 431 setShouldDelayLoadEvent(false); |
380 | 432 |
381 if (m_textTracks) | 433 if (m_textTracks) |
382 m_textTracks->clearOwner(); | 434 m_textTracks->clearOwner(); |
383 m_audioTracks->shutdown(); | 435 m_audioTracks->shutdown(); |
(...skipping 19 matching lines...) Expand all Loading... |
403 // m_audioSourceNode is explicitly cleared by AudioNode::dispose(). | 455 // m_audioSourceNode is explicitly cleared by AudioNode::dispose(). |
404 // Since AudioNode::dispose() is guaranteed to be always called before | 456 // Since AudioNode::dispose() is guaranteed to be always called before |
405 // the AudioNode is destructed, m_audioSourceNode is explicitly cleared | 457 // the AudioNode is destructed, m_audioSourceNode is explicitly cleared |
406 // even if the AudioNode and the HTMLMediaElement die together. | 458 // even if the AudioNode and the HTMLMediaElement die together. |
407 ASSERT(!m_audioSourceNode); | 459 ASSERT(!m_audioSourceNode); |
408 } | 460 } |
409 | 461 |
410 #if ENABLE(OILPAN) | 462 #if ENABLE(OILPAN) |
411 void HTMLMediaElement::dispose() | 463 void HTMLMediaElement::dispose() |
412 { | 464 { |
| 465 // This must happen before we're destructed. |
| 466 if (m_autoplayHelper) |
| 467 m_autoplayHelper->dispose(); |
| 468 |
413 // If the HTMLMediaElement dies with the Document we are not | 469 // If the HTMLMediaElement dies with the Document we are not |
414 // allowed to touch the Document to adjust delay load event counts | 470 // allowed to touch the Document to adjust delay load event counts |
415 // from the destructor, as the Document could have been already | 471 // from the destructor, as the Document could have been already |
416 // destructed. | 472 // destructed. |
417 // | 473 // |
418 // Work around that restriction by accessing the Document from | 474 // Work around that restriction by accessing the Document from |
419 // a prefinalizer action instead, updating its delayed load count. | 475 // a prefinalizer action instead, updating its delayed load count. |
420 // If needed - if the Document has been detached and informed its | 476 // If needed - if the Document has been detached and informed its |
421 // ContextLifecycleObservers (which HTMLMediaElement is) that | 477 // ContextLifecycleObservers (which HTMLMediaElement is) that |
422 // it is being destroyed, the connection to the Document will | 478 // it is being destroyed, the connection to the Document will |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
663 case WebMimeRegistry::IsSupported: | 719 case WebMimeRegistry::IsSupported: |
664 canPlay = "probably"; | 720 canPlay = "probably"; |
665 break; | 721 break; |
666 } | 722 } |
667 | 723 |
668 WTF_LOG(Media, "HTMLMediaElement::canPlayType(%p, %s) -> %s", this, mimeType
.utf8().data(), canPlay.utf8().data()); | 724 WTF_LOG(Media, "HTMLMediaElement::canPlayType(%p, %s) -> %s", this, mimeType
.utf8().data(), canPlay.utf8().data()); |
669 | 725 |
670 return canPlay; | 726 return canPlay; |
671 } | 727 } |
672 | 728 |
673 void HTMLMediaElement::recordMetricsIfPausing() | |
674 { | |
675 // If not playing, then nothing to record. | |
676 // TODO(liberato): test metrics. this was m_paused. | |
677 if (m_paused) | |
678 return; | |
679 | |
680 const bool bailout = isBailout(); | |
681 | |
682 // Record that play was paused. We don't care if it was autoplay, | |
683 // play(), or the user manually started it. | |
684 recordAutoplayMetric(AnyPlaybackPaused); | |
685 if (bailout) | |
686 recordAutoplayMetric(AnyPlaybackBailout); | |
687 | |
688 // If this was a gestureless play, then record that separately. | |
689 // These cover attr and play() gestureless starts. | |
690 if (m_initialPlayWithoutUserGesture) { | |
691 m_initialPlayWithoutUserGesture = false; | |
692 | |
693 recordAutoplayMetric(AutoplayPaused); | |
694 | |
695 if (bailout) | |
696 recordAutoplayMetric(AutoplayBailout); | |
697 } | |
698 } | |
699 | |
700 void HTMLMediaElement::load() | 729 void HTMLMediaElement::load() |
701 { | 730 { |
702 WTF_LOG(Media, "HTMLMediaElement::load(%p)", this); | 731 WTF_LOG(Media, "HTMLMediaElement::load(%p)", this); |
703 | 732 |
704 recordMetricsIfPausing(); | 733 m_autoplayHelper->loadMethodCalled(); |
705 | |
706 if (UserGestureIndicator::processingUserGesture() && m_userGestureRequiredFo
rPlay) { | |
707 recordAutoplayMetric(AutoplayEnabledThroughLoad); | |
708 m_userGestureRequiredForPlay = false; | |
709 // While usergesture-initiated load()s technically count as autoplayed, | |
710 // they don't feel like such to the users and hence we don't want to | |
711 // count them for the purposes of metrics. | |
712 m_autoplayMediaCounted = true; | |
713 } | |
714 | 734 |
715 prepareForLoad(); | 735 prepareForLoad(); |
716 loadInternal(); | 736 loadInternal(); |
717 prepareToPlay(); | 737 prepareToPlay(); |
718 } | 738 } |
719 | 739 |
720 void HTMLMediaElement::prepareForLoad() | 740 void HTMLMediaElement::prepareForLoad() |
721 { | 741 { |
722 WTF_LOG(Media, "HTMLMediaElement::prepareForLoad(%p)", this); | 742 WTF_LOG(Media, "HTMLMediaElement::prepareForLoad(%p)", this); |
723 | 743 |
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
924 | 944 |
925 LocalFrame* frame = document().frame(); | 945 LocalFrame* frame = document().frame(); |
926 if (!frame) { | 946 if (!frame) { |
927 mediaLoadingFailed(WebMediaPlayer::NetworkStateFormatError); | 947 mediaLoadingFailed(WebMediaPlayer::NetworkStateFormatError); |
928 return; | 948 return; |
929 } | 949 } |
930 | 950 |
931 // The resource fetch algorithm | 951 // The resource fetch algorithm |
932 setNetworkState(NETWORK_LOADING); | 952 setNetworkState(NETWORK_LOADING); |
933 | 953 |
| 954 m_autoplayHelper->loadingStarted(); |
| 955 |
934 // Set m_currentSrc *before* changing to the cache url, the fact that we are
loading from the app | 956 // Set m_currentSrc *before* changing to the cache url, the fact that we are
loading from the app |
935 // cache is an internal detail not exposed through the media element API. | 957 // cache is an internal detail not exposed through the media element API. |
936 m_currentSrc = url; | 958 m_currentSrc = url; |
937 | 959 |
938 if (m_audioSourceNode) | 960 if (m_audioSourceNode) |
939 m_audioSourceNode->onCurrentSrcChanged(m_currentSrc); | 961 m_audioSourceNode->onCurrentSrcChanged(m_currentSrc); |
940 | 962 |
941 WTF_LOG(Media, "HTMLMediaElement::loadResource(%p) - m_currentSrc -> %s", th
is, urlForLoggingMedia(m_currentSrc).utf8().data()); | 963 WTF_LOG(Media, "HTMLMediaElement::loadResource(%p) - m_currentSrc -> %s", th
is, urlForLoggingMedia(m_currentSrc).utf8().data()); |
942 | 964 |
943 startProgressEventTimer(); | 965 startProgressEventTimer(); |
944 | 966 |
945 // Reset display mode to force a recalculation of what to show because we ar
e resetting the player. | 967 // Reset display mode to force a recalculation of what to show because we ar
e resetting the player. |
946 setDisplayMode(Unknown); | 968 setDisplayMode(Unknown); |
947 | 969 |
948 setPlayerPreload(); | 970 setPlayerPreload(); |
949 | 971 |
950 if (fastHasAttribute(mutedAttr)) | 972 if (fastHasAttribute(mutedAttr)) |
951 m_muted = true; | 973 m_muted = true; |
952 updateVolume(); | 974 updateVolume(); |
953 | 975 |
954 ASSERT(!m_mediaSource); | 976 ASSERT(!m_mediaSource); |
955 | 977 |
956 bool attemptLoad = true; | 978 bool attemptLoad = true; |
957 | 979 |
958 if (url.protocolIs(mediaSourceBlobProtocol)) { | 980 if (url.protocolIs(mediaSourceBlobProtocol)) { |
959 if (isMediaStreamURL(url.string())) { | 981 if (isMediaStreamURL(url.string())) { |
960 m_userGestureRequiredForPlay = false; | 982 m_autoplayHelper->removeUserGestureRequirement(GesturelessPlaybackEn
abledByStream); |
961 } else { | 983 } else { |
962 m_mediaSource = HTMLMediaSource::lookup(url.string()); | 984 m_mediaSource = HTMLMediaSource::lookup(url.string()); |
963 | 985 |
964 if (m_mediaSource) { | 986 if (m_mediaSource) { |
965 if (!m_mediaSource->attachToElement(this)) { | 987 if (!m_mediaSource->attachToElement(this)) { |
966 // Forget our reference to the MediaSource, so we leave it a
lone | 988 // Forget our reference to the MediaSource, so we leave it a
lone |
967 // while processing remainder of load failure. | 989 // while processing remainder of load failure. |
968 m_mediaSource = nullptr; | 990 m_mediaSource = nullptr; |
969 attemptLoad = false; | 991 attemptLoad = false; |
970 } | 992 } |
(...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1536 if (oldState <= HAVE_CURRENT_DATA) { | 1558 if (oldState <= HAVE_CURRENT_DATA) { |
1537 scheduleEvent(EventTypeNames::canplay); | 1559 scheduleEvent(EventTypeNames::canplay); |
1538 if (isPotentiallyPlaying) | 1560 if (isPotentiallyPlaying) |
1539 scheduleEvent(EventTypeNames::playing); | 1561 scheduleEvent(EventTypeNames::playing); |
1540 } | 1562 } |
1541 | 1563 |
1542 // Check for autoplay, and record metrics about it if needed. | 1564 // Check for autoplay, and record metrics about it if needed. |
1543 if (shouldAutoplay(RecordMetricsBehavior::DoRecord)) { | 1565 if (shouldAutoplay(RecordMetricsBehavior::DoRecord)) { |
1544 // If the autoplay experiment says that it's okay to play now, | 1566 // If the autoplay experiment says that it's okay to play now, |
1545 // then don't require a user gesture. | 1567 // then don't require a user gesture. |
1546 m_autoplayHelper.becameReadyToPlay(); | 1568 m_autoplayHelper->becameReadyToPlay(); |
1547 | 1569 |
1548 if (!m_userGestureRequiredForPlay) { | 1570 if (!m_userGestureRequiredForPlay) { |
1549 m_paused = false; | 1571 m_paused = false; |
1550 invalidateCachedTime(); | 1572 invalidateCachedTime(); |
1551 scheduleEvent(EventTypeNames::play); | 1573 scheduleEvent(EventTypeNames::play); |
1552 scheduleEvent(EventTypeNames::playing); | 1574 scheduleEvent(EventTypeNames::playing); |
1553 m_autoplaying = false; | 1575 m_autoplaying = false; |
1554 } | 1576 } |
1555 } | 1577 } |
1556 | 1578 |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1675 | 1697 |
1676 m_lastSeekTime = time; | 1698 m_lastSeekTime = time; |
1677 m_sentEndEvent = false; | 1699 m_sentEndEvent = false; |
1678 | 1700 |
1679 // 10 - Queue a task to fire a simple event named seeking at the element. | 1701 // 10 - Queue a task to fire a simple event named seeking at the element. |
1680 scheduleEvent(EventTypeNames::seeking); | 1702 scheduleEvent(EventTypeNames::seeking); |
1681 | 1703 |
1682 // 11 - Set the current playback position to the given new playback position
. | 1704 // 11 - Set the current playback position to the given new playback position
. |
1683 webMediaPlayer()->seek(time); | 1705 webMediaPlayer()->seek(time); |
1684 | 1706 |
1685 m_initialPlayWithoutUserGesture = false; | |
1686 | |
1687 // 14-17 are handled, if necessary, when the engine signals a readystate cha
nge or otherwise | 1707 // 14-17 are handled, if necessary, when the engine signals a readystate cha
nge or otherwise |
1688 // satisfies seek completion and signals a time change. | 1708 // satisfies seek completion and signals a time change. |
1689 } | 1709 } |
1690 | 1710 |
1691 void HTMLMediaElement::finishSeek() | 1711 void HTMLMediaElement::finishSeek() |
1692 { | 1712 { |
1693 WTF_LOG(Media, "HTMLMediaElement::finishSeek(%p)", this); | 1713 WTF_LOG(Media, "HTMLMediaElement::finishSeek(%p)", this); |
1694 | 1714 |
1695 // 14 - Set the seeking IDL attribute to false. | 1715 // 14 - Set the seeking IDL attribute to false. |
1696 m_seeking = false; | 1716 m_seeking = false; |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1858 } | 1878 } |
1859 | 1879 |
1860 bool HTMLMediaElement::autoplay() const | 1880 bool HTMLMediaElement::autoplay() const |
1861 { | 1881 { |
1862 return fastHasAttribute(autoplayAttr); | 1882 return fastHasAttribute(autoplayAttr); |
1863 } | 1883 } |
1864 | 1884 |
1865 bool HTMLMediaElement::shouldAutoplay(const RecordMetricsBehavior recordMetrics) | 1885 bool HTMLMediaElement::shouldAutoplay(const RecordMetricsBehavior recordMetrics) |
1866 { | 1886 { |
1867 if (m_autoplaying && m_paused && autoplay()) { | 1887 if (m_autoplaying && m_paused && autoplay()) { |
1868 if (recordMetrics == RecordMetricsBehavior::DoRecord) | |
1869 autoplayMediaEncountered(); | |
1870 | |
1871 if (document().isSandboxed(SandboxAutomaticFeatures)) { | 1888 if (document().isSandboxed(SandboxAutomaticFeatures)) { |
1872 if (recordMetrics == RecordMetricsBehavior::DoRecord) | 1889 if (recordMetrics == RecordMetricsBehavior::DoRecord) |
1873 recordAutoplayMetric(AutoplayDisabledBySandbox); | 1890 m_autoplayHelper->recordSandboxFailure(); |
1874 return false; | 1891 return false; |
1875 } | 1892 } |
1876 | 1893 |
1877 return true; | 1894 return true; |
1878 } | 1895 } |
1879 | 1896 |
1880 return false; | 1897 return false; |
1881 } | 1898 } |
1882 | 1899 |
1883 String HTMLMediaElement::preload() const | 1900 String HTMLMediaElement::preload() const |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1938 | 1955 |
1939 WebMediaPlayer::Preload HTMLMediaElement::effectivePreloadType() const | 1956 WebMediaPlayer::Preload HTMLMediaElement::effectivePreloadType() const |
1940 { | 1957 { |
1941 return autoplay() ? WebMediaPlayer::PreloadAuto : preloadType(); | 1958 return autoplay() ? WebMediaPlayer::PreloadAuto : preloadType(); |
1942 } | 1959 } |
1943 | 1960 |
1944 void HTMLMediaElement::play() | 1961 void HTMLMediaElement::play() |
1945 { | 1962 { |
1946 WTF_LOG(Media, "HTMLMediaElement::play(%p)", this); | 1963 WTF_LOG(Media, "HTMLMediaElement::play(%p)", this); |
1947 | 1964 |
1948 m_autoplayHelper.playMethodCalled(); | 1965 m_autoplayHelper->playMethodCalled(); |
1949 | 1966 |
1950 if (!UserGestureIndicator::processingUserGesture()) { | 1967 if (!UserGestureIndicator::processingUserGesture()) { |
1951 autoplayMediaEncountered(); | |
1952 | |
1953 if (m_userGestureRequiredForPlay) { | 1968 if (m_userGestureRequiredForPlay) { |
1954 recordAutoplayMetric(PlayMethodFailed); | 1969 recordAutoplayMetric(PlayMethodFailed); |
1955 String message = ExceptionMessages::failedToExecute("play", "HTMLMed
iaElement", "API can only be initiated by a user gesture."); | 1970 String message = ExceptionMessages::failedToExecute("play", "HTMLMed
iaElement", "API can only be initiated by a user gesture."); |
1956 document().addConsoleMessage(ConsoleMessage::create(JSMessageSource,
WarningMessageLevel, message)); | 1971 document().addConsoleMessage(ConsoleMessage::create(JSMessageSource,
WarningMessageLevel, message)); |
1957 return; | 1972 return; |
1958 } | 1973 } |
1959 } else if (m_userGestureRequiredForPlay) { | 1974 } else { |
1960 if (m_autoplayMediaCounted) | 1975 // We ask the helper to remove the gesture requirement for us, so that |
1961 recordAutoplayMetric(AutoplayManualStart); | 1976 // it can record the reason. |
1962 m_userGestureRequiredForPlay = false; | 1977 m_autoplayHelper->removeUserGestureRequirement(GesturelessPlaybackEnable
dByPlayMethod); |
1963 } | 1978 } |
1964 | 1979 |
1965 playInternal(); | 1980 playInternal(); |
1966 } | 1981 } |
1967 | 1982 |
1968 void HTMLMediaElement::playInternal() | 1983 void HTMLMediaElement::playInternal() |
1969 { | 1984 { |
1970 WTF_LOG(Media, "HTMLMediaElement::playInternal(%p)", this); | 1985 WTF_LOG(Media, "HTMLMediaElement::playInternal(%p)", this); |
1971 | 1986 |
1972 // Always return the buffering strategy to normal when not paused, | 1987 // Always return the buffering strategy to normal when not paused, |
(...skipping 20 matching lines...) Expand all Loading... |
1993 if (m_readyState <= HAVE_CURRENT_DATA) | 2008 if (m_readyState <= HAVE_CURRENT_DATA) |
1994 scheduleEvent(EventTypeNames::waiting); | 2009 scheduleEvent(EventTypeNames::waiting); |
1995 else if (m_readyState >= HAVE_FUTURE_DATA) | 2010 else if (m_readyState >= HAVE_FUTURE_DATA) |
1996 scheduleEvent(EventTypeNames::playing); | 2011 scheduleEvent(EventTypeNames::playing); |
1997 } | 2012 } |
1998 m_autoplaying = false; | 2013 m_autoplaying = false; |
1999 | 2014 |
2000 updatePlayState(); | 2015 updatePlayState(); |
2001 } | 2016 } |
2002 | 2017 |
2003 void HTMLMediaElement::autoplayMediaEncountered() | |
2004 { | |
2005 if (!m_autoplayMediaCounted) { | |
2006 m_autoplayMediaCounted = true; | |
2007 recordAutoplayMetric(AutoplayMediaFound); | |
2008 | |
2009 if (!m_userGestureRequiredForPlay) | |
2010 m_initialPlayWithoutUserGesture = true; | |
2011 } | |
2012 } | |
2013 | |
2014 bool HTMLMediaElement::isBailout() const | |
2015 { | |
2016 // We count the user as having bailed-out on the video if they watched | |
2017 // less than one minute and less than 50% of it. | |
2018 const double playedTime = currentTime(); | |
2019 const double progress = playedTime / duration(); | |
2020 return (playedTime < 60) && (progress < 0.5); | |
2021 } | |
2022 | |
2023 void HTMLMediaElement::pause() | 2018 void HTMLMediaElement::pause() |
2024 { | 2019 { |
2025 WTF_LOG(Media, "HTMLMediaElement::pause(%p)", this); | 2020 WTF_LOG(Media, "HTMLMediaElement::pause(%p)", this); |
2026 | 2021 |
2027 // Only buffer aggressively on a user-initiated pause. Other types of pauses | 2022 // Only buffer aggressively on a user-initiated pause. Other types of pauses |
2028 // (which go directly to pauseInternal()) should not cause this behavior. | 2023 // (which go directly to pauseInternal()) should not cause this behavior. |
2029 if (webMediaPlayer() && UserGestureIndicator::processingUserGesture()) | 2024 if (webMediaPlayer() && UserGestureIndicator::processingUserGesture()) |
2030 webMediaPlayer()->setBufferingStrategy(WebMediaPlayer::BufferingStrategy
::Aggressive); | 2025 webMediaPlayer()->setBufferingStrategy(WebMediaPlayer::BufferingStrategy
::Aggressive); |
2031 | 2026 |
2032 pauseInternal(); | 2027 pauseInternal(); |
2033 } | 2028 } |
2034 | 2029 |
2035 void HTMLMediaElement::pauseInternal() | 2030 void HTMLMediaElement::pauseInternal() |
2036 { | 2031 { |
2037 WTF_LOG(Media, "HTMLMediaElement::pauseInternal(%p)", this); | 2032 WTF_LOG(Media, "HTMLMediaElement::pauseInternal(%p)", this); |
2038 | 2033 |
2039 if (m_networkState == NETWORK_EMPTY) | 2034 if (m_networkState == NETWORK_EMPTY) |
2040 scheduleDelayedAction(LoadMediaResource); | 2035 scheduleDelayedAction(LoadMediaResource); |
2041 | 2036 |
2042 m_autoplayHelper.pauseMethodCalled(); | 2037 m_autoplayHelper->pauseMethodCalled(); |
2043 | 2038 |
2044 m_autoplaying = false; | 2039 m_autoplaying = false; |
2045 | 2040 |
2046 if (!m_paused) { | 2041 if (!m_paused) { |
2047 recordMetricsIfPausing(); | |
2048 | |
2049 m_paused = true; | 2042 m_paused = true; |
2050 scheduleTimeupdateEvent(false); | 2043 scheduleTimeupdateEvent(false); |
2051 scheduleEvent(EventTypeNames::pause); | 2044 scheduleEvent(EventTypeNames::pause); |
2052 } | 2045 } |
2053 | 2046 |
2054 updatePlayState(); | 2047 updatePlayState(); |
2055 } | 2048 } |
2056 | 2049 |
2057 void HTMLMediaElement::requestRemotePlayback() | 2050 void HTMLMediaElement::requestRemotePlayback() |
2058 { | 2051 { |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2143 | 2136 |
2144 void HTMLMediaElement::setMuted(bool muted) | 2137 void HTMLMediaElement::setMuted(bool muted) |
2145 { | 2138 { |
2146 WTF_LOG(Media, "HTMLMediaElement::setMuted(%p, %s)", this, boolString(muted)
); | 2139 WTF_LOG(Media, "HTMLMediaElement::setMuted(%p, %s)", this, boolString(muted)
); |
2147 | 2140 |
2148 if (m_muted == muted) | 2141 if (m_muted == muted) |
2149 return; | 2142 return; |
2150 | 2143 |
2151 m_muted = muted; | 2144 m_muted = muted; |
2152 | 2145 |
2153 m_autoplayHelper.mutedChanged(); | 2146 m_autoplayHelper->mutedChanged(); |
2154 | 2147 |
2155 updateVolume(); | 2148 updateVolume(); |
2156 | 2149 |
2157 scheduleEvent(EventTypeNames::volumechange); | 2150 scheduleEvent(EventTypeNames::volumechange); |
2158 } | 2151 } |
2159 | 2152 |
2160 void HTMLMediaElement::updateVolume() | 2153 void HTMLMediaElement::updateVolume() |
2161 { | 2154 { |
2162 if (webMediaPlayer()) | 2155 if (webMediaPlayer()) |
2163 webMediaPlayer()->setVolume(effectiveMediaVolume()); | 2156 webMediaPlayer()->setVolume(effectiveMediaVolume()); |
(...skipping 575 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2739 // If the media element has a loop attribute specified | 2732 // If the media element has a loop attribute specified |
2740 if (loop()) { | 2733 if (loop()) { |
2741 m_sentEndEvent = false; | 2734 m_sentEndEvent = false; |
2742 // then seek to the earliest possible position of the media resourc
e and abort these steps. | 2735 // then seek to the earliest possible position of the media resourc
e and abort these steps. |
2743 seek(0); | 2736 seek(0); |
2744 } else { | 2737 } else { |
2745 // If the media element has still ended playback, and the direction
of playback is still | 2738 // If the media element has still ended playback, and the direction
of playback is still |
2746 // forwards, and paused is false, | 2739 // forwards, and paused is false, |
2747 if (!m_paused) { | 2740 if (!m_paused) { |
2748 // changes paused to true and fires a simple event named pause a
t the media element. | 2741 // changes paused to true and fires a simple event named pause a
t the media element. |
| 2742 m_autoplayHelper->playbackEnded(); |
2749 m_paused = true; | 2743 m_paused = true; |
2750 scheduleEvent(EventTypeNames::pause); | 2744 scheduleEvent(EventTypeNames::pause); |
2751 } | 2745 } |
2752 // Queue a task to fire a simple event named ended at the media elem
ent. | 2746 // Queue a task to fire a simple event named ended at the media elem
ent. |
2753 if (!m_sentEndEvent) { | 2747 if (!m_sentEndEvent) { |
2754 m_sentEndEvent = true; | 2748 m_sentEndEvent = true; |
2755 scheduleEvent(EventTypeNames::ended); | 2749 scheduleEvent(EventTypeNames::ended); |
2756 } | 2750 } |
2757 recordMetricsIfPausing(); | |
2758 } | 2751 } |
2759 } else { | 2752 } else { |
2760 m_sentEndEvent = false; | 2753 m_sentEndEvent = false; |
2761 } | 2754 } |
2762 | 2755 |
2763 updatePlayState(); | 2756 updatePlayState(); |
2764 } | 2757 } |
2765 | 2758 |
2766 void HTMLMediaElement::durationChanged() | 2759 void HTMLMediaElement::durationChanged() |
2767 { | 2760 { |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2954 if (shouldBePlaying) { | 2947 if (shouldBePlaying) { |
2955 setDisplayMode(Video); | 2948 setDisplayMode(Video); |
2956 invalidateCachedTime(); | 2949 invalidateCachedTime(); |
2957 | 2950 |
2958 if (!isPlaying) { | 2951 if (!isPlaying) { |
2959 // Set rate, muted before calling play in case they were set before
the media engine was setup. | 2952 // Set rate, muted before calling play in case they were set before
the media engine was setup. |
2960 // The media engine should just stash the rate and muted values sinc
e it isn't already playing. | 2953 // The media engine should just stash the rate and muted values sinc
e it isn't already playing. |
2961 webMediaPlayer()->setRate(playbackRate()); | 2954 webMediaPlayer()->setRate(playbackRate()); |
2962 updateVolume(); | 2955 updateVolume(); |
2963 webMediaPlayer()->play(); | 2956 webMediaPlayer()->play(); |
| 2957 m_autoplayHelper->playbackStarted(); |
2964 } | 2958 } |
2965 | 2959 |
2966 if (mediaControls()) | 2960 if (mediaControls()) |
2967 mediaControls()->playbackStarted(); | 2961 mediaControls()->playbackStarted(); |
2968 startPlaybackProgressTimer(); | 2962 startPlaybackProgressTimer(); |
2969 m_playing = true; | 2963 m_playing = true; |
2970 recordAutoplayMetric(AnyPlaybackStarted); | |
2971 | 2964 |
2972 } else { // Should not be playing right now | 2965 } else { // Should not be playing right now |
2973 if (isPlaying) | 2966 if (isPlaying) |
2974 webMediaPlayer()->pause(); | 2967 webMediaPlayer()->pause(); |
| 2968 |
2975 refreshCachedTime(); | 2969 refreshCachedTime(); |
2976 | 2970 |
2977 m_playbackProgressTimer.stop(); | 2971 m_playbackProgressTimer.stop(); |
2978 m_playing = false; | 2972 m_playing = false; |
2979 double time = currentTime(); | 2973 double time = currentTime(); |
2980 if (time > m_lastSeekTime) | 2974 if (time > m_lastSeekTime) |
2981 addPlayedRange(m_lastSeekTime, time); | 2975 addPlayedRange(m_lastSeekTime, time); |
2982 | 2976 |
2983 if (couldPlayIfEnoughData()) | 2977 if (couldPlayIfEnoughData()) |
2984 prepareToPlay(); | 2978 prepareToPlay(); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3032 mediaControls()->refreshCastButtonVisibilityWithoutUpdate(); | 3026 mediaControls()->refreshCastButtonVisibilityWithoutUpdate(); |
3033 | 3027 |
3034 if (layoutObject()) | 3028 if (layoutObject()) |
3035 layoutObject()->setShouldDoFullPaintInvalidation(); | 3029 layoutObject()->setShouldDoFullPaintInvalidation(); |
3036 } | 3030 } |
3037 | 3031 |
3038 void HTMLMediaElement::stop() | 3032 void HTMLMediaElement::stop() |
3039 { | 3033 { |
3040 WTF_LOG(Media, "HTMLMediaElement::stop(%p)", this); | 3034 WTF_LOG(Media, "HTMLMediaElement::stop(%p)", this); |
3041 | 3035 |
3042 recordMetricsIfPausing(); | |
3043 | |
3044 // Close the async event queue so that no events are enqueued. | 3036 // Close the async event queue so that no events are enqueued. |
3045 cancelPendingEventsAndCallbacks(); | 3037 cancelPendingEventsAndCallbacks(); |
3046 m_asyncEventQueue->close(); | 3038 m_asyncEventQueue->close(); |
3047 | 3039 |
3048 // Stop the playback without generating events | 3040 // Stop the playback without generating events |
3049 clearMediaPlayer(-1); | 3041 clearMediaPlayer(-1); |
3050 m_readyState = HAVE_NOTHING; | 3042 m_readyState = HAVE_NOTHING; |
3051 m_readyStateMaximum = HAVE_NOTHING; | 3043 m_readyStateMaximum = HAVE_NOTHING; |
3052 setNetworkState(NETWORK_EMPTY); | 3044 setNetworkState(NETWORK_EMPTY); |
3053 setShouldDelayLoadEvent(false); | 3045 setShouldDelayLoadEvent(false); |
(...skipping 453 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3507 visitor->trace(m_error); | 3499 visitor->trace(m_error); |
3508 visitor->trace(m_currentSourceNode); | 3500 visitor->trace(m_currentSourceNode); |
3509 visitor->trace(m_nextChildNodeToConsider); | 3501 visitor->trace(m_nextChildNodeToConsider); |
3510 visitor->trace(m_mediaSource); | 3502 visitor->trace(m_mediaSource); |
3511 visitor->trace(m_audioTracks); | 3503 visitor->trace(m_audioTracks); |
3512 visitor->trace(m_videoTracks); | 3504 visitor->trace(m_videoTracks); |
3513 visitor->trace(m_cueTimeline); | 3505 visitor->trace(m_cueTimeline); |
3514 visitor->trace(m_textTracks); | 3506 visitor->trace(m_textTracks); |
3515 visitor->trace(m_textTracksWhenResourceSelectionBegan); | 3507 visitor->trace(m_textTracksWhenResourceSelectionBegan); |
3516 visitor->trace(m_audioSourceProvider); | 3508 visitor->trace(m_audioSourceProvider); |
| 3509 visitor->trace(m_autoplayHelperClient); |
| 3510 visitor->trace(m_autoplayHelper); |
3517 visitor->template registerWeakMembers<HTMLMediaElement, &HTMLMediaElement::c
learWeakMembers>(this); | 3511 visitor->template registerWeakMembers<HTMLMediaElement, &HTMLMediaElement::c
learWeakMembers>(this); |
3518 visitor->trace(m_autoplayHelper); | |
3519 HeapSupplementable<HTMLMediaElement>::trace(visitor); | 3512 HeapSupplementable<HTMLMediaElement>::trace(visitor); |
3520 #endif | 3513 #endif |
3521 HTMLElement::trace(visitor); | 3514 HTMLElement::trace(visitor); |
3522 ActiveDOMObject::trace(visitor); | 3515 ActiveDOMObject::trace(visitor); |
3523 } | 3516 } |
3524 | 3517 |
3525 void HTMLMediaElement::createPlaceholderTracksIfNecessary() | 3518 void HTMLMediaElement::createPlaceholderTracksIfNecessary() |
3526 { | 3519 { |
3527 if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) | 3520 if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) |
3528 return; | 3521 return; |
(...skipping 24 matching lines...) Expand all Loading... |
3553 bool HTMLMediaElement::isUserGestureRequiredForPlay() const | 3546 bool HTMLMediaElement::isUserGestureRequiredForPlay() const |
3554 { | 3547 { |
3555 return m_userGestureRequiredForPlay; | 3548 return m_userGestureRequiredForPlay; |
3556 } | 3549 } |
3557 | 3550 |
3558 void HTMLMediaElement::removeUserGestureRequirement() | 3551 void HTMLMediaElement::removeUserGestureRequirement() |
3559 { | 3552 { |
3560 m_userGestureRequiredForPlay = false; | 3553 m_userGestureRequiredForPlay = false; |
3561 } | 3554 } |
3562 | 3555 |
3563 void HTMLMediaElement::setInitialPlayWithoutUserGestures(bool value) | |
3564 { | |
3565 m_initialPlayWithoutUserGesture = value; | |
3566 } | |
3567 | |
3568 void HTMLMediaElement::setNetworkState(NetworkState state) | 3556 void HTMLMediaElement::setNetworkState(NetworkState state) |
3569 { | 3557 { |
3570 if (m_networkState != state) { | 3558 if (m_networkState != state) { |
3571 m_networkState = state; | 3559 m_networkState = state; |
3572 if (MediaControls* controls = mediaControls()) | 3560 if (MediaControls* controls = mediaControls()) |
3573 controls->networkStateChanged(); | 3561 controls->networkStateChanged(); |
3574 } | 3562 } |
3575 } | 3563 } |
3576 | 3564 |
3577 void HTMLMediaElement::notifyPositionMayHaveChanged(const IntRect& visibleRect) | 3565 void HTMLMediaElement::notifyPositionMayHaveChanged(const IntRect& visibleRect) |
3578 { | 3566 { |
3579 m_autoplayHelper.positionChanged(visibleRect); | 3567 m_autoplayHelper->positionChanged(visibleRect); |
3580 } | 3568 } |
3581 | 3569 |
3582 void HTMLMediaElement::updatePositionNotificationRegistration() | 3570 void HTMLMediaElement::updatePositionNotificationRegistration() |
3583 { | 3571 { |
3584 m_autoplayHelper.updatePositionNotificationRegistration(); | 3572 m_autoplayHelper->updatePositionNotificationRegistration(); |
3585 } | 3573 } |
3586 | 3574 |
3587 // TODO(liberato): remove once autoplay gesture override experiment concludes. | 3575 // TODO(liberato): remove once autoplay gesture override experiment concludes. |
3588 void HTMLMediaElement::triggerAutoplayViewportCheckForTesting() | 3576 void HTMLMediaElement::triggerAutoplayViewportCheckForTesting() |
3589 { | 3577 { |
3590 m_autoplayHelper.triggerAutoplayViewportCheckForTesting(); | 3578 if (FrameView* view = document().view()) |
| 3579 m_autoplayHelper->positionChanged(view->rootFrameToContents(view->comput
eVisibleArea())); |
| 3580 m_autoplayHelper->triggerAutoplayViewportCheckForTesting(); |
3591 } | 3581 } |
3592 | 3582 |
3593 void HTMLMediaElement::clearWeakMembers(Visitor* visitor) | 3583 void HTMLMediaElement::clearWeakMembers(Visitor* visitor) |
3594 { | 3584 { |
3595 if (!Heap::isHeapObjectAlive(m_audioSourceNode)) | 3585 if (!Heap::isHeapObjectAlive(m_audioSourceNode)) |
3596 audioSourceProvider().setClient(nullptr); | 3586 audioSourceProvider().setClient(nullptr); |
3597 } | 3587 } |
3598 | 3588 |
3599 void HTMLMediaElement::AudioSourceProviderImpl::wrap(WebAudioSourceProvider* pro
vider) | 3589 void HTMLMediaElement::AudioSourceProviderImpl::wrap(WebAudioSourceProvider* pro
vider) |
3600 { | 3590 { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3649 DEFINE_TRACE(HTMLMediaElement::AudioClientImpl) | 3639 DEFINE_TRACE(HTMLMediaElement::AudioClientImpl) |
3650 { | 3640 { |
3651 visitor->trace(m_client); | 3641 visitor->trace(m_client); |
3652 } | 3642 } |
3653 | 3643 |
3654 DEFINE_TRACE(HTMLMediaElement::AudioSourceProviderImpl) | 3644 DEFINE_TRACE(HTMLMediaElement::AudioSourceProviderImpl) |
3655 { | 3645 { |
3656 visitor->trace(m_client); | 3646 visitor->trace(m_client); |
3657 } | 3647 } |
3658 | 3648 |
| 3649 HTMLMediaElement::AutoplayHelperClientImpl::~AutoplayHelperClientImpl() |
| 3650 { |
| 3651 } |
| 3652 |
| 3653 bool HTMLMediaElement::AutoplayHelperClientImpl::isLegacyViewportType() |
| 3654 { |
| 3655 return m_element->document().viewportDescription().isLegacyViewportType(); |
| 3656 } |
| 3657 |
| 3658 PageVisibilityState HTMLMediaElement::AutoplayHelperClientImpl::pageVisibilitySt
ate() const |
| 3659 { |
| 3660 return m_element->document().pageVisibilityState(); |
| 3661 } |
| 3662 |
| 3663 String HTMLMediaElement::AutoplayHelperClientImpl::autoplayExperimentMode() cons
t |
| 3664 { |
| 3665 String mode; |
| 3666 if (m_element->document().settings()) |
| 3667 mode = m_element->document().settings()->autoplayExperimentMode(); |
| 3668 |
| 3669 return mode; |
| 3670 } |
| 3671 |
| 3672 void HTMLMediaElement::AutoplayHelperClientImpl::setRequestPositionUpdates(bool
request) |
| 3673 { |
| 3674 if (LayoutObject* layoutObject = m_element->layoutObject()) { |
| 3675 LayoutMedia* layoutMedia = toLayoutMedia(layoutObject); |
| 3676 layoutMedia->setRequestPositionUpdates(request); |
| 3677 } |
| 3678 } |
| 3679 |
| 3680 IntRect HTMLMediaElement::AutoplayHelperClientImpl::absoluteBoundingBoxRect() co
nst |
| 3681 { |
| 3682 IntRect result; |
| 3683 if (LayoutObject* object = m_element->layoutObject()) |
| 3684 result = object->absoluteBoundingBoxRect(); |
| 3685 return result; |
| 3686 } |
| 3687 |
3659 } // namespace blink | 3688 } // namespace blink |
OLD | NEW |