Skip to content

Commit

Permalink
Capture mouse input to plugins on MouseDown
Browse files Browse the repository at this point in the history
When a user presses a mouse button over a PDF, the PDF receives all
mouse input until there is a corresponding MouseUp. This is currently
broken for OOPIFs because the browser process doesn't know when a PDF
is supposed to capture input and so it doesn't always route events to
the right process. This change causes renderers to signal the browser
process for mouse capture when a PDF is is clicked.

Bug: 864957
Change-Id: If17587d5ca475d9a8ac03a3bba301d4084e6d4e3
Reviewed-on: https://chromium-review.googlesource.com/c/1203883
Commit-Queue: Ken Buchanan <kenrb@chromium.org>
Reviewed-by: Dave Tapuska <dtapuska@chromium.org>
Reviewed-by: James MacLean <wjmaclean@chromium.org>
Reviewed-by: Alex Moshchuk <alexmos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#596893}
  • Loading branch information
kenrb authored and Commit Bot committed Oct 4, 2018
1 parent bfcf456 commit d1d30d1
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -1709,4 +1709,11 @@ void RenderWidgetHostInputEventRouter::SetMouseCaptureTarget(
mouse_capture_target_.target = nullptr;
}

RenderWidgetHostImpl*
RenderWidgetHostInputEventRouter::GetMouseCaptureWidgetForTests() const {
if (mouse_capture_target_.target)
return mouse_capture_target_.target->host();
return nullptr;
}

} // namespace content
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter
// Allows a target to claim or release capture of mouse events.
void SetMouseCaptureTarget(RenderWidgetHostViewBase* target,
bool captures_dragging);
RenderWidgetHostImpl* GetMouseCaptureWidgetForTests() const;

std::vector<RenderWidgetHostView*> GetRenderWidgetHostViewsForTests() const;
RenderWidgetTargeter* GetRenderWidgetTargeterForTests();
Expand Down
21 changes: 21 additions & 0 deletions content/public/test/browser_test_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -786,6 +786,21 @@ void SimulateRoutedMouseClickAt(WebContents* web_contents,
ui::LatencyInfo());
}

void SendMouseDownToWidget(RenderWidgetHost* target,
int modifiers,
blink::WebMouseEvent::Button button) {
auto* view = static_cast<content::RenderWidgetHostImpl*>(target)->GetView();

blink::WebMouseEvent mouse_event(blink::WebInputEvent::kMouseDown, modifiers,
ui::EventTimeForNow());
mouse_event.button = button;
int x = view->GetViewBounds().width() / 2;
int y = view->GetViewBounds().height() / 2;
mouse_event.SetPositionInWidget(x, y);
mouse_event.click_count = 1;
target->ForwardMouseEvent(mouse_event);
}

void SimulateMouseEvent(WebContents* web_contents,
blink::WebInputEvent::Type type,
const gfx::Point& point) {
Expand Down Expand Up @@ -1876,6 +1891,12 @@ RenderWidgetHost* GetKeyboardLockWidget(WebContents* web_contents) {
return static_cast<WebContentsImpl*>(web_contents)->GetKeyboardLockWidget();
}

RenderWidgetHost* GetMouseCaptureWidget(WebContents* web_contents) {
return static_cast<WebContentsImpl*>(web_contents)
->GetInputEventRouter()
->GetMouseCaptureWidgetForTests();
}

bool RequestKeyboardLock(WebContents* web_contents,
base::Optional<base::flat_set<ui::DomCode>> codes) {
DCHECK(!codes.has_value() || !codes.value().empty());
Expand Down
12 changes: 12 additions & 0 deletions content/public/test/browser_test_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,12 @@ void SimulateRoutedMouseClickAt(WebContents* web_contents,
blink::WebMouseEvent::Button button,
const gfx::Point& point);

// Simulates MouseDown at the center of the given RenderWidgetHost's area.
// This does not send a corresponding MouseUp.
void SendMouseDownToWidget(RenderWidgetHost* target,
int modifiers,
blink::WebMouseEvent::Button button);

// Simulates asynchronously a mouse enter/move/leave event.
void SimulateMouseEvent(WebContents* web_contents,
blink::WebInputEvent::Type type,
Expand Down Expand Up @@ -840,6 +846,12 @@ RenderWidgetHost* GetMouseLockWidget(WebContents* web_contents);
// Returns the RenderWidgetHost that holds the keyboard lock.
RenderWidgetHost* GetKeyboardLockWidget(WebContents* web_contents);

// Returns the RenderWidgetHost that holds mouse capture, if any. This is
// distinct from MouseLock above in that it is a widget that has requested
// implicit capture, such as during a drag. MouseLock is explicitly gained
// through the JavaScript API.
RenderWidgetHost* GetMouseCaptureWidget(WebContents* web_contents);

// Allows tests to drive keyboard lock functionality without requiring access
// to the RenderWidgetHostImpl header or setting up an HTTP test server.
// |codes| represents the set of keys to lock. If |codes| has no value, then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -341,4 +341,24 @@ IN_PROC_BROWSER_TEST_F(MimeHandlerViewBrowserPluginSpecificTest,
FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
run_loop.Run();
}
}
}

// Verify that a BrowserPlugin captures mouse input on MouseDown.
IN_PROC_BROWSER_TEST_F(MimeHandlerViewBrowserPluginSpecificTest,
MouseCaptureOnMouseDown) {
RunTest("testBasic.csv");
auto* guest_web_contents = GetGuestViewManager()->WaitForSingleGuestCreated();
auto* guest_widget = MimeHandlerViewGuest::FromWebContents(guest_web_contents)
->GetOwnerRenderWidgetHost();
auto* embedder_web_contents = GetEmbedderWebContents();

SendMouseDownToWidget(guest_widget, 0, blink::WebMouseEvent::Button::kLeft);

while (!GetMouseCaptureWidget(embedder_web_contents)) {
base::RunLoop run_loop;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
run_loop.Run();
}
EXPECT_EQ(GetMouseCaptureWidget(embedder_web_contents), guest_widget);
}
3 changes: 3 additions & 0 deletions third_party/blink/renderer/core/exported/web_view_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,7 @@ void WebViewImpl::HandleMouseDown(LocalFrame& main_frame,
if (!result.GetScrollbar() && hit_node && hit_node->GetLayoutObject() &&
hit_node->GetLayoutObject()->IsEmbeddedObject()) {
mouse_capture_node_ = hit_node;
page_->DeprecatedLocalMainFrame()->Client()->SetMouseCapture(true);
TRACE_EVENT_ASYNC_BEGIN0("input", "capturing mouse", this);
}
}
Expand Down Expand Up @@ -1847,6 +1848,8 @@ void WebViewImpl::SetCursorVisibilityState(bool is_visible) {
void WebViewImpl::MouseCaptureLost() {
TRACE_EVENT_ASYNC_END0("input", "capturing mouse", this);
mouse_capture_node_ = nullptr;
if (page_->DeprecatedLocalMainFrame())
page_->DeprecatedLocalMainFrame()->Client()->SetMouseCapture(false);
}

void WebViewImpl::SetFocus(bool enable) {
Expand Down

0 comments on commit d1d30d1

Please sign in to comment.