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