Commit 23a84fc3 authored by Sarthak Shah's avatar Sarthak Shah Committed by Commit Bot

Clear autoscroll latched target when view is destroyed

This is a regression from a fix for middle-click auto-scroll for
OOPIFs where input events get locked to a single target when moving
over OOPIFs (https://crrev.com/c/1773540). When middle-click
auto-scroll is in progress and the view is destroyed, we need to
clear the state of latched target. However, the previous CL missed
this fact.

This CL fixes the issue by clearing the state of middle-click latched
target when it is destroyed.

Bug: 1007983
Change-Id: Ie4d98fdc97b7cf14e193857e61212e193cfd7f62
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1825489
Commit-Queue: Sarthak Shah <sarsha@microsoft.com>
Reviewed-by: default avatarSadrul Chowdhury <sadrul@chromium.org>
Reviewed-by: default avatarDavid Bokan <bokan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#703918}
parent 83023149
......@@ -1974,7 +1974,7 @@ RenderWidgetHostInputEventRouter::GetMouseCaptureWidgetForTests() const {
void RenderWidgetHostInputEventRouter::SetAutoScrollInProgress(
bool is_autoscroll_in_progress) {
event_targeter_->set_is_auto_scroll_in_progress(is_autoscroll_in_progress);
event_targeter_->SetIsAutoScrollInProgress(is_autoscroll_in_progress);
}
} // namespace content
......@@ -909,4 +909,29 @@ TEST_F(RenderWidgetHostInputEventRouterTest, CanCallShowContextMenuAtPoint) {
view_root_.get());
}
// Input events get latched to a target when middle click autoscroll is in
// progress. This tests enusres that autoscroll latched target state is cleared
// when the view, input events are latched to is destroyed.
TEST_F(RenderWidgetHostInputEventRouterTest,
EnsureAutoScrollLatchedTargetIsCleared) {
ChildViewState child = MakeChildView(view_root_.get());
// Simulate middle click mouse event.
blink::WebMouseEvent mouse_event(
blink::WebInputEvent::kMouseDown, blink::WebInputEvent::kNoModifiers,
blink::WebInputEvent::GetStaticTimeStampForTests());
mouse_event.button = blink::WebPointerProperties::Button::kMiddle;
view_root_->SetHittestResult(child.view.get(), false);
RenderWidgetTargeter* targeter = rwhier()->GetRenderWidgetTargeterForTests();
rwhier()->RouteMouseEvent(view_root_.get(), &mouse_event,
ui::LatencyInfo(ui::SourceEventType::MOUSE));
// Set middle click autoscroll in progress to true.
rwhier()->SetAutoScrollInProgress(true);
// Destroy the view/target, middle click autoscroll is latched to.
rwhier()->OnRenderWidgetHostViewBaseDestroyed(child.view.get());
EXPECT_FALSE(targeter->is_auto_scroll_in_progress());
}
} // namespace content
......@@ -290,12 +290,25 @@ void RenderWidgetTargeter::ResolveTargetingRequest(TargetingRequest request) {
void RenderWidgetTargeter::ViewWillBeDestroyed(RenderWidgetHostViewBase* view) {
unresponsive_views_.erase(view);
if (is_autoscroll_in_progress_ && middle_click_result_.view == view) {
SetIsAutoScrollInProgress(false);
}
}
bool RenderWidgetTargeter::HasEventsPendingDispatch() const {
return request_in_flight_ || !requests_.empty();
}
void RenderWidgetTargeter::SetIsAutoScrollInProgress(
bool autoscroll_in_progress) {
is_autoscroll_in_progress_ = autoscroll_in_progress;
// If middle click autoscroll ends, reset |middle_click_result_|.
if (!autoscroll_in_progress)
middle_click_result_ = RenderWidgetTargetResult();
}
void RenderWidgetTargeter::QueryClientInternal(
RenderWidgetHostViewBase* target,
const gfx::PointF& target_location,
......
......@@ -134,13 +134,7 @@ class RenderWidgetTargeter {
return request_in_flight_.has_value();
}
void set_is_auto_scroll_in_progress(bool autoscroll_in_progress) {
is_autoscroll_in_progress_ = autoscroll_in_progress;
// If middle click autoscroll ends, reset |middle_click_result_|.
if (!autoscroll_in_progress)
middle_click_result_ = RenderWidgetTargetResult();
}
void SetIsAutoScrollInProgress(bool autoscroll_in_progress);
bool is_auto_scroll_in_progress() const { return is_autoscroll_in_progress_; }
......
<!DOCTYPE html>
<title>Clear middle click target if target is destroyed when autoscroll is in progress</title>
<style>
#target-iframe1 {
height: 100px;
width: 100px;
overflow-y: scroll;
position: absolute;
left: 100px;
top: 100px;
}
</style>
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
<script src='/js-test-resources/gesture-util.js'></script>
<script>
var container;
var iframeScrolled = false;
var iframeLoadCount = 0;
async_test(t => {
// On document load, perform middle click on the iframe to start the
// autoscroll. When middle click autoscroll is in progress on iframe,
// navigate iframe to another cross-domain url and perform mouse move
// on root frame. If the bug (crbug.com/1007983) repros, it will crash
// the process.
window.addEventListener('load', async () => {
container = document.getElementById('container');
var subFrame = document.getElementsByTagName('iframe')[0];
var startx = subFrame.offsetLeft + (subFrame.offsetWidth / 2);
var starty = subFrame.offsetTop;
// move the mouse inside the iframe.
await mouseMoveTo(startx + 10 , starty + 10);
// middle click in iframe to start autoscroll.
await mouseClickOn(startx + 10, starty + 10, 1);
await mouseMoveTo(startx + 10, starty + 30);
//wait for the iframe to scroll.
await waitFor(() => {
return (iframeScrolled === true);
});
t.step(() => { assert_equals(iframeLoadCount, 1)});
// Change the source of iframe to naviagate to a cross-domain url,
// so it will destory the view.
subFrame.src = 'about:blank';
// Wait for the iframe to load.
await waitFor(() => {
return (iframeLoadCount === 2);
});
// Peform mouse event on root frame. If the bug repros, renderer will
// crash.
await mouseMoveTo(10, 10);
t.done();
});
});
window.addEventListener("message", handleMessage);
function handleMessage(event){
if(event.data.scrollTop > 0) {
iframeScrolled = true;
}
}
function onIframeLoad(){
// Increment the count each time iframe is loaded.
iframeLoadCount = iframeLoadCount+1;
}
</script>
<div id="container" style="height: 400px; width: 400px; overflow: auto">
<div id="filler" style="height:4000px; width: 4000px"></div>
<iframe id="target-iframe1" onload="onIframeLoad()"
src= "http://localhost:8000/misc/resources/cross-origin-subframe-for-scrolling.html">
</iframe>
</div>
......@@ -33,6 +33,10 @@ function handleMessage(event) {
window.onscroll = (() => {
if (port) {
port.postMessage({scrolled: frame_id, scrollTop: document.documentElement.scrollTop}, "*");
} else{
// If parent is performing middle click autoscroll on iframe, send the
// scrollTop data back to parent.
parent.postMessage({scrolled: frame_id, scrollTop: document.documentElement.scrollTop}, "*");
}
});
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment