Changeset 249147 in webkit
- Timestamp:
- Aug 27, 2019 9:48:21 AM (5 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r249141 r249147 1 2019-08-26 Jer Noble <jer.noble@apple.com> 2 3 Removing fullscreen element in rAF() callback after requestFullscreen() can leave fullscreen in inconsistent state. 4 https://bugs.webkit.org/show_bug.cgi?id=201101 5 <rdar://problem/54164587> 6 7 Reviewed by Eric Carlson. 8 9 * fullscreen/full-screen-request-removed-with-raf-expected.txt: Added. 10 * fullscreen/full-screen-request-removed-with-raf.html: Added. 11 1 12 2019-08-27 Peng Liu <peng.liu6@apple.com> 2 13 -
trunk/Source/WebCore/ChangeLog
r249141 r249147 1 2019-08-26 Jer Noble <jer.noble@apple.com> 2 3 Removing fullscreen element in rAF() callback after requestFullscreen() can leave fullscreen in inconsistent state. 4 https://bugs.webkit.org/show_bug.cgi?id=201101 5 <rdar://problem/54164587> 6 7 Reviewed by Eric Carlson. 8 9 Test: fullscreen/full-screen-request-removed-with-raf.html 10 11 Add a new state variable, m_pendingFullscreenElement, to track which element is about to 12 become the fullscreen element, so that when elements are removed or cancelFullscreen() is 13 called, the state machine inside the fullscreen algorithm can cancel effectively. 14 15 * dom/FullscreenManager.cpp: 16 (WebCore::FullscreenManager::requestFullscreenForElement): 17 (WebCore::FullscreenManager::cancelFullscreen): 18 (WebCore::FullscreenManager::exitFullscreen): 19 (WebCore::FullscreenManager::willEnterFullscreen): 20 (WebCore::FullscreenManager::willExitFullscreen): 21 (WebCore::FullscreenManager::didExitFullscreen): 22 (WebCore::FullscreenManager::adjustFullscreenElementOnNodeRemoval): 23 (WebCore::FullscreenManager::clear): 24 (WebCore::FullscreenManager::fullscreenElementRemoved): Deleted. 25 * dom/FullscreenManager.h: 26 1 27 2019-08-27 Peng Liu <peng.liu6@apple.com> 2 28 -
trunk/Source/WebCore/dom/FullscreenManager.cpp
r246490 r249147 121 121 } 122 122 123 m_pendingFullscreenElement = element; 124 123 125 m_fullscreenTaskQueue.enqueueTask([this, element = makeRefPtr(element), checkType, hasKeyboardAccess, failedPreflights] () mutable { 126 // Don't allow fullscreen if it has been cancelled or a different fullscreen element 127 // has requested fullscreen. 128 if (m_pendingFullscreenElement != element) { 129 failedPreflights(WTFMove(element)); 130 return; 131 } 132 124 133 // Don't allow fullscreen if document is hidden. 125 134 if (document().hidden()) { … … 210 219 // 6. Optionally, perform some animation. 211 220 m_areKeysEnabledInFullscreen = hasKeyboardAccess; 212 m_fullscreenTaskQueue.enqueueTask([this, element = WTFMove(element)] { 213 if (auto page = this->page()) 214 page->chrome().client().enterFullScreenForElement(*element.get()); 221 m_fullscreenTaskQueue.enqueueTask([this, element = WTFMove(element), failedPreflights = WTFMove(failedPreflights)] () mutable { 222 auto page = this->page(); 223 if (!page || document().hidden() || m_pendingFullscreenElement != element || !element->isConnected()) { 224 failedPreflights(element); 225 return; 226 } 227 page->chrome().client().enterFullScreenForElement(*element.get()); 215 228 }); 216 229 … … 226 239 // context's document and subsequently empty that document's fullscreen element stack." 227 240 Document& topDocument = document().topDocument(); 228 if (!topDocument.fullscreenManager().fullscreenElement()) 229 return; 241 if (!topDocument.fullscreenManager().fullscreenElement()) { 242 // If there is a pending fullscreen element but no top document fullscreen element, 243 // there is a pending task in enterFullscreen(). Cause it to cancel and fire an error 244 // by clearing the pending fullscreen element. 245 m_pendingFullscreenElement = nullptr; 246 return; 247 } 230 248 231 249 // To achieve that aim, remove all the elements from the top document's stack except for the first before … … 246 264 247 265 // 2. If doc's fullscreen element stack is empty, terminate these steps. 248 if (m_fullscreenElementStack.isEmpty()) 249 return; 266 if (m_fullscreenElementStack.isEmpty()) { 267 // If there is a pending fullscreen element but an empty fullscreen element stack, 268 // there is a pending task in requestFullscreenForElement(). Cause it to cancel and fire an error 269 // by clearing the pending fullscreen element. 270 m_pendingFullscreenElement = nullptr; 271 return; 272 } 250 273 251 274 // 3. Let descendants be all the doc's descendant browsing context's documents with a non-empty fullscreen … … 299 322 return; 300 323 324 // If there is a pending fullscreen element but no fullscreen element 325 // there is a pending task in requestFullscreenForElement(). Cause it to cancel and fire an error 326 // by clearing the pending fullscreen element. 327 if (!fullscreenElement && m_pendingFullscreenElement) { 328 m_pendingFullscreenElement = nullptr; 329 return; 330 } 331 301 332 // Only exit out of full screen window mode if there are no remaining elements in the 302 333 // full screen stack. … … 340 371 return; 341 372 373 // If pending fullscreen element is unset or another element's was requested, 374 // issue a cancel fullscreen request to the client 375 if (m_pendingFullscreenElement != &element) { 376 page()->chrome().client().exitFullScreenForElement(&element); 377 return; 378 } 379 342 380 ASSERT(page()->settings().fullScreenEnabled()); 343 381 … … 346 384 element.willBecomeFullscreenElement(); 347 385 386 ASSERT(&element == m_pendingFullscreenElement); 387 m_pendingFullscreenElement = nullptr; 348 388 m_fullscreenElement = &element; 349 389 … … 386 426 void FullscreenManager::willExitFullscreen() 387 427 { 388 if (!m_fullscreenElement) 428 auto fullscreenElement = fullscreenOrPendingElement(); 429 if (!fullscreenElement) 389 430 return; 390 431 … … 392 433 return; 393 434 394 m_fullscreenElement->willStopBeingFullscreenElement();435 fullscreenElement->willStopBeingFullscreenElement(); 395 436 } 396 437 397 438 void FullscreenManager::didExitFullscreen() 398 439 { 399 if (!m_fullscreenElement) 440 auto fullscreenElement = fullscreenOrPendingElement(); 441 if (!fullscreenElement) 400 442 return; 401 443 402 444 if (!hasLivingRenderTree() || pageCacheState() != Document::NotInPageCache) 403 445 return; 404 405 m_fullscreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false); 446 fullscreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false); 406 447 407 448 m_areKeysEnabledInFullscreen = false; … … 410 451 411 452 m_fullscreenElement = nullptr; 453 m_pendingFullscreenElement = nullptr; 412 454 scheduleFullStyleRebuild(); 413 455 … … 484 526 } 485 527 486 void FullscreenManager::fullscreenElementRemoved()487 {488 m_fullscreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false);489 cancelFullscreen();490 }491 492 528 void FullscreenManager::adjustFullscreenElementOnNodeRemoval(Node& node, Document::NodeRemoval nodeRemoval) 493 529 { 494 if (!m_fullscreenElement) 530 auto fullscreenElement = fullscreenOrPendingElement(); 531 if (!fullscreenElement) 495 532 return; 496 533 497 534 bool elementInSubtree = false; 498 535 if (nodeRemoval == Document::NodeRemoval::ChildrenOfNode) 499 elementInSubtree = m_fullscreenElement->isDescendantOf(node);536 elementInSubtree = fullscreenElement->isDescendantOf(node); 500 537 else 501 elementInSubtree = (m_fullscreenElement == &node) || m_fullscreenElement->isDescendantOf(node); 502 503 if (elementInSubtree) 504 fullscreenElementRemoved(); 538 elementInSubtree = (fullscreenElement == &node) || fullscreenElement->isDescendantOf(node); 539 540 if (elementInSubtree) { 541 fullscreenElement->setContainsFullScreenElementOnAncestorsCrossingFrameBoundaries(false); 542 cancelFullscreen(); 543 } 505 544 } 506 545 … … 542 581 { 543 582 m_fullscreenElement = nullptr; 583 m_pendingFullscreenElement = nullptr; 544 584 m_fullscreenElementStack.clear(); 545 585 } -
trunk/Source/WebCore/dom/FullscreenManager.h
r248762 r249147 110 110 Document& m_document; 111 111 112 RefPtr<Element> fullscreenOrPendingElement() const { return m_fullscreenElement ? m_fullscreenElement : m_pendingFullscreenElement; } 113 114 RefPtr<Element> m_pendingFullscreenElement; 112 115 RefPtr<Element> m_fullscreenElement; 113 116 Vector<RefPtr<Element>> m_fullscreenElementStack; -
trunk/Source/WebKit/ChangeLog
r249142 r249147 1 2019-08-26 Jer Noble <jer.noble@apple.com> 2 3 Removing fullscreen element in rAF() callback after requestFullscreen() can leave fullscreen in inconsistent state. 4 https://bugs.webkit.org/show_bug.cgi?id=201101 5 <rdar://problem/54164587> 6 7 Reviewed by Eric Carlson. 8 9 Add more state to track in which direction the animation is flowing to allow in-process 10 animations to be cancelled more gracefully. 11 12 * UIProcess/ios/fullscreen/WKFullScreenWindowControllerIOS.mm: 13 (-[WKFullScreenWindowController enterFullScreen]): 14 (-[WKFullScreenWindowController beganEnterFullScreenWithInitialFrame:finalFrame:]): 15 (-[WKFullScreenWindowController requestExitFullScreen]): 16 (-[WKFullScreenWindowController exitFullScreen]): 17 * WebProcess/cocoa/VideoFullscreenManager.h: 18 (WebKit::VideoFullscreenInterfaceContext::animationState const): 19 (WebKit::VideoFullscreenInterfaceContext::setAnimationState): 20 (WebKit::VideoFullscreenInterfaceContext::isAnimating const): Deleted. 21 (WebKit::VideoFullscreenInterfaceContext::setIsAnimating): Deleted. 22 * WebProcess/cocoa/VideoFullscreenManager.mm: 23 (WebKit::VideoFullscreenManager::enterVideoFullscreenForVideoElement): 24 (WebKit::VideoFullscreenManager::exitVideoFullscreenForVideoElement): 25 (WebKit::VideoFullscreenManager::didEnterFullscreen): 26 (WebKit::VideoFullscreenManager::didCleanupFullscreen): 27 1 28 2019-08-27 Carlos Garcia Campos <cgarcia@igalia.com> 2 29 -
trunk/Source/WebKit/UIProcess/ios/fullscreen/WKFullScreenWindowControllerIOS.mm
r247018 r249147 448 448 BOOL _EVOrganizationNameIsValid; 449 449 BOOL _inInteractiveDismiss; 450 BOOL _exitRequested; 450 451 451 452 RetainPtr<id> _notificationListener; … … 598 599 _repaintCallback = WebKit::VoidCallback::create([protectedSelf = retainPtr(self), self](WebKit::CallbackBase::Error) { 599 600 _repaintCallback = nullptr; 601 602 if (_exitRequested) { 603 _exitRequested = NO; 604 [self _exitFullscreenImmediately]; 605 return; 606 } 607 600 608 if (auto* manager = [protectedSelf _manager]) { 601 609 manager->willEnterFullScreen(); … … 640 648 [_rootViewController presentViewController:_fullscreenViewController.get() animated:YES completion:^{ 641 649 _fullScreenState = WebKit::InFullScreen; 650 651 if (_exitRequested) { 652 _exitRequested = NO; 653 [self _exitFullscreenImmediately]; 654 return; 655 } 642 656 643 657 auto* page = [self._webView _page]; … … 658 672 - (void)requestExitFullScreen 659 673 { 674 if (_fullScreenState != WebKit::InFullScreen) { 675 _exitRequested = YES; 676 return; 677 } 678 660 679 if (auto* manager = self._manager) { 661 680 manager->requestExitFullScreen(); … … 669 688 - (void)exitFullScreen 670 689 { 671 if (!self.isFullScreen) 672 return; 690 if (_fullScreenState < WebKit::InFullScreen) { 691 _exitRequested = YES; 692 return; 693 } 673 694 _fullScreenState = WebKit::WaitingToExitFullScreen; 674 695 -
trunk/Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.h
r238528 r249147 74 74 void setLayerHostingContext(std::unique_ptr<LayerHostingContext>&&); 75 75 76 bool isAnimating() const { return m_isAnimating; } 77 void setIsAnimating(bool flag) { m_isAnimating = flag; } 76 enum class AnimationType { None, IntoFullscreen, FromFullscreen }; 77 AnimationType animationState() const { return m_animationType; } 78 void setAnimationState(AnimationType flag) { m_animationType = flag; } 78 79 79 80 bool targetIsFullscreen() const { return m_targetIsFullscreen; } … … 99 100 uint64_t m_contextId; 100 101 std::unique_ptr<LayerHostingContext> m_layerHostingContext; 101 bool m_isAnimating{ false };102 AnimationType m_animationType { false }; 102 103 bool m_targetIsFullscreen { false }; 103 104 WebCore::HTMLMediaElementEnums::VideoFullscreenMode m_fullscreenMode { WebCore::HTMLMediaElementEnums::VideoFullscreenModeNone }; -
trunk/Source/WebKit/WebProcess/cocoa/VideoFullscreenManager.mm
r247102 r249147 261 261 model->setVideoLayerFrame(videoLayerFrame); 262 262 263 if (interface-> isAnimating())264 return; 265 interface->set IsAnimating(true);263 if (interface->animationState() != VideoFullscreenInterfaceContext::AnimationType::None) 264 return; 265 interface->setAnimationState(VideoFullscreenInterfaceContext::AnimationType::IntoFullscreen); 266 266 267 267 bool allowsPictureInPicture = videoElement.webkitSupportsPresentationMode(HTMLVideoElement::VideoPresentationMode::PictureInPicture); … … 297 297 interface.setTargetIsFullscreen(false); 298 298 299 if (interface.isAnimating()) 300 return; 301 302 interface.setIsAnimating(true); 299 if (interface.animationState() == VideoFullscreenInterfaceContext::AnimationType::FromFullscreen) 300 return; 301 interface.setAnimationState(VideoFullscreenInterfaceContext::AnimationType::FromFullscreen); 303 302 m_page->send(Messages::VideoFullscreenManagerProxy::ExitFullscreen(contextId, inlineVideoFrame(videoElement))); 304 303 } … … 439 438 auto [model, interface] = ensureModelAndInterface(contextId); 440 439 441 interface->set IsAnimating(false);440 interface->setAnimationState(VideoFullscreenInterfaceContext::AnimationType::None); 442 441 interface->setIsFullscreen(false); 443 442 … … 502 501 } 503 502 504 interface->set IsAnimating(false);503 interface->setAnimationState(VideoFullscreenInterfaceContext::AnimationType::None); 505 504 interface->setIsFullscreen(false); 506 505 HTMLMediaElementEnums::VideoFullscreenMode mode = interface->fullscreenMode();
Note: See TracChangeset
for help on using the changeset viewer.