Skip to content

Commit

Permalink
Use Mojo For Pointer Lock Requests
Browse files Browse the repository at this point in the history
Pointer lock and unlock requests were still using the old IPC workflow.
This updates the call to use Mojo.

This CL is a copy of a merged and reverted CL. For reference to the
discussions here is the original: https://crrev.com/c/2028453

Bug: 1042293
Change-Id: I26c3c3cabce06437698f8b9ebed01d8476bb5eb9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2095402
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
Reviewed-by: Scott Violet <sky@chromium.org>
Commit-Queue: James Hollyer <jameshollyer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#748512}
  • Loading branch information
James Hollyer authored and Commit Bot committed Mar 10, 2020
1 parent 356ffd7 commit 5b0230f
Show file tree
Hide file tree
Showing 32 changed files with 265 additions and 223 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -407,9 +407,8 @@ IN_PROC_BROWSER_TEST_F(FlashFullscreenInteractiveBrowserTest,
web_contents->GetFullscreenRenderWidgetHostView();
content::RenderWidgetHost* fullscreen_widget =
fullscreen_view->GetRenderWidgetHost();
content::RenderProcessHost* process = fullscreen_widget->GetProcess();
content::PwnMessageHelper::LockMouse(
process, fullscreen_widget->GetRoutingID(), true, true, false);
content::RequestMouseLock(fullscreen_widget, /*from_user_gesture=*/true,
/*privileged=*/true, /*unadjusted_movement=*/false);

// Make sure that the fullscreen widget got the mouse lock.
EXPECT_TRUE(fullscreen_view->IsMouseLocked());
Expand Down
41 changes: 5 additions & 36 deletions content/browser/browser_plugin/browser_plugin_guest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ BrowserPluginGuest::BrowserPluginGuest(bool has_render_view,
browser_plugin_instance_id_(browser_plugin::kInstanceIDNone),
focused_(false),
mouse_locked_(false),
pending_lock_request_(false),
is_full_page_plugin_(false),
has_render_view_(has_render_view),
is_in_destruction_(false),
Expand Down Expand Up @@ -403,27 +402,6 @@ void BrowserPluginGuest::DidTextInputStateChange(const TextInputState& params) {
web_contents()->GetRenderWidgetHostView()));
}

void BrowserPluginGuest::DidLockMouse(bool user_gesture, bool privileged) {
if (pending_lock_request_) {
// Immediately reject the lock because only one pointerLock may be active
// at a time.
RenderWidgetHost* widget_host =
web_contents()->GetRenderViewHost()->GetWidget();
widget_host->Send(
new WidgetMsg_LockMouse_ACK(widget_host->GetRoutingID(), false));
return;
}

pending_lock_request_ = true;

RenderWidgetHostImpl* owner = GetOwnerRenderWidgetHost();
bool is_last_unlocked_by_target =
owner ? owner->is_last_unlocked_by_target() : false;

delegate_->RequestPointerLockPermission(
user_gesture, is_last_unlocked_by_target, base::BindOnce([](bool) {}));
}

void BrowserPluginGuest::DidUnlockMouse() {
}

Expand Down Expand Up @@ -566,17 +544,6 @@ void BrowserPluginGuest::OnExtendSelectionAndDelete(
rfh->GetFrameInputHandler()->ExtendSelectionAndDelete(before, after);
}

void BrowserPluginGuest::OnLockMouseAck(int browser_plugin_instance_id,
bool succeeded) {
RenderWidgetHost* widget_host =
web_contents()->GetRenderViewHost()->GetWidget();
widget_host->Send(
new WidgetMsg_LockMouse_ACK(widget_host->GetRoutingID(), succeeded));
pending_lock_request_ = false;
if (succeeded)
mouse_locked_ = true;
}

