| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights | 2 * Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Apple Inc. All rights |
| 3 * reserved. | 3 * reserved. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
| 7 * are met: | 7 * are met: |
| 8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
| (...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 387 m_loadState(WaitingForSource), | 387 m_loadState(WaitingForSource), |
| 388 m_deferredLoadState(NotDeferred), | 388 m_deferredLoadState(NotDeferred), |
| 389 m_deferredLoadTimer(this, &HTMLMediaElement::deferredLoadTimerFired), | 389 m_deferredLoadTimer(this, &HTMLMediaElement::deferredLoadTimerFired), |
| 390 m_webLayer(nullptr), | 390 m_webLayer(nullptr), |
| 391 m_displayMode(Unknown), | 391 m_displayMode(Unknown), |
| 392 m_officialPlaybackPosition(0), | 392 m_officialPlaybackPosition(0), |
| 393 m_officialPlaybackPositionNeedsUpdate(true), | 393 m_officialPlaybackPositionNeedsUpdate(true), |
| 394 m_fragmentEndTime(std::numeric_limits<double>::quiet_NaN()), | 394 m_fragmentEndTime(std::numeric_limits<double>::quiet_NaN()), |
| 395 m_pendingActionFlags(0), | 395 m_pendingActionFlags(0), |
| 396 m_lockedPendingUserGesture(false), | 396 m_lockedPendingUserGesture(false), |
| 397 m_lockedPendingUserGestureIfCrossOriginExperimentEnabled(true), |
| 397 m_playing(false), | 398 m_playing(false), |
| 398 m_shouldDelayLoadEvent(false), | 399 m_shouldDelayLoadEvent(false), |
| 399 m_haveFiredLoadedData(false), | 400 m_haveFiredLoadedData(false), |
| 400 m_autoplaying(true), | 401 m_autoplaying(true), |
| 401 m_muted(false), | 402 m_muted(false), |
| 402 m_paused(true), | 403 m_paused(true), |
| 403 m_seeking(false), | 404 m_seeking(false), |
| 404 m_sentStalledEvent(false), | 405 m_sentStalledEvent(false), |
| 405 m_ignorePreloadNone(false), | 406 m_ignorePreloadNone(false), |
| 406 m_textTracksVisible(false), | 407 m_textTracksVisible(false), |
| 407 m_shouldPerformAutomaticTrackSelection(true), | 408 m_shouldPerformAutomaticTrackSelection(true), |
| 408 m_tracksAreReady(true), | 409 m_tracksAreReady(true), |
| 409 m_processingPreferenceChange(false), | 410 m_processingPreferenceChange(false), |
| 410 m_playingRemotely(false), | 411 m_playingRemotely(false), |
| 411 m_inOverlayFullscreenVideo(false), | 412 m_inOverlayFullscreenVideo(false), |
| 412 m_mostlyFillingViewport(false), | 413 m_mostlyFillingViewport(false), |
| 413 m_audioTracks(this, AudioTrackList::create(*this)), | 414 m_audioTracks(this, AudioTrackList::create(*this)), |
| 414 m_videoTracks(this, VideoTrackList::create(*this)), | 415 m_videoTracks(this, VideoTrackList::create(*this)), |
| 415 m_textTracks(this, nullptr), | 416 m_textTracks(this, nullptr), |
| 416 m_audioSourceNode(nullptr), | 417 m_audioSourceNode(nullptr), |
| 417 m_autoplayUmaHelper(AutoplayUmaHelper::create(this)), | 418 m_autoplayUmaHelper(AutoplayUmaHelper::create(this)), |
| 418 m_remotePlaybackClient(nullptr), | 419 m_remotePlaybackClient(nullptr), |
| 419 m_autoplayVisibilityObserver(nullptr) { | 420 m_autoplayVisibilityObserver(nullptr) { |
| 420 ThreadState::current()->registerPreFinalizer(this); | 421 ThreadState::current()->registerPreFinalizer(this); |
| 421 | 422 |
| 422 BLINK_MEDIA_LOG << "HTMLMediaElement(" << (void*)this << ")"; | 423 BLINK_MEDIA_LOG << "HTMLMediaElement(" << (void*)this << ")"; |
| 423 | 424 |
| 424 m_lockedPendingUserGesture = computeLockedPendingUserGesture(document); | 425 m_lockedPendingUserGesture = computeLockedPendingUserGesture(document); |
| 426 m_lockedPendingUserGestureIfCrossOriginExperimentEnabled = |
| 427 isDocumentCrossOrigin(document); |
| 425 | 428 |
| 426 LocalFrame* frame = document.frame(); | 429 LocalFrame* frame = document.frame(); |
| 427 if (frame) { | 430 if (frame) { |
| 428 m_remotePlaybackClient = | 431 m_remotePlaybackClient = |
| 429 frame->loader().client()->createWebRemotePlaybackClient(*this); | 432 frame->loader().client()->createWebRemotePlaybackClient(*this); |
| 430 } | 433 } |
| 431 | 434 |
| 432 setHasCustomStyleCallbacks(); | 435 setHasCustomStyleCallbacks(); |
| 433 addElementToDocumentMap(this, &document); | 436 addElementToDocumentMap(this, &document); |
| 434 | 437 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 461 void HTMLMediaElement::didMoveToNewDocument(Document& oldDocument) { | 464 void HTMLMediaElement::didMoveToNewDocument(Document& oldDocument) { |
| 462 BLINK_MEDIA_LOG << "didMoveToNewDocument(" << (void*)this << ")"; | 465 BLINK_MEDIA_LOG << "didMoveToNewDocument(" << (void*)this << ")"; |
| 463 | 466 |
| 464 m_autoplayUmaHelper->didMoveToNewDocument(oldDocument); | 467 m_autoplayUmaHelper->didMoveToNewDocument(oldDocument); |
| 465 // If any experiment is enabled, then we want to enable a user gesture by | 468 // If any experiment is enabled, then we want to enable a user gesture by |
| 466 // default, otherwise the experiment does nothing. | 469 // default, otherwise the experiment does nothing. |
| 467 bool oldDocumentRequiresUserGesture = | 470 bool oldDocumentRequiresUserGesture = |
| 468 computeLockedPendingUserGesture(oldDocument); | 471 computeLockedPendingUserGesture(oldDocument); |
| 469 bool newDocumentRequiresUserGesture = | 472 bool newDocumentRequiresUserGesture = |
| 470 computeLockedPendingUserGesture(document()); | 473 computeLockedPendingUserGesture(document()); |
| 471 if (newDocumentRequiresUserGesture && !oldDocumentRequiresUserGesture) { | 474 if (newDocumentRequiresUserGesture && !oldDocumentRequiresUserGesture) |
| 472 m_lockedPendingUserGesture = true; | 475 m_lockedPendingUserGesture = true; |
| 473 } | |
| 474 | 476 |
| 475 if (m_shouldDelayLoadEvent) { | 477 if (m_shouldDelayLoadEvent) { |
| 476 document().incrementLoadEventDelayCount(); | 478 document().incrementLoadEventDelayCount(); |
| 477 // Note: Keeping the load event delay count increment on oldDocument that | 479 // Note: Keeping the load event delay count increment on oldDocument that |
| 478 // was added when m_shouldDelayLoadEvent was set so that destruction of | 480 // was added when m_shouldDelayLoadEvent was set so that destruction of |
| 479 // m_webMediaPlayer can not cause load event dispatching in oldDocument. | 481 // m_webMediaPlayer can not cause load event dispatching in oldDocument. |
| 480 } else { | 482 } else { |
| 481 // Incrementing the load event delay count so that destruction of | 483 // Incrementing the load event delay count so that destruction of |
| 482 // m_webMediaPlayer can not cause load event dispatching in oldDocument. | 484 // m_webMediaPlayer can not cause load event dispatching in oldDocument. |
| 483 oldDocument.incrementLoadEventDelayCount(); | 485 oldDocument.incrementLoadEventDelayCount(); |
| 484 } | 486 } |
| 485 | 487 |
| 488 if (isDocumentCrossOrigin(document()) && !isDocumentCrossOrigin(oldDocument)) |
| 489 m_lockedPendingUserGestureIfCrossOriginExperimentEnabled = true; |
| 490 |
| 486 removeElementFromDocumentMap(this, &oldDocument); | 491 removeElementFromDocumentMap(this, &oldDocument); |
| 487 addElementToDocumentMap(this, &document()); | 492 addElementToDocumentMap(this, &document()); |
| 488 | 493 |
| 489 // FIXME: This is a temporary fix to prevent this object from causing the | 494 // FIXME: This is a temporary fix to prevent this object from causing the |
| 490 // MediaPlayer to dereference LocalFrame and FrameLoader pointers from the | 495 // MediaPlayer to dereference LocalFrame and FrameLoader pointers from the |
| 491 // previous document. This restarts the load, as if the src attribute had been | 496 // previous document. This restarts the load, as if the src attribute had been |
| 492 // set. A proper fix would provide a mechanism to allow this object to | 497 // set. A proper fix would provide a mechanism to allow this object to |
| 493 // refresh the MediaPlayer's LocalFrame and FrameLoader references on document | 498 // refresh the MediaPlayer's LocalFrame and FrameLoader references on document |
| 494 // changes so that playback can be resumed properly. | 499 // changes so that playback can be resumed properly. |
| 495 m_ignorePreloadNone = false; | 500 m_ignorePreloadNone = false; |
| (...skipping 827 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1323 // didPassCORSAccessCheck() means it was a successful CORS-enabled fetch | 1328 // didPassCORSAccessCheck() means it was a successful CORS-enabled fetch |
| 1324 // (vs. non-CORS-enabled or failed). | 1329 // (vs. non-CORS-enabled or failed). |
| 1325 // taintsCanvas() does checkAccess() on the URL plus allow data sources, | 1330 // taintsCanvas() does checkAccess() on the URL plus allow data sources, |
| 1326 // to ensure that it is not a URL that requires CORS (basically same | 1331 // to ensure that it is not a URL that requires CORS (basically same |
| 1327 // origin). | 1332 // origin). |
| 1328 return hasSingleSecurityOrigin() && | 1333 return hasSingleSecurityOrigin() && |
| 1329 ((webMediaPlayer() && webMediaPlayer()->didPassCORSAccessCheck()) || | 1334 ((webMediaPlayer() && webMediaPlayer()->didPassCORSAccessCheck()) || |
| 1330 !origin->taintsCanvas(currentSrc())); | 1335 !origin->taintsCanvas(currentSrc())); |
| 1331 } | 1336 } |
| 1332 | 1337 |
| 1338 bool HTMLMediaElement::isInCrossOriginFrame() const { |
| 1339 return isDocumentCrossOrigin(document()); |
| 1340 } |
| 1341 |
| 1333 void HTMLMediaElement::startProgressEventTimer() { | 1342 void HTMLMediaElement::startProgressEventTimer() { |
| 1334 if (m_progressEventTimer.isActive()) | 1343 if (m_progressEventTimer.isActive()) |
| 1335 return; | 1344 return; |
| 1336 | 1345 |
| 1337 m_previousProgressTime = WTF::currentTime(); | 1346 m_previousProgressTime = WTF::currentTime(); |
| 1338 // 350ms is not magic, it is in the spec! | 1347 // 350ms is not magic, it is in the spec! |
| 1339 m_progressEventTimer.startRepeating(0.350, BLINK_FROM_HERE); | 1348 m_progressEventTimer.startRepeating(0.350, BLINK_FROM_HERE); |
| 1340 } | 1349 } |
| 1341 | 1350 |
| 1342 void HTMLMediaElement::waitForSourceChange() { | 1351 void HTMLMediaElement::waitForSourceChange() { |
| (...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1684 scheduleEvent(EventTypeNames::canplay); | 1693 scheduleEvent(EventTypeNames::canplay); |
| 1685 if (isPotentiallyPlaying) | 1694 if (isPotentiallyPlaying) |
| 1686 scheduleNotifyPlaying(); | 1695 scheduleNotifyPlaying(); |
| 1687 } | 1696 } |
| 1688 | 1697 |
| 1689 // Check for autoplay, and record metrics about it if needed. | 1698 // Check for autoplay, and record metrics about it if needed. |
| 1690 if (shouldAutoplay()) { | 1699 if (shouldAutoplay()) { |
| 1691 m_autoplayUmaHelper->onAutoplayInitiated(AutoplaySource::Attribute); | 1700 m_autoplayUmaHelper->onAutoplayInitiated(AutoplaySource::Attribute); |
| 1692 | 1701 |
| 1693 if (!isGestureNeededForPlayback()) { | 1702 if (!isGestureNeededForPlayback()) { |
| 1703 if (isGestureNeededForPlaybackIfCrossOriginExperimentEnabled()) { |
| 1704 m_autoplayUmaHelper->recordCrossOriginAutoplayResult( |
| 1705 CrossOriginAutoplayResult::AutoplayBlocked); |
| 1706 } else { |
| 1707 m_autoplayUmaHelper->recordCrossOriginAutoplayResult( |
| 1708 CrossOriginAutoplayResult::AutoplayAllowed); |
| 1709 } |
| 1694 if (isHTMLVideoElement() && muted() && | 1710 if (isHTMLVideoElement() && muted() && |
| 1695 RuntimeEnabledFeatures::autoplayMutedVideosEnabled()) { | 1711 RuntimeEnabledFeatures::autoplayMutedVideosEnabled()) { |
| 1696 // We might end up in a situation where the previous | 1712 // We might end up in a situation where the previous |
| 1697 // observer didn't had time to fire yet. We can avoid | 1713 // observer didn't had time to fire yet. We can avoid |
| 1698 // creating a new one in this case. | 1714 // creating a new one in this case. |
| 1699 if (!m_autoplayVisibilityObserver) { | 1715 if (!m_autoplayVisibilityObserver) { |
| 1700 m_autoplayVisibilityObserver = new ElementVisibilityObserver( | 1716 m_autoplayVisibilityObserver = new ElementVisibilityObserver( |
| 1701 this, | 1717 this, |
| 1702 WTF::bind(&HTMLMediaElement::onVisibilityChangedForAutoplay, | 1718 WTF::bind(&HTMLMediaElement::onVisibilityChangedForAutoplay, |
| 1703 wrapWeakPersistent(this))); | 1719 wrapWeakPersistent(this))); |
| 1704 m_autoplayVisibilityObserver->start(); | 1720 m_autoplayVisibilityObserver->start(); |
| 1705 } | 1721 } |
| 1706 } else { | 1722 } else { |
| 1707 m_paused = false; | 1723 m_paused = false; |
| 1708 scheduleEvent(EventTypeNames::play); | 1724 scheduleEvent(EventTypeNames::play); |
| 1709 scheduleNotifyPlaying(); | 1725 scheduleNotifyPlaying(); |
| 1710 m_autoplaying = false; | 1726 m_autoplaying = false; |
| 1711 } | 1727 } |
| 1728 } else { |
| 1729 m_autoplayUmaHelper->recordCrossOriginAutoplayResult( |
| 1730 CrossOriginAutoplayResult::AutoplayBlocked); |
| 1712 } | 1731 } |
| 1713 } | 1732 } |
| 1714 | 1733 |
| 1715 scheduleEvent(EventTypeNames::canplaythrough); | 1734 scheduleEvent(EventTypeNames::canplaythrough); |
| 1716 | 1735 |
| 1717 shouldUpdateDisplayState = true; | 1736 shouldUpdateDisplayState = true; |
| 1718 } | 1737 } |
| 1719 | 1738 |
| 1720 if (shouldUpdateDisplayState) | 1739 if (shouldUpdateDisplayState) |
| 1721 updateDisplayState(); | 1740 updateDisplayState(); |
| (...skipping 456 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2178 if (!UserGestureIndicator::processingUserGesture()) { | 2197 if (!UserGestureIndicator::processingUserGesture()) { |
| 2179 m_autoplayUmaHelper->onAutoplayInitiated(AutoplaySource::Method); | 2198 m_autoplayUmaHelper->onAutoplayInitiated(AutoplaySource::Method); |
| 2180 if (isGestureNeededForPlayback()) { | 2199 if (isGestureNeededForPlayback()) { |
| 2181 // If we're already playing, then this play would do nothing anyway. | 2200 // If we're already playing, then this play would do nothing anyway. |
| 2182 // Call playInternal to handle scheduling the promise resolution. | 2201 // Call playInternal to handle scheduling the promise resolution. |
| 2183 if (!m_paused) { | 2202 if (!m_paused) { |
| 2184 playInternal(); | 2203 playInternal(); |
| 2185 return nullptr; | 2204 return nullptr; |
| 2186 } | 2205 } |
| 2187 | 2206 |
| 2207 m_autoplayUmaHelper->recordCrossOriginAutoplayResult( |
| 2208 CrossOriginAutoplayResult::AutoplayBlocked); |
| 2188 String message = ExceptionMessages::failedToExecute( | 2209 String message = ExceptionMessages::failedToExecute( |
| 2189 "play", "HTMLMediaElement", | 2210 "play", "HTMLMediaElement", |
| 2190 "API can only be initiated by a user gesture."); | 2211 "API can only be initiated by a user gesture."); |
| 2191 document().addConsoleMessage(ConsoleMessage::create( | 2212 document().addConsoleMessage(ConsoleMessage::create( |
| 2192 JSMessageSource, WarningMessageLevel, message)); | 2213 JSMessageSource, WarningMessageLevel, message)); |
| 2193 return NotAllowedError; | 2214 return NotAllowedError; |
| 2215 } else { |
| 2216 if (isGestureNeededForPlaybackIfCrossOriginExperimentEnabled()) { |
| 2217 m_autoplayUmaHelper->recordCrossOriginAutoplayResult( |
| 2218 CrossOriginAutoplayResult::AutoplayBlocked); |
| 2219 } else { |
| 2220 m_autoplayUmaHelper->recordCrossOriginAutoplayResult( |
| 2221 CrossOriginAutoplayResult::AutoplayAllowed); |
| 2222 } |
| 2194 } | 2223 } |
| 2195 } else { | 2224 } else { |
| 2225 m_autoplayUmaHelper->recordCrossOriginAutoplayResult( |
| 2226 CrossOriginAutoplayResult::PlayedWithGesture); |
| 2196 UserGestureIndicator::utilizeUserGesture(); | 2227 UserGestureIndicator::utilizeUserGesture(); |
| 2197 unlockUserGesture(); | 2228 unlockUserGesture(); |
| 2198 } | 2229 } |
| 2199 | 2230 |
| 2200 if (m_error && m_error->code() == MediaError::kMediaErrSrcNotSupported) | 2231 if (m_error && m_error->code() == MediaError::kMediaErrSrcNotSupported) |
| 2201 return NotSupportedError; | 2232 return NotSupportedError; |
| 2202 | 2233 |
| 2203 playInternal(); | 2234 playInternal(); |
| 2204 | 2235 |
| 2205 return nullptr; | 2236 return nullptr; |
| (...skipping 1573 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3779 if (videoTracks().length() > 0 && videoTracks().selectedIndex() == -1) | 3810 if (videoTracks().length() > 0 && videoTracks().selectedIndex() == -1) |
| 3780 videoTracks().anonymousIndexedGetter(0)->setSelected(true); | 3811 videoTracks().anonymousIndexedGetter(0)->setSelected(true); |
| 3781 } | 3812 } |
| 3782 | 3813 |
| 3783 bool HTMLMediaElement::isLockedPendingUserGesture() const { | 3814 bool HTMLMediaElement::isLockedPendingUserGesture() const { |
| 3784 return m_lockedPendingUserGesture; | 3815 return m_lockedPendingUserGesture; |
| 3785 } | 3816 } |
| 3786 | 3817 |
| 3787 void HTMLMediaElement::unlockUserGesture() { | 3818 void HTMLMediaElement::unlockUserGesture() { |
| 3788 m_lockedPendingUserGesture = false; | 3819 m_lockedPendingUserGesture = false; |
| 3820 m_lockedPendingUserGestureIfCrossOriginExperimentEnabled = false; |
| 3789 } | 3821 } |
| 3790 | 3822 |
| 3791 bool HTMLMediaElement::isGestureNeededForPlayback() const { | 3823 bool HTMLMediaElement::isGestureNeededForPlayback() const { |
| 3792 if (!m_lockedPendingUserGesture) | 3824 if (!m_lockedPendingUserGesture) |
| 3793 return false; | 3825 return false; |
| 3794 | 3826 |
| 3827 return isGestureNeededForPlaybackIfPendingUserGestureIsLocked(); |
| 3828 } |
| 3829 |
| 3830 bool HTMLMediaElement:: |
| 3831 isGestureNeededForPlaybackIfCrossOriginExperimentEnabled() const { |
| 3832 if (!m_lockedPendingUserGestureIfCrossOriginExperimentEnabled) |
| 3833 return false; |
| 3834 |
| 3835 return isGestureNeededForPlaybackIfPendingUserGestureIsLocked(); |
| 3836 } |
| 3837 |
| 3838 bool HTMLMediaElement::isGestureNeededForPlaybackIfPendingUserGestureIsLocked() |
| 3839 const { |
| 3795 if (loadType() == WebMediaPlayer::LoadTypeMediaStream) | 3840 if (loadType() == WebMediaPlayer::LoadTypeMediaStream) |
| 3796 return false; | 3841 return false; |
| 3797 | 3842 |
| 3798 // We want to allow muted video to autoplay if: | 3843 // We want to allow muted video to autoplay if: |
| 3799 // - the flag is enabled; | 3844 // - the flag is enabled; |
| 3800 // - Data Saver is not enabled; | 3845 // - Data Saver is not enabled; |
| 3801 // - Preload was not disabled (low end devices); | 3846 // - Preload was not disabled (low end devices); |
| 3802 // - Autoplay is enabled in settings; | 3847 // - Autoplay is enabled in settings; |
| 3803 if (isHTMLVideoElement() && muted() && | 3848 if (isHTMLVideoElement() && muted() && |
| 3804 RuntimeEnabledFeatures::autoplayMutedVideosEnabled() && | 3849 RuntimeEnabledFeatures::autoplayMutedVideosEnabled() && |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4065 kMostlyFillViewportBecomeStableSeconds, BLINK_FROM_HERE); | 4110 kMostlyFillViewportBecomeStableSeconds, BLINK_FROM_HERE); |
| 4066 } | 4111 } |
| 4067 | 4112 |
| 4068 void HTMLMediaElement::viewportFillDebouncerTimerFired(TimerBase*) { | 4113 void HTMLMediaElement::viewportFillDebouncerTimerFired(TimerBase*) { |
| 4069 m_mostlyFillingViewport = true; | 4114 m_mostlyFillingViewport = true; |
| 4070 if (m_webMediaPlayer) | 4115 if (m_webMediaPlayer) |
| 4071 m_webMediaPlayer->becameDominantVisibleContent(m_mostlyFillingViewport); | 4116 m_webMediaPlayer->becameDominantVisibleContent(m_mostlyFillingViewport); |
| 4072 } | 4117 } |
| 4073 | 4118 |
| 4074 } // namespace blink | 4119 } // namespace blink |
| OLD | NEW |