Changeset 233560 in webkit
- Timestamp:
- Jul 5, 2018, 8:20:20 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 8 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/media/remove-video-best-media-element-in-main-frame-crash-expected.txt (added)
-
LayoutTests/media/remove-video-best-media-element-in-main-frame-crash.html (added)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/html/HTMLMediaElement.cpp (modified) (18 diffs)
-
Source/WebCore/html/HTMLMediaElement.h (modified) (3 diffs)
-
Source/WebCore/page/Page.cpp (modified) (2 diffs)
-
Source/WebCore/page/Page.h (modified) (3 diffs)
-
Source/WebCore/testing/Internals.cpp (modified) (1 diff)
-
Source/WebCore/testing/Internals.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r233556 r233560 1 2018-07-05 Ryosuke Niwa <rniwa@webkit.org> 2 3 Youtube video pages crash after a couple of minutes 4 https://bugs.webkit.org/show_bug.cgi?id=187316 5 6 Reviewed by Antti Koivisto. 7 8 Added a regression test to remove an iframe with a video while there is a main content 9 which is eligible to be shown in the Touch Bar. 10 11 * media/remove-video-best-media-element-in-main-frame-crash-expected.txt: Added. 12 * media/remove-video-best-media-element-in-main-frame-crash.html: Added. 13 1 14 2018-07-05 Fujii Hironori <Hironori.Fujii@sony.com> 2 15 -
trunk/Source/WebCore/ChangeLog
r233557 r233560 1 2018-07-05 Ryosuke Niwa <rniwa@webkit.org> 2 3 Youtube video pages crash after a couple of minutes 4 https://bugs.webkit.org/show_bug.cgi?id=187316 5 6 Reviewed by Antti Koivisto. 7 8 The crash was caused by HTMLMediaElement::stopWithoutDestroyingMediaPlayer invoking updatePlaybackControlsManager, 9 which traverses all media players across different documents including the one in the main frame while its iframe 10 is getting removed (to update the Touch Bar's media control). 11 12 Fixed the bug by making this code async in both stopWithoutDestroyingMediaPlayer and ~HTMLMediaElement. To do this, 13 this patch moves the timer to update the playback controls manager from HTMLMediaElement to Page since scheduling 14 a timer owned by HTMLMediaElement in its destructor wouldn't work as the timer would get destructed immediately. 15 16 Also replaced the call to clientWillPausePlayback by a call to stopSession in stopWithoutDestroyingMediaPlayer 17 since the former also updates the layout synchronously via updateNowPlayingInfo; the latter function schedules 18 a timer via scheduleUpdateNowPlayingInfo instead. 19 20 Test: media/remove-video-best-media-element-in-main-frame-crash.html 21 22 * html/HTMLMediaElement.cpp: 23 (WebCore::HTMLMediaElement::~HTMLMediaElement): Call scheduleUpdatePlaybackControlsManager now that timer has been 24 moved to Page. 25 (WebCore::HTMLMediaElement::bestMediaElementForShowingPlaybackControlsManager): Made this return a RefPtr instead of 26 a raw pointer while we're at it. 27 (WebCore::HTMLMediaElement::clearMediaPlayer): Call scheduleUpdatePlaybackControlsManager. 28 (WebCore::HTMLMediaElement::stopWithoutDestroyingMediaPlayer): Ditto. Also invoke stopSession instead of 29 clientWillPausePlayback on MediaSession since clientWillPausePlayback will synchronously try to update the layout. 30 (WebCore::HTMLMediaElement::contextDestroyed): 31 (WebCore::HTMLMediaElement::stop): 32 (WebCore::HTMLMediaElement::schedulePlaybackControlsManagerUpdate): Renamed from scheduleUpdatePlaybackControlsManager. 33 (WebCore::HTMLMediaElement::updatePlaybackControlsManager): Moved to Page::playbackControlsManagerUpdateTimerFired. 34 * html/HTMLMediaElement.h: 35 * page/Page.cpp: 36 (WebCore::Page::Page): 37 (WebCore::Page::schedulePlaybackControlsManagerUpdate): Added. 38 (WebCore::Page::playbackControlsManagerUpdateTimerFired): Moved from HTMLMediaElement::updatePlaybackControlsManager. 39 * page/Page.h: 40 * testing/Internals.cpp: 41 (WebCore::Internals::bestMediaElementForShowingPlaybackControlsManager): 42 * testing/Internals.h: 43 1 44 2018-07-05 Ryosuke Niwa <rniwa@webkit.org> 2 45 -
trunk/Source/WebCore/html/HTMLMediaElement.cpp
r233557 r233560 681 681 m_promiseTaskQueue.close(); 682 682 m_pauseAfterDetachedTaskQueue.close(); 683 m_updatePlaybackControlsManagerQueue.close();684 683 m_playbackControlsManagerBehaviorRestrictionsQueue.close(); 685 684 m_resourceSelectionTaskQueue.close(); … … 697 696 698 697 m_mediaSession = nullptr; 699 updatePlaybackControlsManager();698 schedulePlaybackControlsManagerUpdate(); 700 699 } 701 700 … … 710 709 } 711 710 712 HTMLMediaElement*HTMLMediaElement::bestMediaElementForShowingPlaybackControlsManager(MediaElementSession::PlaybackControlsPurpose purpose)711 RefPtr<HTMLMediaElement> HTMLMediaElement::bestMediaElementForShowingPlaybackControlsManager(MediaElementSession::PlaybackControlsPurpose purpose) 713 712 { 714 713 auto allSessions = PlatformMediaSessionManager::sharedManager().currentSessionsMatching([] (const PlatformMediaSession& session) { … … 1141 1140 resolvePendingPlayPromises(WTFMove(pendingPlayPromises)); 1142 1141 1143 schedule UpdatePlaybackControlsManager();1142 schedulePlaybackControlsManagerUpdate(); 1144 1143 } 1145 1144 … … 3745 3744 } 3746 3745 3747 schedule UpdatePlaybackControlsManager();3746 schedulePlaybackControlsManagerUpdate(); 3748 3747 } 3749 3748 … … 4404 4403 if (!m_receivedLayoutSizeChanged) { 4405 4404 m_receivedLayoutSizeChanged = true; 4406 schedule UpdatePlaybackControlsManager();4405 schedulePlaybackControlsManagerUpdate(); 4407 4406 } 4408 4407 … … 5330 5329 5331 5330 if (shouldBePlaying) { 5332 schedule UpdatePlaybackControlsManager();5331 schedulePlaybackControlsManagerUpdate(); 5333 5332 5334 5333 setDisplayMode(Video); … … 5359 5358 setPlaying(true); 5360 5359 } else { 5361 schedule UpdatePlaybackControlsManager();5360 schedulePlaybackControlsManagerUpdate(); 5362 5361 5363 5362 if (!playerPaused) … … 5523 5522 m_player = nullptr; 5524 5523 } 5525 updatePlaybackControlsManager();5524 schedulePlaybackControlsManagerUpdate(); 5526 5525 5527 5526 stopPeriodicTimers(); … … 5563 5562 setPreparedToReturnVideoLayerToInline(true); 5564 5563 5565 updatePlaybackControlsManager();5564 schedulePlaybackControlsManagerUpdate(); 5566 5565 setInActiveDocument(false); 5567 5566 … … 5569 5568 setPlaying(false); 5570 5569 setPausedInternal(true); 5571 m_mediaSession-> clientWillPausePlayback();5570 m_mediaSession->stopSession(); 5572 5571 5573 5572 setPlaybackWithoutUserGesture(PlaybackWithoutUserGesture::None); … … 5588 5587 m_promiseTaskQueue.close(); 5589 5588 m_pauseAfterDetachedTaskQueue.close(); 5590 m_updatePlaybackControlsManagerQueue.close();5591 5589 #if ENABLE(ENCRYPTED_MEDIA) 5592 5590 m_encryptedMediaQueue.close(); … … 5607 5605 m_asyncEventQueue.close(); 5608 5606 m_promiseTaskQueue.close(); 5609 m_updatePlaybackControlsManagerQueue.close();5610 5607 m_resourceSelectionTaskQueue.close(); 5611 5608 … … 6554 6551 m_player = MediaPlayer::create(*this); 6555 6552 m_player->setShouldBufferData(m_shouldBufferData); 6556 schedule UpdatePlaybackControlsManager();6553 schedulePlaybackControlsManagerUpdate(); 6557 6554 6558 6555 #if ENABLE(WEB_AUDIO) … … 7866 7863 m_mediaSession->isVisibleInViewportChanged(); 7867 7864 updateShouldAutoplay(); 7868 schedule UpdatePlaybackControlsManager();7865 schedulePlaybackControlsManagerUpdate(); 7869 7866 }); 7870 7867 } … … 7909 7906 } 7910 7907 7911 void HTMLMediaElement:: updatePlaybackControlsManager()7908 void HTMLMediaElement::schedulePlaybackControlsManagerUpdate() 7912 7909 { 7913 7910 Page* page = document().page(); 7914 7911 if (!page) 7915 7912 return; 7916 7917 // FIXME: Ensure that the renderer here should be up to date. 7918 if (auto bestMediaElement = bestMediaElementForShowingPlaybackControlsManager(MediaElementSession::PlaybackControlsPurpose::ControlsManager)) 7919 page->chrome().client().setUpPlaybackControlsManager(*bestMediaElement); 7920 else 7921 page->chrome().client().clearPlaybackControlsManager(); 7922 } 7923 7924 void HTMLMediaElement::scheduleUpdatePlaybackControlsManager() 7925 { 7926 if (!m_updatePlaybackControlsManagerQueue.hasPendingTasks()) 7927 m_updatePlaybackControlsManagerQueue.enqueueTask(std::bind(&HTMLMediaElement::updatePlaybackControlsManager, this)); 7913 page->schedulePlaybackControlsManagerUpdate(); 7928 7914 } 7929 7915 … … 7943 7929 7944 7930 mediaElementSession->addBehaviorRestriction(MediaElementSession::RequirePlaybackToControlControlsManager); 7945 protectedThis->schedule UpdatePlaybackControlsManager();7931 protectedThis->schedulePlaybackControlsManagerUpdate(); 7946 7932 }); 7947 7933 } … … 7964 7950 m_videoFullscreenMode = mode; 7965 7951 visibilityStateChanged(); 7966 schedule UpdatePlaybackControlsManager();7952 schedulePlaybackControlsManagerUpdate(); 7967 7953 } 7968 7954 -
trunk/Source/WebCore/html/HTMLMediaElement.h
r233549 r233560 156 156 static HashSet<HTMLMediaElement*>& allMediaElements(); 157 157 158 WEBCORE_EXPORT static HTMLMediaElement*bestMediaElementForShowingPlaybackControlsManager(MediaElementSession::PlaybackControlsPurpose);158 WEBCORE_EXPORT static RefPtr<HTMLMediaElement> bestMediaElementForShowingPlaybackControlsManager(MediaElementSession::PlaybackControlsPurpose); 159 159 160 160 static bool isRunningDestructor(); … … 899 899 void pauseAfterDetachedTask(); 900 900 void updatePlaybackControlsManager(); 901 void schedule UpdatePlaybackControlsManager();901 void schedulePlaybackControlsManagerUpdate(); 902 902 void playbackControlsManagerBehaviorRestrictionsTimerFired(); 903 903 … … 934 934 GenericTaskQueue<Timer> m_promiseTaskQueue; 935 935 GenericTaskQueue<Timer> m_pauseAfterDetachedTaskQueue; 936 GenericTaskQueue<Timer> m_updatePlaybackControlsManagerQueue;937 936 GenericTaskQueue<Timer> m_playbackControlsManagerBehaviorRestrictionsQueue; 938 937 GenericTaskQueue<Timer> m_resourceSelectionTaskQueue; -
trunk/Source/WebCore/page/Page.cpp
r233552 r233560 240 240 , m_visitedLinkStore(*WTFMove(pageConfiguration.visitedLinkStore)) 241 241 , m_sessionID(PAL::SessionID::defaultSessionID()) 242 , m_playbackControlsManagerUpdateTimer(*this, &Page::playbackControlsManagerUpdateTimerFired) 242 243 , m_isUtilityPage(isUtilityPageChromeClient(chrome().client())) 243 244 , m_performanceMonitor(isUtilityPage() ? nullptr : std::make_unique<PerformanceMonitor>(*this)) … … 1486 1487 1487 1488 chrome().client().isPlayingMediaDidChange(state, sourceElementID); 1489 } 1490 1491 void Page::schedulePlaybackControlsManagerUpdate() 1492 { 1493 if (!m_playbackControlsManagerUpdateTimer.isActive()) 1494 m_playbackControlsManagerUpdateTimer.startOneShot(0_s); 1495 } 1496 1497 void Page::playbackControlsManagerUpdateTimerFired() 1498 { 1499 if (auto bestMediaElement = HTMLMediaElement::bestMediaElementForShowingPlaybackControlsManager(MediaElementSession::PlaybackControlsPurpose::ControlsManager)) 1500 chrome().client().setUpPlaybackControlsManager(*bestMediaElement); 1501 else 1502 chrome().client().clearPlaybackControlsManager(); 1488 1503 } 1489 1504 -
trunk/Source/WebCore/page/Page.h
r233552 r233560 570 570 bool isAudioMuted() const { return m_mutedState & MediaProducer::AudioIsMuted; } 571 571 bool isMediaCaptureMuted() const { return m_mutedState & MediaProducer::CaptureDevicesAreMuted; }; 572 void schedulePlaybackControlsManagerUpdate(); 572 573 WEBCORE_EXPORT void setMuted(MediaProducer::MutedStateFlags); 573 574 WEBCORE_EXPORT void stopMediaCapture(); … … 674 675 675 676 std::optional<std::pair<MediaCanStartListener&, Document&>> takeAnyMediaCanStartListener(); 677 678 void playbackControlsManagerUpdateTimerFired(); 676 679 677 680 Vector<Ref<PluginViewBase>> pluginViews(); … … 850 853 851 854 MediaProducer::MediaStateFlags m_mediaState { MediaProducer::IsNotPlaying }; 852 855 856 Timer m_playbackControlsManagerUpdateTimer; 857 853 858 bool m_allowsMediaDocumentInlinePlayback { false }; 854 859 bool m_allowsPlaybackControlsForAutoplayingAudio { false }; -
trunk/Source/WebCore/testing/Internals.cpp
r233549 r233560 3751 3751 3752 3752 #if ENABLE(VIDEO) 3753 HTMLMediaElement*Internals::bestMediaElementForShowingPlaybackControlsManager(Internals::PlaybackControlsPurpose purpose)3753 RefPtr<HTMLMediaElement> Internals::bestMediaElementForShowingPlaybackControlsManager(Internals::PlaybackControlsPurpose purpose) 3754 3754 { 3755 3755 return HTMLMediaElement::bestMediaElementForShowingPlaybackControlsManager(purpose); -
trunk/Source/WebCore/testing/Internals.h
r233549 r233560 705 705 #if ENABLE(VIDEO) 706 706 using PlaybackControlsPurpose = MediaElementSession::PlaybackControlsPurpose; 707 HTMLMediaElement*bestMediaElementForShowingPlaybackControlsManager(PlaybackControlsPurpose);707 RefPtr<HTMLMediaElement> bestMediaElementForShowingPlaybackControlsManager(PlaybackControlsPurpose); 708 708 709 709 using MediaSessionState = PlatformMediaSession::State;
Note:
See TracChangeset
for help on using the changeset viewer.