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 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
322 , m_seeking(false) | 323 , m_seeking(false) |
323 , m_sentStalledEvent(false) | 324 , m_sentStalledEvent(false) |
324 , m_sentEndEvent(false) | 325 , m_sentEndEvent(false) |
325 , m_closedCaptionsVisible(false) | 326 , m_closedCaptionsVisible(false) |
326 , m_havePreparedToPlay(false) | 327 , m_havePreparedToPlay(false) |
327 , m_tracksAreReady(true) | 328 , m_tracksAreReady(true) |
328 , m_processingPreferenceChange(false) | 329 , m_processingPreferenceChange(false) |
329 , m_remoteRoutesAvailable(false) | 330 , m_remoteRoutesAvailable(false) |
330 , m_playingRemotely(false) | 331 , m_playingRemotely(false) |
331 , m_isFinalizing(false) | 332 , m_isFinalizing(false) |
332 , m_initialPlayWithoutUserGesture(false) | |
333 , m_autoplayMediaCounted(false) | |
334 , m_inOverlayFullscreenVideo(false) | 333 , m_inOverlayFullscreenVideo(false) |
335 , m_audioTracks(AudioTrackList::create(*this)) | 334 , m_audioTracks(AudioTrackList::create(*this)) |
336 , m_videoTracks(VideoTrackList::create(*this)) | 335 , m_videoTracks(VideoTrackList::create(*this)) |
337 , m_textTracks(nullptr) | 336 , m_textTracks(nullptr) |
338 , m_audioSourceNode(nullptr) | 337 , m_audioSourceNode(nullptr) |
339 , m_autoplayHelper(*this) | 338 , m_autoplayHelperClient(adoptPtr(new AutoplayHelperClientImpl(this))) |
sof
2016/02/16 08:40:06
Could you add a static create() factory method & c
liberato (no reviews please)
2016/02/24 18:44:05
Done.
| |
339 , m_autoplayHelper(adoptPtr(new AutoplayExperimentHelper(*m_autoplayHelperCl ient))) | |
sof
2016/02/16 08:40:06
Could you add a static create() factory method & c
liberato (no reviews please)
2016/02/24 18:44:05
Done.
| |
340 { | 340 { |
341 #if ENABLE(OILPAN) | 341 #if ENABLE(OILPAN) |
342 ThreadState::current()->registerPreFinalizer(this); | 342 ThreadState::current()->registerPreFinalizer(this); |
343 #endif | 343 #endif |
344 ASSERT(RuntimeEnabledFeatures::mediaEnabled()); | 344 ASSERT(RuntimeEnabledFeatures::mediaEnabled()); |
345 | 345 |
346 WTF_LOG(Media, "HTMLMediaElement::HTMLMediaElement(%p)", this); | 346 WTF_LOG(Media, "HTMLMediaElement::HTMLMediaElement(%p)", this); |
347 | 347 |
348 if (document.settings() && document.settings()->mediaPlaybackRequiresUserGes ture()) | 348 if (document.settings() && document.settings()->mediaPlaybackRequiresUserGes ture()) |
349 m_userGestureRequiredForPlay = true; | 349 m_userGestureRequiredForPlay = true; |
350 | 350 |
351 setHasCustomStyleCallbacks(); | 351 setHasCustomStyleCallbacks(); |
352 addElementToDocumentMap(this, &document); | 352 addElementToDocumentMap(this, &document); |
353 | 353 |
354 UseCounter::count(document, UseCounter::HTMLMediaElement); | 354 UseCounter::count(document, UseCounter::HTMLMediaElement); |
355 } | 355 } |
356 | 356 |
357 HTMLMediaElement::~HTMLMediaElement() | 357 HTMLMediaElement::~HTMLMediaElement() |
358 { | 358 { |
359 WTF_LOG(Media, "HTMLMediaElement::~HTMLMediaElement(%p)", this); | 359 WTF_LOG(Media, "HTMLMediaElement::~HTMLMediaElement(%p)", this); |
360 | 360 |
361 if (m_autoplayHelper) | |
sof
2016/02/16 08:40:06
I haven't looked at the details, but is this expli
liberato (no reviews please)
2016/02/24 18:44:05
yes. destroying the helper calls into the client,
| |
362 m_autoplayHelper.clear(); | |
363 | |
364 if (m_autoplayHelperClient) | |
365 m_autoplayHelperClient.clear(); | |
366 | |
361 #if !ENABLE(OILPAN) | 367 #if !ENABLE(OILPAN) |
362 // HTMLMediaElement and m_asyncEventQueue always become unreachable | 368 // HTMLMediaElement and m_asyncEventQueue always become unreachable |
363 // together. So HTMLMediaElement and m_asyncEventQueue are destructed in | 369 // together. So HTMLMediaElement and m_asyncEventQueue are destructed in |
364 // the same GC. We don't need to close it explicitly in Oilpan. | 370 // the same GC. We don't need to close it explicitly in Oilpan. |
365 m_asyncEventQueue->close(); | 371 m_asyncEventQueue->close(); |
366 | 372 |
367 setShouldDelayLoadEvent(false); | 373 setShouldDelayLoadEvent(false); |
368 | 374 |
369 if (m_textTracks) | 375 if (m_textTracks) |
370 m_textTracks->clearOwner(); | 376 m_textTracks->clearOwner(); |
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
651 case WebMimeRegistry::IsSupported: | 657 case WebMimeRegistry::IsSupported: |
652 canPlay = "probably"; | 658 canPlay = "probably"; |
653 break; | 659 break; |
654 } | 660 } |
655 | 661 |
656 WTF_LOG(Media, "HTMLMediaElement::canPlayType(%p, %s, %s) -> %s", this, mime Type.utf8().data(), keySystem.utf8().data(), canPlay.utf8().data()); | 662 WTF_LOG(Media, "HTMLMediaElement::canPlayType(%p, %s, %s) -> %s", this, mime Type.utf8().data(), keySystem.utf8().data(), canPlay.utf8().data()); |
657 | 663 |
658 return canPlay; | 664 return canPlay; |
659 } | 665 } |
660 | 666 |
661 void HTMLMediaElement::recordMetricsIfPausing() | |
662 { | |
663 // If not playing, then nothing to record. | |
664 // TODO(liberato): test metrics. this was m_paused. | |
665 if (m_paused) | |
666 return; | |
667 | |
668 const bool bailout = isBailout(); | |
669 | |
670 // Record that play was paused. We don't care if it was autoplay, | |
671 // play(), or the user manually started it. | |
672 recordAutoplayMetric(AnyPlaybackPaused); | |
673 if (bailout) | |
674 recordAutoplayMetric(AnyPlaybackBailout); | |
675 | |
676 // If this was a gestureless play, then record that separately. | |
677 // These cover attr and play() gestureless starts. | |
678 if (m_initialPlayWithoutUserGesture) { | |
679 m_initialPlayWithoutUserGesture = false; | |
680 | |
681 recordAutoplayMetric(AutoplayPaused); | |
682 | |
683 if (bailout) | |
684 recordAutoplayMetric(AutoplayBailout); | |
685 } | |
686 } | |
687 | |
688 void HTMLMediaElement::load() | 667 void HTMLMediaElement::load() |
689 { | 668 { |
690 WTF_LOG(Media, "HTMLMediaElement::load(%p)", this); | 669 WTF_LOG(Media, "HTMLMediaElement::load(%p)", this); |
691 | 670 |
692 recordMetricsIfPausing(); | 671 m_autoplayHelper->loadMethodCalled(); |
693 | |
694 if (UserGestureIndicator::processingUserGesture() && m_userGestureRequiredFo rPlay) { | |
695 recordAutoplayMetric(AutoplayEnabledThroughLoad); | |
696 m_userGestureRequiredForPlay = false; | |
697 // While usergesture-initiated load()s technically count as autoplayed, | |
698 // they don't feel like such to the users and hence we don't want to | |
699 // count them for the purposes of metrics. | |
700 m_autoplayMediaCounted = true; | |
701 } | |
702 | 672 |
703 prepareForLoad(); | 673 prepareForLoad(); |
704 loadInternal(); | 674 loadInternal(); |
705 prepareToPlay(); | 675 prepareToPlay(); |
706 } | 676 } |
707 | 677 |
708 void HTMLMediaElement::prepareForLoad() | 678 void HTMLMediaElement::prepareForLoad() |
709 { | 679 { |
710 WTF_LOG(Media, "HTMLMediaElement::prepareForLoad(%p)", this); | 680 WTF_LOG(Media, "HTMLMediaElement::prepareForLoad(%p)", this); |
711 | 681 |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
914 | 884 |
915 LocalFrame* frame = document().frame(); | 885 LocalFrame* frame = document().frame(); |
916 if (!frame) { | 886 if (!frame) { |
917 mediaLoadingFailed(WebMediaPlayer::NetworkStateFormatError); | 887 mediaLoadingFailed(WebMediaPlayer::NetworkStateFormatError); |
918 return; | 888 return; |
919 } | 889 } |
920 | 890 |
921 // The resource fetch algorithm | 891 // The resource fetch algorithm |
922 setNetworkState(NETWORK_LOADING); | 892 setNetworkState(NETWORK_LOADING); |
923 | 893 |
894 m_autoplayHelper->loadingStarted(); | |
895 | |
924 // Set m_currentSrc *before* changing to the cache url, the fact that we are loading from the app | 896 // Set m_currentSrc *before* changing to the cache url, the fact that we are loading from the app |
925 // cache is an internal detail not exposed through the media element API. | 897 // cache is an internal detail not exposed through the media element API. |
926 m_currentSrc = url; | 898 m_currentSrc = url; |
927 | 899 |
928 if (m_audioSourceNode) | 900 if (m_audioSourceNode) |
929 m_audioSourceNode->onCurrentSrcChanged(m_currentSrc); | 901 m_audioSourceNode->onCurrentSrcChanged(m_currentSrc); |
930 | 902 |
931 WTF_LOG(Media, "HTMLMediaElement::loadResource(%p) - m_currentSrc -> %s", th is, urlForLoggingMedia(m_currentSrc).utf8().data()); | 903 WTF_LOG(Media, "HTMLMediaElement::loadResource(%p) - m_currentSrc -> %s", th is, urlForLoggingMedia(m_currentSrc).utf8().data()); |
932 | 904 |
933 startProgressEventTimer(); | 905 startProgressEventTimer(); |
934 | 906 |
935 // Reset display mode to force a recalculation of what to show because we ar e resetting the player. | 907 // Reset display mode to force a recalculation of what to show because we ar e resetting the player. |
936 setDisplayMode(Unknown); | 908 setDisplayMode(Unknown); |
937 | 909 |
938 setPlayerPreload(); | 910 setPlayerPreload(); |
939 | 911 |
940 if (fastHasAttribute(mutedAttr)) | 912 if (fastHasAttribute(mutedAttr)) |
941 m_muted = true; | 913 m_muted = true; |
942 updateVolume(); | 914 updateVolume(); |
943 | 915 |
944 ASSERT(!m_mediaSource); | 916 ASSERT(!m_mediaSource); |
945 | 917 |
946 bool attemptLoad = true; | 918 bool attemptLoad = true; |
947 | 919 |
948 if (url.protocolIs(mediaSourceBlobProtocol)) { | 920 if (url.protocolIs(mediaSourceBlobProtocol)) { |
949 if (isMediaStreamURL(url.string())) { | 921 if (isMediaStreamURL(url.string())) { |
950 m_userGestureRequiredForPlay = false; | 922 m_autoplayHelper->removeUserGestureRequirement(GesturelessPlaybackEn abledByStream); |
951 } else { | 923 } else { |
952 m_mediaSource = HTMLMediaSource::lookup(url.string()); | 924 m_mediaSource = HTMLMediaSource::lookup(url.string()); |
953 | 925 |
954 if (m_mediaSource) { | 926 if (m_mediaSource) { |
955 if (!m_mediaSource->attachToElement(this)) { | 927 if (!m_mediaSource->attachToElement(this)) { |
956 // Forget our reference to the MediaSource, so we leave it a lone | 928 // Forget our reference to the MediaSource, so we leave it a lone |
957 // while processing remainder of load failure. | 929 // while processing remainder of load failure. |
958 m_mediaSource = nullptr; | 930 m_mediaSource = nullptr; |
959 attemptLoad = false; | 931 attemptLoad = false; |
960 } | 932 } |
(...skipping 562 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1523 } | 1495 } |
1524 | 1496 |
1525 if (m_readyState == HAVE_ENOUGH_DATA && oldState < HAVE_ENOUGH_DATA && track sAreReady) { | 1497 if (m_readyState == HAVE_ENOUGH_DATA && oldState < HAVE_ENOUGH_DATA && track sAreReady) { |
1526 if (oldState <= HAVE_CURRENT_DATA) { | 1498 if (oldState <= HAVE_CURRENT_DATA) { |
1527 scheduleEvent(EventTypeNames::canplay); | 1499 scheduleEvent(EventTypeNames::canplay); |
1528 if (isPotentiallyPlaying) | 1500 if (isPotentiallyPlaying) |
1529 scheduleEvent(EventTypeNames::playing); | 1501 scheduleEvent(EventTypeNames::playing); |
1530 } | 1502 } |
1531 | 1503 |
1532 // Check for autoplay, and record metrics about it if needed. | 1504 // Check for autoplay, and record metrics about it if needed. |
1533 if (shouldAutoplay(RecordMetricsBehavior::DoRecord)) { | 1505 if (shouldAutoplay(RecordMetricsBehavior::RecordOnSandboxFailure)) { |
1534 // If the autoplay experiment says that it's okay to play now, | 1506 // If the autoplay experiment says that it's okay to play now, |
1535 // then don't require a user gesture. | 1507 // then don't require a user gesture. |
1536 m_autoplayHelper.becameReadyToPlay(); | 1508 m_autoplayHelper->becameReadyToPlay(); |
1537 | 1509 |
1538 if (!m_userGestureRequiredForPlay) { | 1510 if (!m_userGestureRequiredForPlay) { |
1539 m_paused = false; | 1511 m_paused = false; |
1540 invalidateCachedTime(); | 1512 invalidateCachedTime(); |
1541 scheduleEvent(EventTypeNames::play); | 1513 scheduleEvent(EventTypeNames::play); |
1542 scheduleEvent(EventTypeNames::playing); | 1514 scheduleEvent(EventTypeNames::playing); |
1543 m_autoplaying = false; | 1515 m_autoplaying = false; |
1544 } | 1516 } |
1545 } | 1517 } |
1546 | 1518 |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1665 | 1637 |
1666 m_lastSeekTime = time; | 1638 m_lastSeekTime = time; |
1667 m_sentEndEvent = false; | 1639 m_sentEndEvent = false; |
1668 | 1640 |
1669 // 10 - Queue a task to fire a simple event named seeking at the element. | 1641 // 10 - Queue a task to fire a simple event named seeking at the element. |
1670 scheduleEvent(EventTypeNames::seeking); | 1642 scheduleEvent(EventTypeNames::seeking); |
1671 | 1643 |
1672 // 11 - Set the current playback position to the given new playback position . | 1644 // 11 - Set the current playback position to the given new playback position . |
1673 webMediaPlayer()->seek(time); | 1645 webMediaPlayer()->seek(time); |
1674 | 1646 |
1675 m_initialPlayWithoutUserGesture = false; | |
1676 | |
1677 // 14-17 are handled, if necessary, when the engine signals a readystate cha nge or otherwise | 1647 // 14-17 are handled, if necessary, when the engine signals a readystate cha nge or otherwise |
1678 // satisfies seek completion and signals a time change. | 1648 // satisfies seek completion and signals a time change. |
1679 } | 1649 } |
1680 | 1650 |
1681 void HTMLMediaElement::finishSeek() | 1651 void HTMLMediaElement::finishSeek() |
1682 { | 1652 { |
1683 WTF_LOG(Media, "HTMLMediaElement::finishSeek(%p)", this); | 1653 WTF_LOG(Media, "HTMLMediaElement::finishSeek(%p)", this); |
1684 | 1654 |
1685 // 14 - Set the seeking IDL attribute to false. | 1655 // 14 - Set the seeking IDL attribute to false. |
1686 m_seeking = false; | 1656 m_seeking = false; |
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1848 } | 1818 } |
1849 | 1819 |
1850 bool HTMLMediaElement::autoplay() const | 1820 bool HTMLMediaElement::autoplay() const |
1851 { | 1821 { |
1852 return fastHasAttribute(autoplayAttr); | 1822 return fastHasAttribute(autoplayAttr); |
1853 } | 1823 } |
1854 | 1824 |
1855 bool HTMLMediaElement::shouldAutoplay(const RecordMetricsBehavior recordMetrics) | 1825 bool HTMLMediaElement::shouldAutoplay(const RecordMetricsBehavior recordMetrics) |
1856 { | 1826 { |
1857 if (m_autoplaying && m_paused && autoplay()) { | 1827 if (m_autoplaying && m_paused && autoplay()) { |
1858 if (recordMetrics == RecordMetricsBehavior::DoRecord) | |
1859 autoplayMediaEncountered(); | |
1860 | |
1861 if (document().isSandboxed(SandboxAutomaticFeatures)) { | 1828 if (document().isSandboxed(SandboxAutomaticFeatures)) { |
1862 if (recordMetrics == RecordMetricsBehavior::DoRecord) | 1829 if (recordMetrics == RecordMetricsBehavior::RecordOnSandboxFailure) |
1863 recordAutoplayMetric(AutoplayDisabledBySandbox); | 1830 m_autoplayHelper->recordSandboxFailure(); |
1864 return false; | 1831 return false; |
1865 } | 1832 } |
1866 | 1833 |
1867 return true; | 1834 return true; |
1868 } | 1835 } |
1869 | 1836 |
1870 return false; | 1837 return false; |
1871 } | 1838 } |
1872 | 1839 |
1873 String HTMLMediaElement::preload() const | 1840 String HTMLMediaElement::preload() const |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1928 | 1895 |
1929 WebMediaPlayer::Preload HTMLMediaElement::effectivePreloadType() const | 1896 WebMediaPlayer::Preload HTMLMediaElement::effectivePreloadType() const |
1930 { | 1897 { |
1931 return autoplay() ? WebMediaPlayer::PreloadAuto : preloadType(); | 1898 return autoplay() ? WebMediaPlayer::PreloadAuto : preloadType(); |
1932 } | 1899 } |
1933 | 1900 |
1934 void HTMLMediaElement::play() | 1901 void HTMLMediaElement::play() |
1935 { | 1902 { |
1936 WTF_LOG(Media, "HTMLMediaElement::play(%p)", this); | 1903 WTF_LOG(Media, "HTMLMediaElement::play(%p)", this); |
1937 | 1904 |
1938 m_autoplayHelper.playMethodCalled(); | 1905 m_autoplayHelper->playMethodCalled(); |
1939 | 1906 |
1940 if (!UserGestureIndicator::processingUserGesture()) { | 1907 if (!UserGestureIndicator::processingUserGesture()) { |
1941 autoplayMediaEncountered(); | |
1942 | |
1943 if (m_userGestureRequiredForPlay) { | 1908 if (m_userGestureRequiredForPlay) { |
1944 recordAutoplayMetric(PlayMethodFailed); | 1909 recordAutoplayMetric(PlayMethodFailed); |
1945 String message = ExceptionMessages::failedToExecute("play", "HTMLMed iaElement", "API can only be initiated by a user gesture."); | 1910 String message = ExceptionMessages::failedToExecute("play", "HTMLMed iaElement", "API can only be initiated by a user gesture."); |
1946 document().addConsoleMessage(ConsoleMessage::create(JSMessageSource, WarningMessageLevel, message)); | 1911 document().addConsoleMessage(ConsoleMessage::create(JSMessageSource, WarningMessageLevel, message)); |
1947 return; | 1912 return; |
1948 } | 1913 } |
1949 } else if (m_userGestureRequiredForPlay) { | 1914 } else { |
1950 if (m_autoplayMediaCounted) | 1915 // We ask the helper to remove the gesture requirement for us, so that |
1951 recordAutoplayMetric(AutoplayManualStart); | 1916 // it can record the reason. |
1952 m_userGestureRequiredForPlay = false; | 1917 m_autoplayHelper->removeUserGestureRequirement(GesturelessPlaybackEnable dByPlayMethod); |
1953 } | 1918 } |
1954 | 1919 |
1955 playInternal(); | 1920 playInternal(); |
1956 } | 1921 } |
1957 | 1922 |
1958 void HTMLMediaElement::playInternal() | 1923 void HTMLMediaElement::playInternal() |
1959 { | 1924 { |
1960 WTF_LOG(Media, "HTMLMediaElement::playInternal(%p)", this); | 1925 WTF_LOG(Media, "HTMLMediaElement::playInternal(%p)", this); |
1961 | 1926 |
1962 // Always return the buffering strategy to normal when not paused, | 1927 // Always return the buffering strategy to normal when not paused, |
(...skipping 20 matching lines...) Expand all Loading... | |
1983 if (m_readyState <= HAVE_CURRENT_DATA) | 1948 if (m_readyState <= HAVE_CURRENT_DATA) |
1984 scheduleEvent(EventTypeNames::waiting); | 1949 scheduleEvent(EventTypeNames::waiting); |
1985 else if (m_readyState >= HAVE_FUTURE_DATA) | 1950 else if (m_readyState >= HAVE_FUTURE_DATA) |
1986 scheduleEvent(EventTypeNames::playing); | 1951 scheduleEvent(EventTypeNames::playing); |
1987 } | 1952 } |
1988 m_autoplaying = false; | 1953 m_autoplaying = false; |
1989 | 1954 |
1990 updatePlayState(); | 1955 updatePlayState(); |
1991 } | 1956 } |
1992 | 1957 |
1993 void HTMLMediaElement::autoplayMediaEncountered() | |
1994 { | |
1995 if (!m_autoplayMediaCounted) { | |
1996 m_autoplayMediaCounted = true; | |
1997 recordAutoplayMetric(AutoplayMediaFound); | |
1998 | |
1999 if (!m_userGestureRequiredForPlay) | |
2000 m_initialPlayWithoutUserGesture = true; | |
2001 } | |
2002 } | |
2003 | |
2004 bool HTMLMediaElement::isBailout() const | |
2005 { | |
2006 // We count the user as having bailed-out on the video if they watched | |
2007 // less than one minute and less than 50% of it. | |
2008 const double playedTime = currentTime(); | |
2009 const double progress = playedTime / duration(); | |
2010 return (playedTime < 60) && (progress < 0.5); | |
2011 } | |
2012 | |
2013 void HTMLMediaElement::pause() | 1958 void HTMLMediaElement::pause() |
2014 { | 1959 { |
2015 WTF_LOG(Media, "HTMLMediaElement::pause(%p)", this); | 1960 WTF_LOG(Media, "HTMLMediaElement::pause(%p)", this); |
2016 | 1961 |
2017 // Only buffer aggressively on a user-initiated pause. Other types of pauses | 1962 // Only buffer aggressively on a user-initiated pause. Other types of pauses |
2018 // (which go directly to pauseInternal()) should not cause this behavior. | 1963 // (which go directly to pauseInternal()) should not cause this behavior. |
2019 if (webMediaPlayer() && UserGestureIndicator::processingUserGesture()) | 1964 if (webMediaPlayer() && UserGestureIndicator::processingUserGesture()) |
2020 webMediaPlayer()->setBufferingStrategy(WebMediaPlayer::BufferingStrategy ::Aggressive); | 1965 webMediaPlayer()->setBufferingStrategy(WebMediaPlayer::BufferingStrategy ::Aggressive); |
2021 | 1966 |
2022 pauseInternal(); | 1967 pauseInternal(); |
2023 } | 1968 } |
2024 | 1969 |
2025 void HTMLMediaElement::pauseInternal() | 1970 void HTMLMediaElement::pauseInternal() |
2026 { | 1971 { |
2027 WTF_LOG(Media, "HTMLMediaElement::pauseInternal(%p)", this); | 1972 WTF_LOG(Media, "HTMLMediaElement::pauseInternal(%p)", this); |
2028 | 1973 |
2029 if (m_networkState == NETWORK_EMPTY) | 1974 if (m_networkState == NETWORK_EMPTY) |
2030 scheduleDelayedAction(LoadMediaResource); | 1975 scheduleDelayedAction(LoadMediaResource); |
2031 | 1976 |
2032 m_autoplayHelper.pauseMethodCalled(); | 1977 m_autoplayHelper->pauseMethodCalled(); |
2033 | 1978 |
2034 m_autoplaying = false; | 1979 m_autoplaying = false; |
2035 | 1980 |
2036 if (!m_paused) { | 1981 if (!m_paused) { |
2037 recordMetricsIfPausing(); | |
2038 | |
2039 m_paused = true; | 1982 m_paused = true; |
2040 scheduleTimeupdateEvent(false); | 1983 scheduleTimeupdateEvent(false); |
2041 scheduleEvent(EventTypeNames::pause); | 1984 scheduleEvent(EventTypeNames::pause); |
2042 } | 1985 } |
2043 | 1986 |
2044 updatePlayState(); | 1987 updatePlayState(); |
2045 } | 1988 } |
2046 | 1989 |
2047 void HTMLMediaElement::requestRemotePlayback() | 1990 void HTMLMediaElement::requestRemotePlayback() |
2048 { | 1991 { |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2120 | 2063 |
2121 void HTMLMediaElement::setMuted(bool muted) | 2064 void HTMLMediaElement::setMuted(bool muted) |
2122 { | 2065 { |
2123 WTF_LOG(Media, "HTMLMediaElement::setMuted(%p, %s)", this, boolString(muted) ); | 2066 WTF_LOG(Media, "HTMLMediaElement::setMuted(%p, %s)", this, boolString(muted) ); |
2124 | 2067 |
2125 if (m_muted == muted) | 2068 if (m_muted == muted) |
2126 return; | 2069 return; |
2127 | 2070 |
2128 m_muted = muted; | 2071 m_muted = muted; |
2129 | 2072 |
2130 m_autoplayHelper.mutedChanged(); | 2073 m_autoplayHelper->mutedChanged(); |
2131 | 2074 |
2132 updateVolume(); | 2075 updateVolume(); |
2133 | 2076 |
2134 scheduleEvent(EventTypeNames::volumechange); | 2077 scheduleEvent(EventTypeNames::volumechange); |
2135 } | 2078 } |
2136 | 2079 |
2137 void HTMLMediaElement::updateVolume() | 2080 void HTMLMediaElement::updateVolume() |
2138 { | 2081 { |
2139 if (webMediaPlayer()) | 2082 if (webMediaPlayer()) |
2140 webMediaPlayer()->setVolume(effectiveMediaVolume()); | 2083 webMediaPlayer()->setVolume(effectiveMediaVolume()); |
(...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2720 // If the media element has a loop attribute specified | 2663 // If the media element has a loop attribute specified |
2721 if (loop()) { | 2664 if (loop()) { |
2722 m_sentEndEvent = false; | 2665 m_sentEndEvent = false; |
2723 // then seek to the earliest possible position of the media resourc e and abort these steps. | 2666 // then seek to the earliest possible position of the media resourc e and abort these steps. |
2724 seek(0); | 2667 seek(0); |
2725 } else { | 2668 } else { |
2726 // If the media element has still ended playback, and the direction of playback is still | 2669 // If the media element has still ended playback, and the direction of playback is still |
2727 // forwards, and paused is false, | 2670 // forwards, and paused is false, |
2728 if (!m_paused) { | 2671 if (!m_paused) { |
2729 // changes paused to true and fires a simple event named pause a t the media element. | 2672 // changes paused to true and fires a simple event named pause a t the media element. |
2673 m_autoplayHelper->playbackEnded(); | |
2730 m_paused = true; | 2674 m_paused = true; |
2731 scheduleEvent(EventTypeNames::pause); | 2675 scheduleEvent(EventTypeNames::pause); |
2732 } | 2676 } |
2733 // Queue a task to fire a simple event named ended at the media elem ent. | 2677 // Queue a task to fire a simple event named ended at the media elem ent. |
2734 if (!m_sentEndEvent) { | 2678 if (!m_sentEndEvent) { |
2735 m_sentEndEvent = true; | 2679 m_sentEndEvent = true; |
2736 scheduleEvent(EventTypeNames::ended); | 2680 scheduleEvent(EventTypeNames::ended); |
2737 } | 2681 } |
2738 recordMetricsIfPausing(); | |
2739 } | 2682 } |
2740 } else { | 2683 } else { |
2741 m_sentEndEvent = false; | 2684 m_sentEndEvent = false; |
2742 } | 2685 } |
2743 | 2686 |
2744 updatePlayState(); | 2687 updatePlayState(); |
2745 } | 2688 } |
2746 | 2689 |
2747 void HTMLMediaElement::durationChanged() | 2690 void HTMLMediaElement::durationChanged() |
2748 { | 2691 { |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2935 if (shouldBePlaying) { | 2878 if (shouldBePlaying) { |
2936 setDisplayMode(Video); | 2879 setDisplayMode(Video); |
2937 invalidateCachedTime(); | 2880 invalidateCachedTime(); |
2938 | 2881 |
2939 if (!isPlaying) { | 2882 if (!isPlaying) { |
2940 // Set rate, muted before calling play in case they were set before the media engine was setup. | 2883 // Set rate, muted before calling play in case they were set before the media engine was setup. |
2941 // The media engine should just stash the rate and muted values sinc e it isn't already playing. | 2884 // The media engine should just stash the rate and muted values sinc e it isn't already playing. |
2942 webMediaPlayer()->setRate(playbackRate()); | 2885 webMediaPlayer()->setRate(playbackRate()); |
2943 updateVolume(); | 2886 updateVolume(); |
2944 webMediaPlayer()->play(); | 2887 webMediaPlayer()->play(); |
2888 m_autoplayHelper->playbackStarted(); | |
2945 } | 2889 } |
2946 | 2890 |
2947 if (mediaControls()) | 2891 if (mediaControls()) |
2948 mediaControls()->playbackStarted(); | 2892 mediaControls()->playbackStarted(); |
2949 startPlaybackProgressTimer(); | 2893 startPlaybackProgressTimer(); |
2950 m_playing = true; | 2894 m_playing = true; |
2951 recordAutoplayMetric(AnyPlaybackStarted); | |
2952 | 2895 |
2953 } else { // Should not be playing right now | 2896 } else { // Should not be playing right now |
2954 if (isPlaying) | 2897 if (isPlaying) |
2955 webMediaPlayer()->pause(); | 2898 webMediaPlayer()->pause(); |
2899 | |
2956 refreshCachedTime(); | 2900 refreshCachedTime(); |
2957 | 2901 |
2958 m_playbackProgressTimer.stop(); | 2902 m_playbackProgressTimer.stop(); |
2959 m_playing = false; | 2903 m_playing = false; |
2960 double time = currentTime(); | 2904 double time = currentTime(); |
2961 if (time > m_lastSeekTime) | 2905 if (time > m_lastSeekTime) |
2962 addPlayedRange(m_lastSeekTime, time); | 2906 addPlayedRange(m_lastSeekTime, time); |
2963 | 2907 |
2964 if (couldPlayIfEnoughData()) | 2908 if (couldPlayIfEnoughData()) |
2965 prepareToPlay(); | 2909 prepareToPlay(); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3013 mediaControls()->refreshCastButtonVisibilityWithoutUpdate(); | 2957 mediaControls()->refreshCastButtonVisibilityWithoutUpdate(); |
3014 | 2958 |
3015 if (layoutObject()) | 2959 if (layoutObject()) |
3016 layoutObject()->setShouldDoFullPaintInvalidation(); | 2960 layoutObject()->setShouldDoFullPaintInvalidation(); |
3017 } | 2961 } |
3018 | 2962 |
3019 void HTMLMediaElement::stop() | 2963 void HTMLMediaElement::stop() |
3020 { | 2964 { |
3021 WTF_LOG(Media, "HTMLMediaElement::stop(%p)", this); | 2965 WTF_LOG(Media, "HTMLMediaElement::stop(%p)", this); |
3022 | 2966 |
3023 recordMetricsIfPausing(); | |
3024 | |
3025 // Close the async event queue so that no events are enqueued. | 2967 // Close the async event queue so that no events are enqueued. |
3026 cancelPendingEventsAndCallbacks(); | 2968 cancelPendingEventsAndCallbacks(); |
3027 m_asyncEventQueue->close(); | 2969 m_asyncEventQueue->close(); |
3028 | 2970 |
3029 // Stop the playback without generating events | 2971 // Stop the playback without generating events |
3030 clearMediaPlayer(-1); | 2972 clearMediaPlayer(-1); |
3031 m_readyState = HAVE_NOTHING; | 2973 m_readyState = HAVE_NOTHING; |
3032 m_readyStateMaximum = HAVE_NOTHING; | 2974 m_readyStateMaximum = HAVE_NOTHING; |
3033 setNetworkState(NETWORK_EMPTY); | 2975 setNetworkState(NETWORK_EMPTY); |
3034 setShouldDelayLoadEvent(false); | 2976 setShouldDelayLoadEvent(false); |
(...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3483 visitor->trace(m_currentSourceNode); | 3425 visitor->trace(m_currentSourceNode); |
3484 visitor->trace(m_nextChildNodeToConsider); | 3426 visitor->trace(m_nextChildNodeToConsider); |
3485 visitor->trace(m_mediaSource); | 3427 visitor->trace(m_mediaSource); |
3486 visitor->trace(m_audioTracks); | 3428 visitor->trace(m_audioTracks); |
3487 visitor->trace(m_videoTracks); | 3429 visitor->trace(m_videoTracks); |
3488 visitor->trace(m_cueTimeline); | 3430 visitor->trace(m_cueTimeline); |
3489 visitor->trace(m_textTracks); | 3431 visitor->trace(m_textTracks); |
3490 visitor->trace(m_textTracksWhenResourceSelectionBegan); | 3432 visitor->trace(m_textTracksWhenResourceSelectionBegan); |
3491 visitor->trace(m_audioSourceProvider); | 3433 visitor->trace(m_audioSourceProvider); |
3492 visitor->template registerWeakMembers<HTMLMediaElement, &HTMLMediaElement::c learWeakMembers>(this); | 3434 visitor->template registerWeakMembers<HTMLMediaElement, &HTMLMediaElement::c learWeakMembers>(this); |
3493 visitor->trace(m_autoplayHelper); | |
3494 HeapSupplementable<HTMLMediaElement>::trace(visitor); | 3435 HeapSupplementable<HTMLMediaElement>::trace(visitor); |
3495 #endif | 3436 #endif |
3496 HTMLElement::trace(visitor); | 3437 HTMLElement::trace(visitor); |
3497 ActiveDOMObject::trace(visitor); | 3438 ActiveDOMObject::trace(visitor); |
3498 } | 3439 } |
3499 | 3440 |
3500 void HTMLMediaElement::createPlaceholderTracksIfNecessary() | 3441 void HTMLMediaElement::createPlaceholderTracksIfNecessary() |
3501 { | 3442 { |
3502 if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) | 3443 if (!RuntimeEnabledFeatures::audioVideoTracksEnabled()) |
3503 return; | 3444 return; |
(...skipping 24 matching lines...) Expand all Loading... | |
3528 bool HTMLMediaElement::isUserGestureRequiredForPlay() const | 3469 bool HTMLMediaElement::isUserGestureRequiredForPlay() const |
3529 { | 3470 { |
3530 return m_userGestureRequiredForPlay; | 3471 return m_userGestureRequiredForPlay; |
3531 } | 3472 } |
3532 | 3473 |
3533 void HTMLMediaElement::removeUserGestureRequirement() | 3474 void HTMLMediaElement::removeUserGestureRequirement() |
3534 { | 3475 { |
3535 m_userGestureRequiredForPlay = false; | 3476 m_userGestureRequiredForPlay = false; |
3536 } | 3477 } |
3537 | 3478 |
3538 void HTMLMediaElement::setInitialPlayWithoutUserGestures(bool value) | |
3539 { | |
3540 m_initialPlayWithoutUserGesture = value; | |
3541 } | |
3542 | |
3543 void HTMLMediaElement::setNetworkState(NetworkState state) | 3479 void HTMLMediaElement::setNetworkState(NetworkState state) |
3544 { | 3480 { |
3545 if (m_networkState != state) { | 3481 if (m_networkState != state) { |
3546 m_networkState = state; | 3482 m_networkState = state; |
3547 if (MediaControls* controls = mediaControls()) | 3483 if (MediaControls* controls = mediaControls()) |
3548 controls->networkStateChanged(); | 3484 controls->networkStateChanged(); |
3549 } | 3485 } |
3550 } | 3486 } |
3551 | 3487 |
3552 void HTMLMediaElement::notifyPositionMayHaveChanged(const IntRect& visibleRect) | 3488 void HTMLMediaElement::notifyPositionMayHaveChanged(const IntRect& visibleRect) |
3553 { | 3489 { |
3554 m_autoplayHelper.positionChanged(visibleRect); | 3490 m_autoplayHelper->positionChanged(visibleRect); |
3555 } | 3491 } |
3556 | 3492 |
3557 void HTMLMediaElement::updatePositionNotificationRegistration() | 3493 void HTMLMediaElement::updatePositionNotificationRegistration() |
3558 { | 3494 { |
3559 m_autoplayHelper.updatePositionNotificationRegistration(); | 3495 m_autoplayHelper->updatePositionNotificationRegistration(); |
3560 } | 3496 } |
3561 | 3497 |
3562 // TODO(liberato): remove once autoplay gesture override experiment concludes. | 3498 // TODO(liberato): remove once autoplay gesture override experiment concludes. |
3563 void HTMLMediaElement::triggerAutoplayViewportCheckForTesting() | 3499 void HTMLMediaElement::triggerAutoplayViewportCheckForTesting() |
3564 { | 3500 { |
3565 m_autoplayHelper.triggerAutoplayViewportCheckForTesting(); | 3501 if (FrameView* view = document().view()) |
3502 m_autoplayHelper->positionChanged(view->rootFrameToContents(view->comput eVisibleArea())); | |
3503 m_autoplayHelper->triggerAutoplayViewportCheckForTesting(); | |
3566 } | 3504 } |
3567 | 3505 |
3568 void HTMLMediaElement::clearWeakMembers(Visitor* visitor) | 3506 void HTMLMediaElement::clearWeakMembers(Visitor* visitor) |
3569 { | 3507 { |
3570 if (!Heap::isHeapObjectAlive(m_audioSourceNode)) | 3508 if (!Heap::isHeapObjectAlive(m_audioSourceNode)) |
3571 audioSourceProvider().setClient(nullptr); | 3509 audioSourceProvider().setClient(nullptr); |
3572 } | 3510 } |
3573 | 3511 |
3574 void HTMLMediaElement::AudioSourceProviderImpl::wrap(WebAudioSourceProvider* pro vider) | 3512 void HTMLMediaElement::AudioSourceProviderImpl::wrap(WebAudioSourceProvider* pro vider) |
3575 { | 3513 { |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3624 DEFINE_TRACE(HTMLMediaElement::AudioClientImpl) | 3562 DEFINE_TRACE(HTMLMediaElement::AudioClientImpl) |
3625 { | 3563 { |
3626 visitor->trace(m_client); | 3564 visitor->trace(m_client); |
3627 } | 3565 } |
3628 | 3566 |
3629 DEFINE_TRACE(HTMLMediaElement::AudioSourceProviderImpl) | 3567 DEFINE_TRACE(HTMLMediaElement::AudioSourceProviderImpl) |
3630 { | 3568 { |
3631 visitor->trace(m_client); | 3569 visitor->trace(m_client); |
3632 } | 3570 } |
3633 | 3571 |
3572 HTMLMediaElement::AutoplayHelperClientImpl::~AutoplayHelperClientImpl() | |
3573 { | |
3574 } | |
3575 | |
3576 bool HTMLMediaElement::AutoplayHelperClientImpl::isLegacyViewportType() | |
3577 { | |
3578 return m_element->document().viewportDescription().isLegacyViewportType(); | |
3579 } | |
3580 | |
3581 PageVisibilityState HTMLMediaElement::AutoplayHelperClientImpl::pageVisibilitySt ate() const | |
3582 { | |
3583 return m_element->document().pageVisibilityState(); | |
3584 } | |
3585 | |
3586 String HTMLMediaElement::AutoplayHelperClientImpl::autoplayExperimentMode() cons t | |
3587 { | |
3588 String mode; | |
3589 if (m_element->document().settings()) | |
3590 mode = m_element->document().settings()->autoplayExperimentMode(); | |
3591 | |
3592 return mode; | |
3593 } | |
3594 | |
3595 void HTMLMediaElement::AutoplayHelperClientImpl::setRequestPositionUpdates(bool request) | |
3596 { | |
3597 if (LayoutObject* layoutObject = m_element->layoutObject()) { | |
3598 LayoutMedia* layoutMedia = toLayoutMedia(layoutObject); | |
3599 layoutMedia->setRequestPositionUpdates(request); | |
3600 } | |
3601 } | |
3602 | |
3603 IntRect HTMLMediaElement::AutoplayHelperClientImpl::absoluteBoundingBoxRect() co nst | |
3604 { | |
3605 IntRect result; | |
3606 if (LayoutObject* object = m_element->layoutObject()) | |
3607 result = object->absoluteBoundingBoxRect(); | |
3608 return result; | |
3609 } | |
3610 | |
3634 } // namespace blink | 3611 } // namespace blink |
OLD | NEW |