WebKit Bugzilla
Attachment 340045 Details for
Bug 185487
: Media continues loading after rendered invisible (removed from DOM; scrolled off screen)
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch for landing
bug-185487-20180509155321.patch (text/plain), 44.29 KB, created by
Jer Noble
on 2018-05-09 15:53:22 PDT
(
hide
)
Description:
Patch for landing
Filename:
MIME Type:
Creator:
Jer Noble
Created:
2018-05-09 15:53:22 PDT
Size:
44.29 KB
patch
obsolete
>Subversion Revision: 231516 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index cf4f8489524a7634713977a71f0547829569845c..7697ee20addd96fb1a8ca38231a14b9fd73ede73 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,82 @@ >+2018-05-09 Jer Noble <jer.noble@apple.com> >+ >+ Media continues loading after rendered invisible (removed from DOM; scrolled off screen) >+ https://bugs.webkit.org/show_bug.cgi?id=185487 >+ >+ Reviewed by Eric Carlson. >+ >+ Test: media/video-buffering-allowed.html >+ >+ When a media element is removed from the dom (e.g. through innerHTML=""), it doesn't >+ necessarily stop loading media data; it will continue to do so until its destructor is >+ called through garbage collection. Similarly, when a media element is rendered not-visible >+ by being scrolled off-screen or being made display:none, media loading continues. There >+ are legitimate use cases for out-of-DOM media loading, so only temporarily block loading >+ when the element transitions out of the document. Similarly, only block loading for non-visible >+ media elements when returning from the "page is hidden" state, and only until the media >+ element is asked to play or is otherwise made visible. >+ >+ Note: this refactors a lot of code out of PlatformMediaSession and into MediaElementSession, >+ since this code is specific to "media elements". >+ >+ * html/HTMLMediaElement.cpp: >+ (WebCore::HTMLMediaElement::HTMLMediaElement): >+ (WebCore::HTMLMediaElement::insertedIntoAncestor): >+ (WebCore::HTMLMediaElement::removedFromAncestor): >+ (WebCore::HTMLMediaElement::playInternal): >+ (WebCore::HTMLMediaElement::stopWithoutDestroyingMediaPlayer): >+ (WebCore::HTMLMediaElement::resume): >+ (WebCore::HTMLMediaElement::visibilityStateChanged): >+ (WebCore::HTMLMediaElement::createMediaPlayer): >+ (WebCore::HTMLMediaElement::setShouldBufferData): >+ (WebCore::HTMLMediaElement::purgeBufferedDataIfPossible): >+ (WebCore::HTMLMediaElement::isVisibleInViewportChanged): >+ (WebCore::HTMLMediaElement::fullscreenModeChanged): >+ (WebCore::HTMLMediaElement::setInActiveDocument): >+ * html/HTMLMediaElement.h: >+ (WebCore::HTMLMediaElement::shouldBufferData const): >+ (WebCore::HTMLMediaElement::elementIsHidden const): >+ * html/MediaElementSession.cpp: >+ (WebCore::MediaElementSession::MediaElementSession): >+ (WebCore::MediaElementSession::clientWillBeginAutoplaying): >+ (WebCore::MediaElementSession::clientWillBeginPlayback): >+ (WebCore::MediaElementSession::clientWillPausePlayback): >+ (WebCore::MediaElementSession::visibilityChanged): >+ (WebCore::MediaElementSession::isVisibleInViewportChanged): >+ (WebCore::MediaElementSession::inActiveDocumentChanged): >+ (WebCore::MediaElementSession::scheduleClientDataBufferingCheck): >+ (WebCore::MediaElementSession::clientDataBufferingTimerFired): >+ (WebCore::MediaElementSession::updateClientDataBuffering): >+ (WebCore::MediaElementSession::dataBufferingPermitted const): >+ (WebCore::MediaElementSession::wantsToObserveViewportVisibilityForAutoplay const): >+ * html/MediaElementSession.h: >+ * platform/audio/PlatformMediaSession.cpp: >+ (WebCore::PlatformMediaSession::PlatformMediaSession): >+ (WebCore::PlatformMediaSession::clientWillBeginAutoplaying): >+ (WebCore::PlatformMediaSession::clientWillBeginPlayback): >+ (WebCore::PlatformMediaSession::clientWillPausePlayback): >+ (): Deleted. >+ (WebCore::PlatformMediaSession::visibilityChanged): Deleted. >+ (WebCore::PlatformMediaSession::scheduleClientDataBufferingCheck): Deleted. >+ (WebCore::PlatformMediaSession::clientDataBufferingTimerFired): Deleted. >+ (WebCore::PlatformMediaSession::updateClientDataBuffering): Deleted. >+ (WebCore::PlatformMediaSession::isHidden const): Deleted. >+ * platform/audio/PlatformMediaSession.h: >+ (WebCore::PlatformMediaSessionClient::setShouldBufferData): Deleted. >+ (WebCore::PlatformMediaSessionClient::elementIsHidden const): Deleted. >+ * platform/audio/PlatformMediaSessionManager.cpp: >+ (WebCore::PlatformMediaSessionManager::sessionCanLoadMedia const): Deleted. >+ * platform/audio/PlatformMediaSessionManager.h: >+ * platform/audio/ios/MediaSessionManagerIOS.h: >+ * platform/audio/ios/MediaSessionManagerIOS.mm: >+ (WebCore::MediaSessionManageriOS::sessionCanLoadMedia const): Deleted. >+ * rendering/RenderVideo.cpp: >+ (WebCore::RenderVideo::willBeDestroyed): >+ * testing/Internals.cpp: >+ (WebCore::Internals::elementShouldBufferData): >+ * testing/Internals.h: >+ * testing/Internals.idl: >+ > 2018-05-08 Jer Noble <jer.noble@apple.com> > > Unreviewed build fix; add missing function definition. >diff --git a/Source/WebCore/html/HTMLMediaElement.cpp b/Source/WebCore/html/HTMLMediaElement.cpp >index 96cf8b9b14a0e91fb480e2ce303d3682c03efa2b..7b9fa0809ab02e8ab9657b049e3d640274b1861f 100644 >--- a/Source/WebCore/html/HTMLMediaElement.cpp >+++ b/Source/WebCore/html/HTMLMediaElement.cpp >@@ -477,6 +477,7 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tagName, Document& docum > , m_completelyLoaded(false) > , m_havePreparedToPlay(false) > , m_parsingInProgress(createdByParser) >+ , m_shouldBufferData(true) > , m_elementIsHidden(document.hidden()) > , m_creatingControls(false) > , m_receivedLayoutSizeChanged(false) >@@ -926,7 +927,7 @@ Node::InsertedIntoAncestorResult HTMLMediaElement::insertedIntoAncestor(Insertio > > HTMLElement::insertedIntoAncestor(insertionType, parentOfInsertedTree); > if (insertionType.connectedToDocument) >- m_inActiveDocument = true; >+ setInActiveDocument(true); > > return InsertedIntoAncestorResult::NeedsPostInsertionCallback; > } >@@ -978,7 +979,7 @@ void HTMLMediaElement::removedFromAncestor(RemovalType removalType, ContainerNod > { > INFO_LOG(LOGIDENTIFIER); > >- m_inActiveDocument = false; >+ setInActiveDocument(false); > if (removalType.disconnectedFromDocument) { > // Pause asynchronously to let the operation that removed us finish, in case we get inserted back into a document. > m_pauseAfterDetachedTaskQueue.enqueueTask(std::bind(&HTMLMediaElement::pauseAfterDetachedTask, this)); >@@ -3467,7 +3468,7 @@ void HTMLMediaElement::playInternal() > ALWAYS_LOG(LOGIDENTIFIER, " returning because of interruption"); > return; > } >- >+ > // 4.8.10.9. Playing the media resource > if (!m_player || m_networkState == NETWORK_EMPTY) > selectMediaResource(); >@@ -5520,7 +5521,7 @@ void HTMLMediaElement::stopWithoutDestroyingMediaPlayer() > setPreparedToReturnVideoLayerToInline(true); > > updatePlaybackControlsManager(); >- m_inActiveDocument = false; >+ setInActiveDocument(false); > > // Stop the playback without generating events > setPlaying(false); >@@ -5600,7 +5601,7 @@ void HTMLMediaElement::resume() > { > INFO_LOG(LOGIDENTIFIER); > >- m_inActiveDocument = true; >+ setInActiveDocument(true); > > m_asyncEventQueue.resume(); > >@@ -5638,8 +5639,13 @@ void HTMLMediaElement::mediaVolumeDidChange() > > void HTMLMediaElement::visibilityStateChanged() > { >- m_elementIsHidden = document().hidden() && m_videoFullscreenMode != VideoFullscreenModePictureInPicture; >+ bool elementIsHidden = document().hidden() && m_videoFullscreenMode != VideoFullscreenModePictureInPicture; >+ if (elementIsHidden == m_elementIsHidden) >+ return; >+ >+ m_elementIsHidden = elementIsHidden; > INFO_LOG(LOGIDENTIFIER, "visible = ", !m_elementIsHidden); >+ > updateSleepDisabling(); > m_mediaSession->visibilityChanged(); > if (m_player) >@@ -6499,6 +6505,7 @@ void HTMLMediaElement::createMediaPlayer() > forgetResourceSpecificTracks(); > #endif > m_player = MediaPlayer::create(*this); >+ m_player->setShouldBufferData(m_shouldBufferData); > scheduleUpdatePlaybackControlsManager(); > > #if ENABLE(WEB_AUDIO) >@@ -7660,6 +7667,10 @@ bool HTMLMediaElement::doesHaveAttribute(const AtomicString& attribute, AtomicSt > > void HTMLMediaElement::setShouldBufferData(bool shouldBuffer) > { >+ if (shouldBuffer == m_shouldBufferData) >+ return; >+ >+ m_shouldBufferData = shouldBuffer; > if (m_player) > m_player->setShouldBufferData(shouldBuffer); > } >@@ -7667,7 +7678,7 @@ void HTMLMediaElement::setShouldBufferData(bool shouldBuffer) > void HTMLMediaElement::purgeBufferedDataIfPossible() > { > #if PLATFORM(IOS) >- if (!MemoryPressureHandler::singleton().isUnderMemoryPressure() && PlatformMediaSessionManager::sharedManager().sessionCanLoadMedia(*m_mediaSession)) >+ if (!MemoryPressureHandler::singleton().isUnderMemoryPressure() && m_mediaSession->dataBufferingPermitted()) > return; > > if (m_isPlayingToWirelessTarget) { >@@ -7775,6 +7786,7 @@ bool HTMLMediaElement::isVideoTooSmallForInlinePlayback() > void HTMLMediaElement::isVisibleInViewportChanged() > { > m_visibilityChangeTaskQueue.enqueueTask([this] { >+ m_mediaSession->isVisibleInViewportChanged(); > updateShouldAutoplay(); > scheduleUpdatePlaybackControlsManager(); > }); >@@ -7874,7 +7886,6 @@ void HTMLMediaElement::fullscreenModeChanged(VideoFullscreenMode mode) > > m_videoFullscreenMode = mode; > visibilityStateChanged(); >- m_mediaSession->scheduleClientDataBufferingCheck(); > scheduleUpdatePlaybackControlsManager(); > } > >@@ -7907,6 +7918,15 @@ void HTMLMediaElement::applicationDidBecomeActive() > m_player->applicationDidBecomeActive(); > } > >+void HTMLMediaElement::setInActiveDocument(bool inActiveDocument) >+{ >+ if (inActiveDocument == m_inActiveDocument) >+ return; >+ >+ m_inActiveDocument = inActiveDocument; >+ m_mediaSession->inActiveDocumentChanged(); >+} >+ > } > > #endif >diff --git a/Source/WebCore/html/HTMLMediaElement.h b/Source/WebCore/html/HTMLMediaElement.h >index 04c59afb49217f26102deab5af69e8a5ca45f391..e57271c028a7f1770cf70bf63acfa0be2ba58b30 100644 >--- a/Source/WebCore/html/HTMLMediaElement.h >+++ b/Source/WebCore/html/HTMLMediaElement.h >@@ -265,7 +265,8 @@ public: > > WEBCORE_EXPORT void play() override; > WEBCORE_EXPORT void pause() override; >- void setShouldBufferData(bool) override; >+ void setShouldBufferData(bool); >+ WEBCORE_EXPORT bool shouldBufferData() const { return m_shouldBufferData; } > WEBCORE_EXPORT void fastSeek(double); > double minFastReverseRate() const; > double maxFastForwardRate() const; >@@ -277,7 +278,7 @@ public: > WEBCORE_EXPORT bool webkitClosedCaptionsVisible() const; > WEBCORE_EXPORT void setWebkitClosedCaptionsVisible(bool); > >- bool elementIsHidden() const override { return m_elementIsHidden; } >+ bool elementIsHidden() const { return m_elementIsHidden; } > > #if ENABLE(MEDIA_STATISTICS) > // Statistics >@@ -912,6 +913,8 @@ private: > void applicationWillResignActive() final; > void applicationDidBecomeActive() final; > >+ void setInActiveDocument(bool); >+ > #if !RELEASE_LOG_DISABLED > const char* logClassName() const final { return "HTMLMediaElement"; } > >@@ -1064,7 +1067,9 @@ private: > bool m_completelyLoaded : 1; > bool m_havePreparedToPlay : 1; > bool m_parsingInProgress : 1; >+ bool m_shouldBufferData : 1; > bool m_elementIsHidden : 1; >+ bool m_elementWasRemovedFromDOM : 1; > bool m_creatingControls : 1; > bool m_receivedLayoutSizeChanged : 1; > bool m_hasEverNotifiedAboutPlaying : 1; >diff --git a/Source/WebCore/html/MediaElementSession.cpp b/Source/WebCore/html/MediaElementSession.cpp >index 6728af5bc42dd5f2228246862082837dda2cade7..7c753aaf20ea33fed3af75a2dfdb5f7a92307dff 100644 >--- a/Source/WebCore/html/MediaElementSession.cpp >+++ b/Source/WebCore/html/MediaElementSession.cpp >@@ -56,6 +56,7 @@ > > namespace WebCore { > >+static const Seconds clientDataBufferingTimerThrottleDelay { 100_ms }; > static const Seconds elementMainContentCheckInterval { 250_ms }; > > static bool isElementRectMostlyInMainFrame(const HTMLMediaElement&); >@@ -105,6 +106,7 @@ MediaElementSession::MediaElementSession(HTMLMediaElement& element) > , m_targetAvailabilityChangedTimer(*this, &MediaElementSession::targetAvailabilityChangedTimerFired) > #endif > , m_mainContentCheckTimer(*this, &MediaElementSession::mainContentCheckTimerFired) >+ , m_clientDataBufferingTimer(*this, &MediaElementSession::clientDataBufferingTimerFired) > { > } > >@@ -126,6 +128,86 @@ void MediaElementSession::unregisterWithDocument(Document& document) > #endif > } > >+void MediaElementSession::clientWillBeginAutoplaying() >+{ >+ PlatformMediaSession::clientWillBeginAutoplaying(); >+ m_elementWasRemovedFromDOM = false; >+ updateClientDataBuffering(); >+} >+ >+bool MediaElementSession::clientWillBeginPlayback() >+{ >+ if (!PlatformMediaSession::clientWillBeginPlayback()) >+ return false; >+ >+ m_elementWasRemovedFromDOM = false; >+ updateClientDataBuffering(); >+ return true; >+} >+ >+bool MediaElementSession::clientWillPausePlayback() >+{ >+ if (!PlatformMediaSession::clientWillPausePlayback()) >+ return false; >+ >+ updateClientDataBuffering(); >+ return true; >+} >+ >+void MediaElementSession::visibilityChanged() >+{ >+ scheduleClientDataBufferingCheck(); >+ >+ if (m_element.elementIsHidden() && !m_element.isFullscreen()) >+ m_elementIsHiddenUntilVisibleInViewport = true; >+} >+ >+void MediaElementSession::isVisibleInViewportChanged() >+{ >+ scheduleClientDataBufferingCheck(); >+ >+ if (m_element.isFullscreen() || m_element.isVisibleInViewport()) >+ m_elementIsHiddenUntilVisibleInViewport = false; >+} >+ >+void MediaElementSession::inActiveDocumentChanged() >+{ >+ m_elementWasRemovedFromDOM = !m_element.inActiveDocument(); >+ scheduleClientDataBufferingCheck(); >+} >+ >+void MediaElementSession::scheduleClientDataBufferingCheck() >+{ >+ if (!m_clientDataBufferingTimer.isActive()) >+ m_clientDataBufferingTimer.startOneShot(clientDataBufferingTimerThrottleDelay); >+} >+ >+void MediaElementSession::clientDataBufferingTimerFired() >+{ >+ LOG(Media, "PlatformMediaSession::clientDataBufferingTimerFired(%p)- visible = %s", this, m_element.elementIsHidden() ? "false" : "true"); >+ >+ updateClientDataBuffering(); >+ >+#if PLATFORM(IOS) >+ PlatformMediaSessionManager::sharedManager().configureWireLessTargetMonitoring(); >+#endif >+ >+ if (state() != Playing || !m_element.elementIsHidden()) >+ return; >+ >+ PlatformMediaSessionManager::SessionRestrictions restrictions = PlatformMediaSessionManager::sharedManager().restrictions(mediaType()); >+ if ((restrictions & PlatformMediaSessionManager::BackgroundTabPlaybackRestricted) == PlatformMediaSessionManager::BackgroundTabPlaybackRestricted) >+ pauseSession(); >+} >+ >+void MediaElementSession::updateClientDataBuffering() >+{ >+ if (m_clientDataBufferingTimer.isActive()) >+ m_clientDataBufferingTimer.stop(); >+ >+ m_element.setShouldBufferData(dataBufferingPermitted()); >+} >+ > void MediaElementSession::addBehaviorRestriction(BehaviorRestrictions restriction) > { > LOG(Media, "MediaElementSession::addBehaviorRestriction - adding %s", restrictionName(restriction).utf8().data()); >@@ -263,6 +345,23 @@ bool MediaElementSession::dataLoadingPermitted() const > return true; > } > >+bool MediaElementSession::dataBufferingPermitted() const >+{ >+ if (isSuspended()) >+ return false; >+ >+ if (state() == PlatformMediaSession::Playing) >+ return true; >+ >+ if (shouldOverrideBackgroundLoadingRestriction()) >+ return true; >+ >+ if (m_elementIsHiddenUntilVisibleInViewport || m_elementWasRemovedFromDOM || m_element.elementIsHidden()) >+ return false; >+ >+ return true; >+} >+ > bool MediaElementSession::fullscreenPermitted() const > { > if (m_restrictions & RequireUserGestureForFullscreen && !m_element.document().processingUserGestureForMedia()) { >@@ -406,9 +505,7 @@ bool MediaElementSession::wantsToObserveViewportVisibilityForMediaControls() con > > bool MediaElementSession::wantsToObserveViewportVisibilityForAutoplay() const > { >- if (!m_element.isVideo()) >- return false; >- return hasBehaviorRestriction(InvisibleAutoplayNotPermitted) || hasBehaviorRestriction(OverrideUserGestureRequirementForMainContent); >+ return true; > } > > #if ENABLE(WIRELESS_PLAYBACK_TARGET) >@@ -662,7 +759,7 @@ bool MediaElementSession::allowsPictureInPicture() const > #if PLATFORM(IOS) > bool MediaElementSession::requiresPlaybackTargetRouteMonitoring() const > { >- return m_hasPlaybackTargetAvailabilityListeners && !client().elementIsHidden(); >+ return m_hasPlaybackTargetAvailabilityListeners && !m_element.elementIsHidden(); > } > #endif > >diff --git a/Source/WebCore/html/MediaElementSession.h b/Source/WebCore/html/MediaElementSession.h >index 31af7604b964ac9b397a1d7fd59de485722b798f..666e10d57b51d0fafbaac9be35d8e7320763111d 100644 >--- a/Source/WebCore/html/MediaElementSession.h >+++ b/Source/WebCore/html/MediaElementSession.h >@@ -65,9 +65,18 @@ public: > void registerWithDocument(Document&); > void unregisterWithDocument(Document&); > >+ void clientWillBeginAutoplaying() final; >+ bool clientWillBeginPlayback() final; >+ bool clientWillPausePlayback() final; >+ >+ void visibilityChanged(); >+ void isVisibleInViewportChanged(); >+ void inActiveDocumentChanged(); >+ > SuccessOr<MediaPlaybackDenialReason> playbackPermitted() const; > bool autoplayPermitted() const; > bool dataLoadingPermitted() const; >+ bool dataBufferingPermitted() const; > bool fullscreenPermitted() const; > bool pageAllowsDataLoading() const; > bool pageAllowsPlaybackAfterResuming() const; >@@ -172,9 +181,16 @@ private: > bool updateIsMainContent() const; > void mainContentCheckTimerFired(); > >+ void scheduleClientDataBufferingCheck(); >+ void clientDataBufferingTimerFired(); >+ void updateClientDataBuffering(); >+ > HTMLMediaElement& m_element; > BehaviorRestrictions m_restrictions; > >+ bool m_elementIsHiddenUntilVisibleInViewport { false }; >+ bool m_elementWasRemovedFromDOM { false }; >+ > #if ENABLE(WIRELESS_PLAYBACK_TARGET) > mutable Timer m_targetAvailabilityChangedTimer; > RefPtr<MediaPlaybackTarget> m_playbackTarget; >@@ -189,6 +205,7 @@ private: > > mutable bool m_isMainContent { false }; > Timer m_mainContentCheckTimer; >+ Timer m_clientDataBufferingTimer; > }; > > } // namespace WebCore >diff --git a/Source/WebCore/platform/audio/PlatformMediaSession.cpp b/Source/WebCore/platform/audio/PlatformMediaSession.cpp >index 27ab225f38da450fc8884e4c93c7c8518703ae4d..0aa0832a724d4e32422b2e13bc4710ca6b7b8083 100644 >--- a/Source/WebCore/platform/audio/PlatformMediaSession.cpp >+++ b/Source/WebCore/platform/audio/PlatformMediaSession.cpp >@@ -34,8 +34,6 @@ > > namespace WebCore { > >-static const Seconds clientDataBufferingTimerThrottleDelay { 100_ms }; >- > #if !LOG_DISABLED > static const char* stateName(PlatformMediaSession::State state) > { >@@ -77,7 +75,6 @@ std::unique_ptr<PlatformMediaSession> PlatformMediaSession::create(PlatformMedia > > PlatformMediaSession::PlatformMediaSession(PlatformMediaSessionClient& client) > : m_client(client) >- , m_clientDataBufferingTimer(*this, &PlatformMediaSession::clientDataBufferingTimerFired) > , m_state(Idle) > , m_stateToRestore(Idle) > , m_notifyingClient(false) >@@ -156,7 +153,6 @@ void PlatformMediaSession::clientWillBeginAutoplaying() > } > > setState(Autoplaying); >- updateClientDataBuffering(); > } > > bool PlatformMediaSession::clientWillBeginPlayback() >@@ -171,7 +167,6 @@ bool PlatformMediaSession::clientWillBeginPlayback() > } > > setState(Playing); >- updateClientDataBuffering(); > return true; > } > >@@ -189,7 +184,6 @@ bool PlatformMediaSession::clientWillPausePlayback() > > setState(Paused); > PlatformMediaSessionManager::sharedManager().sessionWillEndPlayback(*this); >- scheduleClientDataBufferingCheck(); > return true; > } > >@@ -253,53 +247,11 @@ bool PlatformMediaSession::supportsSeeking() const > return m_client.supportsSeeking(); > } > >-void PlatformMediaSession::visibilityChanged() >-{ >- scheduleClientDataBufferingCheck(); >-} >- >-void PlatformMediaSession::scheduleClientDataBufferingCheck() >-{ >- if (!m_clientDataBufferingTimer.isActive()) >- m_clientDataBufferingTimer.startOneShot(clientDataBufferingTimerThrottleDelay); >-} >- >-void PlatformMediaSession::clientDataBufferingTimerFired() >-{ >- LOG(Media, "PlatformMediaSession::clientDataBufferingTimerFired(%p)- visible = %s", this, m_client.elementIsHidden() ? "false" : "true"); >- >- updateClientDataBuffering(); >- >-#if PLATFORM(IOS) >- PlatformMediaSessionManager::sharedManager().configureWireLessTargetMonitoring(); >-#endif >- >- if (m_state != Playing || !m_client.elementIsHidden()) >- return; >- >- PlatformMediaSessionManager::SessionRestrictions restrictions = PlatformMediaSessionManager::sharedManager().restrictions(mediaType()); >- if ((restrictions & PlatformMediaSessionManager::BackgroundTabPlaybackRestricted) == PlatformMediaSessionManager::BackgroundTabPlaybackRestricted) >- pauseSession(); >-} >- >-void PlatformMediaSession::updateClientDataBuffering() >-{ >- if (m_clientDataBufferingTimer.isActive()) >- m_clientDataBufferingTimer.stop(); >- >- m_client.setShouldBufferData(PlatformMediaSessionManager::sharedManager().sessionCanLoadMedia(*this)); >-} >- > String PlatformMediaSession::sourceApplicationIdentifier() const > { > return m_client.sourceApplicationIdentifier(); > } > >-bool PlatformMediaSession::isHidden() const >-{ >- return m_client.elementIsHidden(); >-} >- > bool PlatformMediaSession::isSuspended() const > { > return m_client.isSuspended(); >diff --git a/Source/WebCore/platform/audio/PlatformMediaSession.h b/Source/WebCore/platform/audio/PlatformMediaSession.h >index ec58ab60b40afcba26ba9a5b6c787031491e2ad7..5634aa4b5ad39e305a60e24d4ff734a8eb301085 100644 >--- a/Source/WebCore/platform/audio/PlatformMediaSession.h >+++ b/Source/WebCore/platform/audio/PlatformMediaSession.h >@@ -101,15 +101,13 @@ public: > void beginInterruption(InterruptionType); > void endInterruption(EndInterruptionFlags); > >- void clientWillBeginAutoplaying(); >- bool clientWillBeginPlayback(); >- bool clientWillPausePlayback(); >+ virtual void clientWillBeginAutoplaying(); >+ virtual bool clientWillBeginPlayback(); >+ virtual bool clientWillPausePlayback(); > > void pauseSession(); > void stopSession(); > >- void visibilityChanged(); >- > #if ENABLE(VIDEO) > String title() const; > double duration() const; >@@ -167,7 +165,6 @@ public: > bool canProduceAudio() const; > void canProduceAudioChanged(); > >- void scheduleClientDataBufferingCheck(); > virtual void resetPlaybackSessionState() { } > String sourceApplicationIdentifier() const; > >@@ -177,11 +174,7 @@ protected: > PlatformMediaSessionClient& client() const { return m_client; } > > private: >- void clientDataBufferingTimerFired(); >- void updateClientDataBuffering(); >- > PlatformMediaSessionClient& m_client; >- Timer m_clientDataBufferingTimer; > State m_state; > State m_stateToRestore; > InterruptionType m_interruptionType { NoInterruption }; >@@ -216,8 +209,6 @@ public: > virtual void didReceiveRemoteControlCommand(PlatformMediaSession::RemoteControlCommandType, const PlatformMediaSession::RemoteCommandArgument*) = 0; > virtual bool supportsSeeking() const = 0; > >- virtual void setShouldBufferData(bool) { } >- virtual bool elementIsHidden() const { return false; } > virtual bool canProduceAudio() const { return false; } > virtual bool isSuspended() const { return false; }; > >diff --git a/Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp b/Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp >index 806a3a5a63a141a2af841aa6dff510e49bfd4e95..3277b1a088377ea193459a86403946bcc98cefcd 100644 >--- a/Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp >+++ b/Source/WebCore/platform/audio/PlatformMediaSessionManager.cpp >@@ -287,13 +287,6 @@ Vector<PlatformMediaSession*> PlatformMediaSessionManager::currentSessionsMatchi > return matchingSessions; > } > >-bool PlatformMediaSessionManager::sessionCanLoadMedia(const PlatformMediaSession& session) const >-{ >- if (session.isSuspended()) >- return false; >- return session.state() == PlatformMediaSession::Playing || !session.isHidden() || session.shouldOverrideBackgroundLoadingRestriction(); >-} >- > void PlatformMediaSessionManager::applicationWillBecomeInactive() const > { > LOG(Media, "PlatformMediaSessionManager::applicationWillBecomeInactive"); >diff --git a/Source/WebCore/platform/audio/PlatformMediaSessionManager.h b/Source/WebCore/platform/audio/PlatformMediaSessionManager.h >index 8a434d630ff964b1de06adaa37406594ccab2e37..9897e6a5ffadb8d16173d861e6eb36af040614f3 100644 >--- a/Source/WebCore/platform/audio/PlatformMediaSessionManager.h >+++ b/Source/WebCore/platform/audio/PlatformMediaSessionManager.h >@@ -94,7 +94,6 @@ public: > > virtual bool sessionWillBeginPlayback(PlatformMediaSession&); > virtual void sessionWillEndPlayback(PlatformMediaSession&); >- virtual bool sessionCanLoadMedia(const PlatformMediaSession&) const; > virtual void sessionDidEndRemoteScrubbing(const PlatformMediaSession&) { }; > virtual void clientCharacteristicsChanged(PlatformMediaSession&) { } > >diff --git a/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.h b/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.h >index eb70dc2584bcad89c963da82632beaf101de42ff..ee193f4f5275065418a9844aa6dcb2510186a45d 100644 >--- a/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.h >+++ b/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.h >@@ -65,8 +65,6 @@ private: > > void configureWireLessTargetMonitoring() override; > >- bool sessionCanLoadMedia(const PlatformMediaSession&) const override; >- > bool hasActiveNowPlayingSession() const final { return m_nowPlayingActive; } > String lastUpdatedNowPlayingTitle() const final { return m_reportedTitle; } > double lastUpdatedNowPlayingDuration() const final { return m_reportedDuration; } >diff --git a/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm b/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm >index c8f435f49a2ce22f7b7c6d4052576e104a5b48da..8b0bb34eb62bdf95e8af648b1d2a75ff1dcbc7ca 100644 >--- a/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm >+++ b/Source/WebCore/platform/audio/ios/MediaSessionManagerIOS.mm >@@ -301,14 +301,6 @@ void MediaSessionManageriOS::updateNowPlayingInfo() > #endif // HAVE(MEDIA_PLAYER) > } > >-bool MediaSessionManageriOS::sessionCanLoadMedia(const PlatformMediaSession& session) const >-{ >- if (session.displayType() == PlatformMediaSession::Optimized) >- return true; >- >- return PlatformMediaSessionManager::sessionCanLoadMedia(session); >-} >- > void MediaSessionManageriOS::externalOutputDeviceAvailableDidChange() > { > BEGIN_BLOCK_OBJC_EXCEPTIONS >diff --git a/Source/WebCore/rendering/RenderVideo.cpp b/Source/WebCore/rendering/RenderVideo.cpp >index 0289205b5eee11059d6cb7fe7628275daa1fd71b..681b4cb851be0394b8224c33813c0a7bcbd114ca 100644 >--- a/Source/WebCore/rendering/RenderVideo.cpp >+++ b/Source/WebCore/rendering/RenderVideo.cpp >@@ -64,6 +64,7 @@ RenderVideo::~RenderVideo() > > void RenderVideo::willBeDestroyed() > { >+ visibleInViewportStateChanged(); > if (auto player = videoElement().player()) > player->setVisible(false); > >diff --git a/Source/WebCore/testing/Internals.cpp b/Source/WebCore/testing/Internals.cpp >index 81a4009533f9cdf19b263f862513ba82b9335b40..0fd7d4e7bc8d00a83aa291f3f817bf1adb9fb4f2 100644 >--- a/Source/WebCore/testing/Internals.cpp >+++ b/Source/WebCore/testing/Internals.cpp >@@ -3223,6 +3223,11 @@ void Internals::endSimulatedHDCPError(HTMLMediaElement& element) > player->endSimulatedHDCPError(); > } > >+bool Internals::elementShouldBufferData(HTMLMediaElement& element) >+{ >+ return element.shouldBufferData(); >+} >+ > #endif > > bool Internals::isSelectPopupVisible(HTMLSelectElement& element) >diff --git a/Source/WebCore/testing/Internals.h b/Source/WebCore/testing/Internals.h >index 1b83bcb18de773c5f34a5060572d4985ab9df2c1..6036ee9fe29d487bd1f91782f9586736436a3ed1 100644 >--- a/Source/WebCore/testing/Internals.h >+++ b/Source/WebCore/testing/Internals.h >@@ -470,6 +470,8 @@ public: > ExceptionOr<bool> mediaElementHasCharacteristic(HTMLMediaElement&, const String&); > void beginSimulatedHDCPError(HTMLMediaElement&); > void endSimulatedHDCPError(HTMLMediaElement&); >+ >+ bool elementShouldBufferData(HTMLMediaElement&); > #endif > > bool isSelectPopupVisible(HTMLSelectElement&); >diff --git a/Source/WebCore/testing/Internals.idl b/Source/WebCore/testing/Internals.idl >index 8d9c267cdde0d465dbff7734e92b660c478fc388..25c0d1cc47757a104ab748a4bb949a524fa8bc38 100644 >--- a/Source/WebCore/testing/Internals.idl >+++ b/Source/WebCore/testing/Internals.idl >@@ -426,6 +426,8 @@ enum EventThrottlingBehavior { > [Conditional=VIDEO] void beginSimulatedHDCPError(HTMLMediaElement media); > [Conditional=VIDEO] void endSimulatedHDCPError(HTMLMediaElement media); > >+ [Conditional=VIDEO] boolean elementShouldBufferData(HTMLMediaElement media); >+ > [Conditional=LEGACY_ENCRYPTED_MEDIA] void initializeMockCDM(); > [Conditional=ENCRYPTED_MEDIA] MockCDMFactory registerMockCDM(); > >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index 7bd211652c0f5566b1edb767ad991ffa6cc5c68f..0ec96282de7c5780b4eb05f9f854a6c42c085c4b 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,18 @@ >+2018-05-09 Jer Noble <jer.noble@apple.com> >+ >+ Media continues loading after rendered invisible (removed from DOM; scrolled off screen) >+ https://bugs.webkit.org/show_bug.cgi?id=185487 >+ >+ Reviewed by Eric Carlson. >+ >+ * media/video-buffering-allowed-expected.txt: Added. >+ * media/video-buffering-allowed.html: Added. >+ * media/video-test.js: >+ (compare): >+ (testExpected): >+ (sleepFor): >+ (testArraysEqual): Deleted. >+ > 2018-05-08 Eric Carlson <eric.carlson@apple.com> > > Consecutive messages logged as JSON are coalesced >diff --git a/LayoutTests/media/media-source/only-bcp47-language-tags-accepted-as-valid-expected.txt b/LayoutTests/media/media-source/only-bcp47-language-tags-accepted-as-valid-expected.txt >index a11aa4a4178bc0583b301a26c943d80428b0e45b..54a6e483b89457ab2e2e3ce76a5003a821078181 100644 >--- a/LayoutTests/media/media-source/only-bcp47-language-tags-accepted-as-valid-expected.txt >+++ b/LayoutTests/media/media-source/only-bcp47-language-tags-accepted-as-valid-expected.txt >@@ -1,48 +1,48 @@ >-CONSOLE MESSAGE: line 176: The language 'a' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language 'a' is not a valid BCP 47 language tag. > CONSOLE MESSAGE: line 106: The language 'a' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language 'a' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language '1' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language 'a' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language '1' is not a valid BCP 47 language tag. > CONSOLE MESSAGE: line 106: The language '1' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language '1' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language 'ab-abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language '1' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language 'ab-abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij' is not a valid BCP 47 language tag. > CONSOLE MESSAGE: line 106: The language 'ab-abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language 'ab-abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language '1a' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language 'ab-abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language '1a' is not a valid BCP 47 language tag. > CONSOLE MESSAGE: line 106: The language '1a' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language '1a' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language '-a' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language '1a' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language '-a' is not a valid BCP 47 language tag. > CONSOLE MESSAGE: line 106: The language '-a' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language '-a' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language 'a-' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language '-a' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language 'a-' is not a valid BCP 47 language tag. > CONSOLE MESSAGE: line 106: The language 'a-' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language 'a-' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language 'a1' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language 'a-' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language 'a1' is not a valid BCP 47 language tag. > CONSOLE MESSAGE: line 106: The language 'a1' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language 'a1' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language 'aa1' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language 'a1' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language 'aa1' is not a valid BCP 47 language tag. > CONSOLE MESSAGE: line 106: The language 'aa1' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language 'aa1' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language 'aaaa' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language 'aa1' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language 'aaaa' is not a valid BCP 47 language tag. > CONSOLE MESSAGE: line 106: The language 'aaaa' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language 'aaaa' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language 'aaa1' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language 'aaaa' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language 'aaa1' is not a valid BCP 47 language tag. > CONSOLE MESSAGE: line 106: The language 'aaa1' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language 'aaa1' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language 'inv-alid-char space' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language 'aaa1' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language 'inv-alid-char space' is not a valid BCP 47 language tag. > CONSOLE MESSAGE: line 106: The language 'inv-alid-char space' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language 'inv-alid-char space' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language 'inv-alid-charââ¬âlongDash' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language 'inv-alid-char space' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language 'inv-alid-charââ¬âlongDash' is not a valid BCP 47 language tag. > CONSOLE MESSAGE: line 106: The language 'inv-alid-charââ¬âlongDash' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language 'inv-alid-charââ¬âlongDash' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language 'inv-alid-char-PÃÂ¥lska' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language 'inv-alid-charââ¬âlongDash' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language 'inv-alid-char-PÃÂ¥lska' is not a valid BCP 47 language tag. > CONSOLE MESSAGE: line 106: The language 'inv-alid-char-PÃÂ¥lska' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language 'inv-alid-char-PÃÂ¥lska' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language 'inv-alid-char-*' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language 'inv-alid-char-PÃÂ¥lska' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language 'inv-alid-char-*' is not a valid BCP 47 language tag. > CONSOLE MESSAGE: line 106: The language 'inv-alid-char-*' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language 'inv-alid-char-*' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language 'inv-alid-char-' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language 'inv-alid-char-*' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language 'inv-alid-char-' is not a valid BCP 47 language tag. > CONSOLE MESSAGE: line 106: The language 'inv-alid-char-' is not a valid BCP 47 language tag. >-CONSOLE MESSAGE: line 176: The language 'inv-alid-char-' is not a valid BCP 47 language tag. >+CONSOLE MESSAGE: line 221: The language 'inv-alid-char-' is not a valid BCP 47 language tag. > Test that only BCP47 language tags are accepted as valid but still reflected. > > >diff --git a/LayoutTests/media/video-buffering-allowed-expected.txt b/LayoutTests/media/video-buffering-allowed-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..1da49de6842019d181314144d24044b86f767f8d >--- /dev/null >+++ b/LayoutTests/media/video-buffering-allowed-expected.txt >@@ -0,0 +1,32 @@ >+ >+RUN(video.src = findMediaFile("video", "content/test")) >+EVENT(canplaythrough) >+EXPECTED (internals.elementShouldBufferData(video) == 'true') OK >+* Remove the video element from the document. >+RUN(video.parentNode.removeChild(video)) >+EXPECTED (internals.elementShouldBufferData(video) == 'false') OK >+* Play the video. >+RUN(video.play()) >+EVENT(playing) >+EXPECTED (internals.elementShouldBufferData(video) == 'true') OK >+* Pause the video. >+RUN(video.pause()) >+EVENT(pause) >+EXPECTED (internals.elementShouldBufferData(video) == 'true') OK >+* Re-insert the video element into the document. >+RUN(document.body.insertBefore(video, document.body.firstChild)) >+EXPECTED (internals.elementShouldBufferData(video) == 'true') OK >+* display:none the video element. >+RUN(video.style.display = "none") >+EXPECTED (internals.elementShouldBufferData(video) == 'true') OK >+* Simulate the view becoming invisible. >+RUN(internals.setPageVisibility(false)) >+EXPECTED (internals.elementShouldBufferData(video) == 'false') OK >+* Simulate the view becoming visible. >+RUN(internals.setPageVisibility(true)) >+EXPECTED (internals.elementShouldBufferData(video) == 'false') OK >+* Remove display:none from the video element. >+RUN(video.style.removeProperty("display")) >+EXPECTED (internals.elementShouldBufferData(video) == 'true') OK >+END OF TEST >+ >diff --git a/LayoutTests/media/video-buffering-allowed.html b/LayoutTests/media/video-buffering-allowed.html >new file mode 100644 >index 0000000000000000000000000000000000000000..6fbbe15bc71188236746855b050e2d7f759c3a58 >--- /dev/null >+++ b/LayoutTests/media/video-buffering-allowed.html >@@ -0,0 +1,58 @@ >+<!DOCTYPE html> >+<html> >+<head> >+ <title>video-buffering-allowed</title> >+ <script src=media-file.js></script> >+ <script src=video-test.js></script> >+ <script> >+ async function runTest() { >+ findMediaElement(); >+ failTestIn(1000); >+ >+ run('video.src = findMediaFile("video", "content/test")'); >+ await waitFor(video, 'canplaythrough'); >+ testExpected('internals.elementShouldBufferData(video)', true); >+ >+ consoleWrite('* Remove the video element from the document.'); >+ run('video.parentNode.removeChild(video)'); >+ await testExpectedEventually('internals.elementShouldBufferData(video)', false); >+ >+ consoleWrite('* Play the video.'); >+ run ('video.play()'); >+ await waitFor(video, 'playing'); >+ testExpected('internals.elementShouldBufferData(video)', true); >+ >+ consoleWrite('* Pause the video.'); >+ run('video.pause()'); >+ await waitFor(video, 'pause'); >+ testExpected('internals.elementShouldBufferData(video)', true); >+ >+ consoleWrite('* Re-insert the video element into the document.'); >+ run('document.body.insertBefore(video, document.body.firstChild)'); >+ await testExpectedEventually('internals.elementShouldBufferData(video)', true); >+ >+ consoleWrite('* display:none the video element.'); >+ run('video.style.display = "none"'); >+ await testExpectedEventually('internals.elementShouldBufferData(video)', true); >+ >+ consoleWrite('* Simulate the view becoming invisible.'); >+ run('internals.setPageVisibility(false)'); >+ await testExpectedEventually('internals.elementShouldBufferData(video)', false); >+ >+ consoleWrite('* Simulate the view becoming visible.'); >+ run('internals.setPageVisibility(true)'); >+ await testExpectedEventually('internals.elementShouldBufferData(video)', false); >+ >+ consoleWrite('* Remove display:none from the video element.'); >+ run('video.style.removeProperty("display")'); >+ await testExpectedEventually('internals.elementShouldBufferData(video)', true); >+ >+ endTest(); >+ } >+ window.addEventListener('load', runTest); >+ </script> >+</head> >+<body> >+ <video controls></video> >+</body> >+</html> >diff --git a/LayoutTests/media/video-test.js b/LayoutTests/media/video-test.js >index d4b463c6e8987c23e2f0046e5106ea639660ee83..6eb110f8fe16f1cfc5b2eb63f348f64aa6271c9a 100644 >--- a/LayoutTests/media/video-test.js >+++ b/LayoutTests/media/video-test.js >@@ -62,17 +62,9 @@ function test(testFuncString, endit) > endTest(); > } > >-function testExpected(testFuncString, expected, comparison) >+function compare(testFuncString, expected, comparison) > { >- try { >- var observed = eval(testFuncString); >- } catch (ex) { >- consoleWrite(ex); >- return; >- } >- >- if (comparison === undefined) >- comparison = '=='; >+ var observed = eval(testFuncString); > > var success = false; > switch (comparison) >@@ -87,7 +79,51 @@ function testExpected(testFuncString, expected, comparison) > case 'instanceof': success = observed instanceof expected; break; > } > >- reportExpected(success, testFuncString, comparison, expected, observed) >+ return {success:success, observed:observed}; >+} >+ >+function testExpected(testFuncString, expected, comparison) >+{ >+ if (comparison === undefined) >+ comparison = '=='; >+ >+ try { >+ let {success, observed} = compare(testFuncString, expected, comparison); >+ reportExpected(success, testFuncString, comparison, expected, observed) >+ } catch (ex) { >+ consoleWrite(ex); >+ } >+} >+ >+function sleepFor(duration) { >+ return new Promise(resolve => { >+ setTimeout(resolve, duration); >+ }); >+} >+ >+function testExpectedEventually(testFuncString, expected, comparison) >+{ >+ return new Promise(async resolve => { >+ var success; >+ var observed; >+ if (comparison === undefined) >+ comparison = '=='; >+ while (true) { >+ try { >+ let {success, observed} = compare(testFuncString, expected, comparison); >+ if (success) { >+ reportExpected(success, testFuncString, comparison, expected, observed); >+ resolve(); >+ return; >+ } >+ await sleepFor(1); >+ } catch (ex) { >+ consoleWrite(ex); >+ resolve(); >+ return; >+ } >+ } >+ }); > } > > function testArraysEqual(testFuncString, expected) >@@ -150,6 +186,15 @@ function run(testFuncString) > } > } > >+function waitFor(element, event) { >+ return new Promise(resolve => { >+ element.addEventListener(event, event => { >+ consoleWrite(`EVENT(${event.type})`); >+ resolve(event); >+ }, { once: true }); >+ }); >+} >+ > function waitForEventOnce(eventName, func, endit) > { > waitForEvent(eventName, func, endit, true)
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 185487
:
340016
|
340027
|
340036
|
340045
|
340326
|
340332
|
340347
|
340376