void BrowserPluginGuest::OnSetFocus(int browser_plugin_instance_id,
bool focused,
blink::mojom::FocusType focus_type) {
Expand All @@ -600,9 +567,11 @@ void BrowserPluginGuest::OnUnlockMouseAck(int browser_plugin_instance_id) {
// to window focus, or for various other reasons before the guest was informed
// of the lock's success.
if (mouse_locked_) {
RenderWidgetHost* widget_host =
web_contents()->GetRenderViewHost()->GetWidget();
widget_host->Send(new WidgetMsg_MouseLockLost(widget_host->GetRoutingID()));
mojom::WidgetInputHandler* input_handler = GetWebContents()
->GetRenderViewHost()
->GetWidget()
->GetWidgetInputHandler();
input_handler->MouseLockLost();
}
mouse_locked_ = false;
}
Expand Down
3 changes: 0 additions & 3 deletions content/browser/browser_plugin/browser_plugin_guest.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,6 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
// Methods to handle events from InputEventShim.
void DidSetHasTouchEventHandlers(bool accept);
void DidTextInputStateChange(const TextInputState& params);
void DidLockMouse(bool user_gesture, bool privileged);
void DidUnlockMouse();

// WebContentsObserver implementation.
Expand Down Expand Up @@ -259,7 +258,6 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
void OnExecuteEditCommand(int instance_id,
const std::string& command);

void OnLockMouseAck(int instance_id, bool succeeded);
// Resizes the guest's web contents.
void OnSetFocus(int instance_id,
bool focused,
Expand Down Expand Up @@ -330,7 +328,6 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
gfx::Rect frame_rect_;
bool focused_;
bool mouse_locked_;
bool pending_lock_request_;
// Whether the browser plugin is inside a plugin document.
bool is_full_page_plugin_;

Expand Down
17 changes: 17 additions & 0 deletions content/browser/pointer_lock_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,23 @@ IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockBasic) {
// Release pointer lock on root frame.
EXPECT_TRUE(ExecJs(root, "document.exitPointerLock()"));

// setup promise structure to ensure request finishes.
EXPECT_TRUE(ExecJs(child, R"(
var advertisementreceivedPromise = new Promise(resolve => {
document.addEventListener('pointerlockchange',
event => {
resolve(true);
});
});
)"));

// Request a pointer lock on the child frame's body.
EXPECT_TRUE(ExecJs(child, "document.body.requestPointerLock()"));

// ensure request finishes before moving on.
auto advertisementreceived_promise_result =
EvalJs(child, "advertisementreceivedPromise");

// Child frame should have been granted pointer lock.
EXPECT_EQ(true,
EvalJs(child, "document.pointerLockElement == document.body"));
Expand Down Expand Up @@ -610,6 +624,9 @@ IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockWidgetHidden) {
// Request a pointer lock on the child frame's body.
EXPECT_TRUE(ExecJs(child, "document.body.requestPointerLock()"));

// execute dummy js to run a js loop and finish the request
EXPECT_TRUE(ExecJs(child, ""));

// Child frame should have been granted pointer lock.
EXPECT_EQ(true,
EvalJs(child, "document.pointerLockElement == document.body"));
Expand Down
8 changes: 8 additions & 0 deletions content/browser/renderer_host/input/input_router_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "cc/input/touch_action.h"
#include "content/browser/renderer_host/event_with_latency_info.h"
#include "content/common/content_export.h"
#include "content/common/input/input_handler.mojom.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/common/input_event_ack_source.h"
#include "content/public/common/input_event_ack_state.h"
Expand Down Expand Up @@ -77,6 +78,13 @@ class CONTENT_EXPORT InputRouterClient {
// Called to toggle whether the RenderWidgetHost should capture all mouse
// input.
virtual void SetMouseCapture(bool capture) = 0;
virtual void RequestMouseLock(
bool from_user_gesture,
bool privileged,
bool unadjusted_movement,
mojom::WidgetInputHandlerHost::RequestMouseLockCallback response) = 0;

virtual void UnlockMouse() = 0;

virtual void FallbackCursorModeLockCursor(bool left,
bool right,
Expand Down
12 changes: 12 additions & 0 deletions content/browser/renderer_host/input/input_router_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,18 @@ void InputRouterImpl::SetMouseCapture(bool capture) {
client_->SetMouseCapture(capture);
}

void InputRouterImpl::RequestMouseLock(bool from_user_gesture,
bool privileged,
bool unadjusted_movement,
RequestMouseLockCallback response) {
client_->RequestMouseLock(from_user_gesture, privileged, unadjusted_movement,
std::move(response));
}

void InputRouterImpl::UnlockMouse() {
client_->UnlockMouse();
}

void InputRouterImpl::SetMovementXYForTouchPoints(blink::WebTouchEvent* event) {
for (size_t i = 0; i < event->touches_length; ++i) {
blink::WebTouchPoint* touch_point = &event->touches[i];
Expand Down
5 changes: 5 additions & 0 deletions content/browser/renderer_host/input/input_router_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ class CONTENT_EXPORT InputRouterImpl : public InputRouter,
const gfx::Range& range,
const std::vector<gfx::Rect>& bounds) override;
void SetMouseCapture(bool capture) override;
void RequestMouseLock(bool from_user_gesture,
bool privileged,
bool unadjusted_movement,
RequestMouseLockCallback response) override;
void UnlockMouse() override;
void OnHasTouchEventHandlers(bool has_handlers) override;
void WaitForInputProcessed(base::OnceClosure callback) override;
void FlushTouchEventQueue() override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,14 @@ class MockInputRouterImplClient : public InputRouterImplClient {

void SetMouseCapture(bool capture) override {}

void RequestMouseLock(bool from_user_gesture,
bool privileged,
bool unadjusted_movement,
mojom::WidgetInputHandlerHost::RequestMouseLockCallback
response) override {}

void UnlockMouse() override {}

void FallbackCursorModeLockCursor(bool left,
bool right,
bool up,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ class MockInputRouterClient : public InputRouterClient,
bool IsWheelScrollInProgress() override;
bool IsAutoscrollInProgress() override;
void SetMouseCapture(bool capture) override {}
void RequestMouseLock(bool user_gesture,
bool privileged,
bool unadjusted_movement,
mojom::WidgetInputHandlerHost::RequestMouseLockCallback
response) override {}
void UnlockMouse() override {}
void FallbackCursorModeLockCursor(bool left,
bool right,
bool up,
Expand Down
2 changes: 2 additions & 0 deletions content/browser/renderer_host/render_widget_host_delegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,8 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
bool last_unlocked_by_target,
bool privileged) {}

virtual void UnlockMouse(RenderWidgetHostImpl* render_widget_host) {}

// Returns whether the associated tab is in fullscreen mode.
virtual bool IsFullscreenForCurrentTab();

Expand Down
91 changes: 47 additions & 44 deletions content/browser/renderer_host/render_widget_host_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,9 @@ class UnboundWidgetInputHandler : public mojom::WidgetInputHandler {
void MouseCaptureLost() override {
DLOG(WARNING) << "Input request on unbound interface";
}
void MouseLockLost() override {
DLOG(WARNING) << "Input request on unbound interface";
}
void SetEditCommandsForNextKeyEvent(
const std::vector<content::EditCommand>& commands) override {
DLOG(WARNING) << "Input request on unbound interface";
Expand Down Expand Up @@ -572,8 +575,6 @@ bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
IPC_MESSAGE_HANDLER(WidgetHostMsg_AutoscrollEnd, OnAutoscrollEnd)
IPC_MESSAGE_HANDLER(WidgetHostMsg_TextInputStateChanged,
OnTextInputStateChanged)
IPC_MESSAGE_HANDLER(WidgetHostMsg_LockMouse, OnLockMouse)
IPC_MESSAGE_HANDLER(WidgetHostMsg_UnlockMouse, OnUnlockMouse)
IPC_MESSAGE_HANDLER(WidgetHostMsg_SelectionBoundsChanged,
OnSelectionBoundsChanged)
IPC_MESSAGE_HANDLER(DragHostMsg_StartDragging, OnStartDragging)
Expand Down Expand Up @@ -1016,7 +1017,7 @@ void RenderWidgetHostImpl::LostMouseLock() {
}

void RenderWidgetHostImpl::SendMouseLockLost() {
Send(new WidgetMsg_MouseLockLost(routing_id_));
widget_input_handler_->MouseLockLost();
}

void RenderWidgetHostImpl::ViewDestroyed() {
Expand Down Expand Up @@ -1935,9 +1936,11 @@ void RenderWidgetHostImpl::ImeCancelComposition() {
void RenderWidgetHostImpl::RejectMouseLockOrUnlockIfNecessary() {
DCHECK(!pending_mouse_lock_request_ || !IsMouseLocked());
if (pending_mouse_lock_request_) {
DCHECK(request_mouse_callback_);
pending_mouse_lock_request_ = false;
mouse_lock_raw_movement_ = false;
Send(new WidgetMsg_LockMouse_ACK(routing_id_, false));
std::move(request_mouse_callback_).Run(/*success=*/false);

} else if (IsMouseLocked()) {
view_->UnlockMouse();
}
Expand Down Expand Up @@ -2407,6 +2410,43 @@ void RenderWidgetHostImpl::SetMouseCapture(bool capture) {
delegate_->GetInputEventRouter()->SetMouseCaptureTarget(GetView(), capture);
}

void RenderWidgetHostImpl::RequestMouseLock(
bool from_user_gesture,
bool privileged,
bool unadjusted_movement,
InputRouterImpl::RequestMouseLockCallback response) {
if (pending_mouse_lock_request_) {
std::move(response).Run(/*success=*/false);
return;
}

request_mouse_callback_ = std::move(response);

pending_mouse_lock_request_ = true;
mouse_lock_raw_movement_ = unadjusted_movement;
if (delegate_) {
delegate_->RequestToLockMouse(this, from_user_gesture,
is_last_unlocked_by_target_,
privileged && allow_privileged_mouse_lock_);
// We need to reset |is_last_unlocked_by_target_| here as we don't know
// request source in |LostMouseLock()|.
is_last_unlocked_by_target_ = false;
return;
}

// Directly reject or approve the mouse lock based on privilege.
GotResponseToLockMouseRequest(allow_privileged_mouse_lock_ && privileged);
}

void RenderWidgetHostImpl::UnlockMouse() {
// Got unlock request from renderer. Will update |is_last_unlocked_by_target_|
// for silent re-lock.
const bool was_mouse_locked = !pending_mouse_lock_request_ && IsMouseLocked();
RejectMouseLockOrUnlockIfNecessary();
if (was_mouse_locked)
is_last_unlocked_by_target_ = true;
}

void RenderWidgetHostImpl::FallbackCursorModeLockCursor(bool left,
bool right,
bool up,
Expand All @@ -2433,44 +2473,6 @@ void RenderWidgetHostImpl::OnProcessSwapMessage(const IPC::Message& message) {
rph->OnMessageReceived(message);
}

void RenderWidgetHostImpl::OnLockMouse(bool user_gesture,
bool privileged,
bool request_unadjusted_movement) {
if (pending_mouse_lock_request_) {
Send(new WidgetMsg_LockMouse_ACK(routing_id_, false));
return;
}

pending_mouse_lock_request_ = true;
mouse_lock_raw_movement_ = request_unadjusted_movement;
if (delegate_) {
delegate_->RequestToLockMouse(this, user_gesture,
is_last_unlocked_by_target_,
privileged && allow_privileged_mouse_lock_);
// We need to reset |is_last_unlocked_by_target_| here as we don't know
// request source in |LostMouseLock()|.
is_last_unlocked_by_target_ = false;
return;
}

if (privileged && allow_privileged_mouse_lock_) {
// Directly approve to lock the mouse.
GotResponseToLockMouseRequest(true);
} else {
// Otherwise, just reject it.
GotResponseToLockMouseRequest(false);
}
}

void RenderWidgetHostImpl::OnUnlockMouse() {
// Got unlock request from renderer. Will update |is_last_unlocked_by_target_|
// for silent re-lock.
const bool was_mouse_locked = !pending_mouse_lock_request_ && IsMouseLocked();
RejectMouseLockOrUnlockIfNecessary();
if (was_mouse_locked)
is_last_unlocked_by_target_ = true;
}

bool RenderWidgetHostImpl::RequestKeyboardLock(
base::Optional<base::flat_set<ui::DomCode>> codes) {
if (!delegate_) {
Expand Down Expand Up @@ -2719,14 +2721,15 @@ bool RenderWidgetHostImpl::GotResponseToLockMouseRequest(bool allowed) {
return false;
}

DCHECK(request_mouse_callback_);
pending_mouse_lock_request_ = false;
if (!view_ || !view_->HasFocus() ||
!view_->LockMouse(mouse_lock_raw_movement_)) {
Send(new WidgetMsg_LockMouse_ACK(routing_id_, false));
std::move(request_mouse_callback_).Run(/*success=*/false);
return false;
}

Send(new WidgetMsg_LockMouse_ACK(routing_id_, true));
std::move(request_mouse_callback_).Run(/*success=*/true);
return true;
}

Expand Down
Loading

0 comments on commit 5b0230f

Please sign in to comment.