Changeset 287860 in webkit
- Timestamp:
- Jan 10, 2022, 2:58:49 PM (5 years ago)
- Location:
- trunk
- Files:
-
- 5 edited
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/page/ModalContainerObserver.cpp (modified) (4 diffs)
-
Tools/ChangeLog (modified) (1 diff)
-
Tools/TestWebKitAPI/Tests/WebKit/modal-container-custom.html (modified) (1 diff)
-
Tools/TestWebKitAPI/Tests/WebKitCocoa/ModalContainerObservation.mm (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r287855 r287860 1 2022-01-10 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 Modal container observer should classify elements that are styled like clickable controls 4 https://bugs.webkit.org/show_bug.cgi?id=235022 5 6 Reviewed by Tim Horton. 7 8 Broaden the criteria when considering whether or not an element inside of a detected modal container is a 9 "clickable control". In the case where there are event listeners on the modal container, an element inside of 10 the modal container that has `cursor: pointer;` may trigger an action on the modal container when clicked, even 11 if it does not have event listeners itself. Handle this scenario by considering the element to be a "clickable 12 control", and extract text from the element for the purposes of control classification. 13 14 Test: ModalContainerObservation.DetectControlsWithEventListenersOnModalContainer 15 16 * page/ModalContainerObserver.cpp: 17 (WebCore::listensToUserActivation): 18 19 Factor out this logic into a separate helper function. 20 21 (WebCore::isClickableControl): 22 (WebCore::ModalContainerObserver::collectClickableElements): 23 1 24 2022-01-10 Eric Carlson <eric.carlson@apple.com> 2 25 -
trunk/Source/WebCore/page/ModalContainerObserver.cpp
r287849 r287860 60 60 61 61 static constexpr size_t maxLengthForClickableElementText = 100; 62 static constexpr double maxWidthForElementsThatLookClickable = 200; 63 static constexpr double maxHeightForElementsThatLookClickable = 100; 62 64 63 65 bool ModalContainerObserver::isNeededFor(const Document& document) … … 296 298 } 297 299 298 static bool isClickableControl(const HTMLElement& element) 300 static bool listensForUserActivation(const Element& element) 301 { 302 return element.hasEventListeners(eventNames().clickEvent) || element.hasEventListeners(eventNames().mousedownEvent) || element.hasEventListeners(eventNames().mouseupEvent) 303 || element.hasEventListeners(eventNames().touchstartEvent) || element.hasEventListeners(eventNames().touchendEvent) 304 || element.hasEventListeners(eventNames().pointerdownEvent) || element.hasEventListeners(eventNames().pointerupEvent); 305 } 306 307 enum class ContainerListensForUserActivation : bool { No, Yes }; 308 static bool isClickableControl(const HTMLElement& element, ContainerListensForUserActivation containerListensForUserActivation) 299 309 { 300 310 if (element.isActuallyDisabled()) … … 327 337 } 328 338 329 return element.hasEventListeners(eventNames().clickEvent) || element.hasEventListeners(eventNames().mousedownEvent) || element.hasEventListeners(eventNames().mouseupEvent) 330 || element.hasEventListeners(eventNames().touchstartEvent) || element.hasEventListeners(eventNames().touchendEvent) 331 || element.hasEventListeners(eventNames().pointerdownEvent) || element.hasEventListeners(eventNames().pointerupEvent); 339 if (listensForUserActivation(element)) 340 return true; 341 342 if (containerListensForUserActivation == ContainerListensForUserActivation::No) 343 return false; 344 345 auto rendererAndRect = element.boundingAbsoluteRectWithoutLayout(); 346 if (!rendererAndRect) 347 return false; 348 349 auto [renderer, rect] = *rendererAndRect; 350 if (!renderer || rect.isEmpty()) 351 return false; 352 353 // If the modal container itself has event listeners for user activation, continue looking for elements that look like 354 // clickable elements (e.g. small nodes with pointer-style cursor). 355 if (renderer->style().cursor() == CursorType::Pointer) { 356 if (rect.width() <= maxWidthForElementsThatLookClickable && rect.height() <= maxHeightForElementsThatLookClickable) 357 return true; 358 } 359 360 return false; 332 361 } 333 362 … … 710 739 return { }; 711 740 741 auto containerListensForUserActivation = listensForUserActivation(*containerForControls) ? ContainerListensForUserActivation::Yes : ContainerListensForUserActivation::No; 712 742 Vector<Ref<HTMLElement>> clickableControls; 713 743 for (auto& child : descendantsOfType<HTMLElement>(*containerForControls)) { 714 if (isClickableControl(child ))744 if (isClickableControl(child, containerListensForUserActivation)) 715 745 clickableControls.append(child); 716 746 } -
trunk/Tools/ChangeLog
r287859 r287860 1 2022-01-10 Wenson Hsieh <wenson_hsieh@apple.com> 2 3 Modal container observer should classify elements that are styled like clickable controls 4 https://bugs.webkit.org/show_bug.cgi?id=235022 5 6 Reviewed by Tim Horton. 7 8 Add a new API test to exercise the change, and adjust the test harness to allow tests using the harness to 9 additionally add an event listener on the modal container. 10 11 * TestWebKitAPI/Tests/WebKit/modal-container-custom.html: 12 * TestWebKitAPI/Tests/WebKitCocoa/ModalContainerObservation.mm: 13 (TestWebKitAPI::TEST): 14 1 15 2022-01-10 Jonathan Bedard <jbedard@apple.com> 2 16 -
trunk/Tools/TestWebKitAPI/Tests/WebKit/modal-container-custom.html
r287420 r287860 30 30 fixedContainer.style.display = "block"; 31 31 } 32 33 function showWithEventListener(markup, eventType, callback) { 34 const fixedContainer = document.getElementById("fixed"); 35 fixedContainer.addEventListener(eventType, callback); 36 fixedContainer.innerHTML = markup; 37 fixedContainer.style.display = "block"; 38 } 32 39 </script> 33 40 </head> -
trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ModalContainerObservation.mm
r287849 r287860 329 329 } 330 330 331 TEST(ModalContainerObservation, DetectControlsWithEventListenersOnModalContainer) 332 { 333 auto webView = createModalContainerWebView(); 334 [webView loadBundlePage:@"modal-container-custom"]; 335 auto script = @"showWithEventListener(`<div>Hello world <span style='cursor: pointer;'>yes</span></div>`, 'click', () => window.testPassed = true)"; 336 [webView evaluate:script andDecidePolicy:_WKModalContainerDecisionHideAndAllow]; 337 [webView waitForNextPresentationUpdate]; 338 EXPECT_FALSE([[webView contentsAsString] containsString:@"Hello world"]); 339 EXPECT_EQ([webView lastModalContainerInfo].availableTypes, _WKModalContainerControlTypePositive); 340 EXPECT_TRUE([[webView objectByEvaluatingJavaScript:@"window.testPassed"] boolValue]); 341 } 342 331 343 } // namespace TestWebKitAPI
Note:
See TracChangeset
for help on using the changeset viewer.