-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor logic for muting autoplaying video elements in background tabs
https://bugs.webkit.org/show_bug.cgi?id=273633 rdar://125859510 Reviewed by Aditya Keerthi. Refactor some logic related to muting media elements. See below for more details. * LayoutTests/fast/element-targeting/target-video-in-subframe-expected.txt: Added. * LayoutTests/fast/element-targeting/target-video-in-subframe.html: Added. * LayoutTests/resources/ui-helper.js: (window.UIHelper.resetVisibilityAdjustments): (window.UIHelper): Add a new layout test (and testing hooks) to exercise the change. * Source/WebCore/dom/Document.cpp: (WebCore::Document::visibilityAdjustmentStateDidChange): Add plumbing to propagate visibility state change to all audio producers. * Source/WebCore/dom/Document.h: * Source/WebCore/dom/Element.cpp: (WebCore::Element::setVisibilityAdjustment): Set a flag on `Page` to indicate that we've applied visibility adjustment to at least one element before. Used in `isInVisibilityAdjustmentSubtree()` below to exit right away, in the common case where there has never been visibility adjustment. (WebCore::Element::isInVisibilityAdjustmentSubtree const): Add a helper method to compute whether or not the element is inside of a visibility adjustment subtree, by traversing ancestors in the DOM. * Source/WebCore/dom/Element.h: * Source/WebCore/html/HTMLMediaElement.cpp: (WebCore::HTMLMediaElement::didFinishInsertingNode): (WebCore::HTMLMediaElement::removedFromAncestor): (WebCore::HTMLMediaElement::visibilityAdjustmentStateDidChange): Recompute and cache the visibility adjustment subtree state whenever the media element is unparented, re-parented, or visibility state otherwise changes. (WebCore::HTMLMediaElement::effectiveMuted const): Consult the cached state flag that's updated above when determining whether the media element should be `effectivelyMuted()`. * Source/WebCore/html/HTMLMediaElement.h: * Source/WebCore/page/ElementTargetingController.cpp: (WebCore::hasAudibleMedia): (WebCore::targetedElementInfo): Add support for a `hasAudibleMedia` flag on targeted element info. (WebCore::findOnlyMainElement): (WebCore::isNavigationalElement): (WebCore::containsNavigationalElement): Drive-by fix: mark the arguments to a few helper functions as `const`. (WebCore::ElementTargetingController::adjustVisibility): (WebCore::ElementTargetingController::adjustVisibilityInRepeatedlyTargetedRegions): (WebCore::ElementTargetingController::resetVisibilityAdjustments): (WebCore::ElementTargetingController::dispatchVisibilityAdjustmentStateDidChange): * Source/WebCore/page/ElementTargetingController.h: * Source/WebCore/page/ElementTargetingTypes.h: * Source/WebCore/page/MediaProducer.h: (WebCore::MediaProducer::visibilityAdjustmentStateDidChange): Add a new delegate hook to inform media producers when visibility state changes. Currently, this is only implemented by `HTMLMediaElement`, which allows it to adjust whether or not the underlying media player should be muted, through `effectiveMuted()`. * Source/WebCore/page/Page.cpp: (WebCore::Page::didCommitLoad): * Source/WebCore/page/Page.h: Add a boolean flag to track whether or not there has ever been any visibility adjustment in the page (this bit is cleared out in `didCommitLoad` above). (WebCore::Page::hasEverSetVisibilityAdjustment const): (WebCore::Page::didSetVisibilityAdjustment): * Source/WebCore/testing/Internals.cpp: (WebCore::Internals::isEffectivelyMuted): * Source/WebCore/testing/Internals.h: * Source/WebCore/testing/Internals.idl: Add a new testing-only hook to ask for `HTMLMediaElement::effectiveMuted()`. * Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in: * Source/WebKit/UIProcess/API/APITargetedElementInfo.h: * Source/WebKit/UIProcess/API/Cocoa/_WKTargetedElementInfo.h: * Source/WebKit/UIProcess/API/Cocoa/_WKTargetedElementInfo.mm: (-[_WKTargetedElementInfo hasAudibleMedia]): * Tools/TestRunnerShared/UIScriptContext/Bindings/UIScriptController.idl: * Tools/TestRunnerShared/UIScriptContext/UIScriptController.h: (WTR::UIScriptController::resetVisibilityAdjustments): * Tools/WebKitTestRunner/cocoa/UIScriptControllerCocoa.h: * Tools/WebKitTestRunner/cocoa/UIScriptControllerCocoa.mm: (WTR::UIScriptControllerCocoa::resetVisibilityAdjustments): Canonical link: https://commits.webkit.org/278356@main
- Loading branch information
Showing
26 changed files
with
281 additions
and
9 deletions.
There are no files selected for viewing
14 changes: 14 additions & 0 deletions
14
LayoutTests/fast/element-targeting/target-video-in-subframe-expected.txt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
PASS originalVideo.muted is false | ||
PASS originalVideo.volume is 1 | ||
PASS internals.isEffectivelyMuted(originalVideo) is true | ||
PASS clonedVideo.muted is false | ||
PASS clonedVideo.volume is 1 | ||
PASS internals.isEffectivelyMuted(clonedVideo) is true | ||
After reset: | ||
PASS internals.isEffectivelyMuted(originalVideo) is false | ||
PASS internals.isEffectivelyMuted(clonedVideo) is false | ||
PASS successfullyParsed is true | ||
|
||
TEST COMPLETE | ||
|
||
This test requires WebKitTestRunner |
84 changes: 84 additions & 0 deletions
84
LayoutTests/fast/element-targeting/target-video-in-subframe.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] --> | ||
<html> | ||
<head> | ||
<meta name="viewport" content="width=device-width, initial-scale=1"> | ||
<script src="../../resources/ui-helper.js"></script> | ||
<script src="../../resources/js-test.js"></script> | ||
<style> | ||
body, html { | ||
margin: 0; | ||
} | ||
|
||
div.container { | ||
width: 320px; | ||
height: 240px; | ||
border: 1px solid gray; | ||
box-sizing: border-box; | ||
text-align: center; | ||
} | ||
|
||
iframe { | ||
width: 100%; | ||
height: 100%; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<div class="container"> | ||
<iframe></iframe> | ||
</div> | ||
<div>This test requires WebKitTestRunner</div> | ||
</body> | ||
<script> | ||
jsTestIsAsync = true; | ||
|
||
addEventListener("load", async event => { | ||
const frame = document.querySelector("iframe"); | ||
await new Promise(resolve => { | ||
frame.addEventListener("load", resolve, { once: true }); | ||
frame.srcdoc = ` | ||
<head> | ||
<style> | ||
video { | ||
width: 160px; | ||
height: 120px; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<video src="../../media/content/audio-describes-video.mp4" loop autoplay /> | ||
<script> | ||
function cloneVideo() { | ||
const originalVideo = document.querySelector("video"); | ||
const clonedVideo = document.createElement("video"); | ||
clonedVideo.src = originalVideo.src; | ||
clonedVideo.autoplay = true; | ||
clonedVideo.loop = true; | ||
document.body.appendChild(clonedVideo); | ||
return [originalVideo, clonedVideo]; | ||
} | ||
</` + `script> | ||
</body>`; | ||
}); | ||
|
||
await UIHelper.adjustVisibilityForFrontmostTarget(100, 100); | ||
|
||
[originalVideo, clonedVideo] = frame.contentWindow.cloneVideo(); | ||
|
||
shouldBeFalse("originalVideo.muted"); | ||
shouldBe("originalVideo.volume", "1"); | ||
shouldBeTrue("internals.isEffectivelyMuted(originalVideo)"); | ||
|
||
shouldBeFalse("clonedVideo.muted"); | ||
shouldBe("clonedVideo.volume", "1"); | ||
shouldBeTrue("internals.isEffectivelyMuted(clonedVideo)"); | ||
|
||
await UIHelper.resetVisibilityAdjustments(); | ||
|
||
debug("After reset:"); | ||
shouldBeFalse("internals.isEffectivelyMuted(originalVideo)"); | ||
shouldBeFalse("internals.isEffectivelyMuted(clonedVideo)"); | ||
finishJSTest(); | ||
}); | ||
</script> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.