Commit a0ea017d authored by Lucas Gadani's avatar Lucas Gadani Committed by Commit Bot

Pointer lock: test crash recovery in oopif cases.

Since a RenderWidgetHostView is destroyed when a renderer process crashes, it
is necessary to null-check it before de-referencing it.
This CL is based on nick@'s CL: https://chromium-review.googlesource.com/c/chromium/src/+/956624

Bug: 859215
Change-Id: I029d3615fee56c9cd2287ee816b269338802937c
Reviewed-on: https://chromium-review.googlesource.com/1234873
Commit-Queue: Lucas Gadani <lfg@chromium.org>
Reviewed-by: default avatarCharlie Reis <creis@chromium.org>
Cr-Commit-Position: refs/heads/master@{#592883}
parent a6767cf7
......@@ -319,6 +319,55 @@ IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest,
root->current_frame_host()->GetRenderWidgetHost()));
}
IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockOopifCrashes) {
// This test runs three times, testing a crash at each level of the frametree.
for (int crash_depth = 0; crash_depth < 3; crash_depth++) {
GURL main_url(embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(b(c))"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
FrameTreeNode* root = web_contents()->GetFrameTree()->root();
FrameTreeNode* lock_node = root->child_at(0)->child_at(0);
// Pick which node to crash.
FrameTreeNode* crash_node = root;
for (int i = 0; i < crash_depth; i++)
crash_node = crash_node->child_at(0);
// Request a pointer lock to |lock_node|'s document.body.
EXPECT_EQ("success", EvalJs(lock_node, R"(
new Promise((resolve, reject) => {
document.addEventListener('pointerlockchange', resolve);
document.addEventListener('pointerlockerror', reject);
document.body.requestPointerLock();
}).then(() => 'success');
)"));
// Root (platform) RenderWidgetHostView should have the pointer locked.
EXPECT_TRUE(root->current_frame_host()->GetView()->IsMouseLocked());
EXPECT_EQ(lock_node->current_frame_host()->GetRenderWidgetHost(),
web_contents()->GetMouseLockWidget());
// Crash the process of |crash_node|.
RenderProcessHost* crash_process =
crash_node->current_frame_host()->GetProcess();
RenderProcessHostWatcher crash_observer(
crash_process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
crash_process->Shutdown(0);
crash_observer.Wait();
// This should cancel the pointer lock.
EXPECT_EQ(nullptr, web_contents()->GetMouseLockWidget());
EXPECT_EQ(nullptr, web_contents()->mouse_lock_widget_);
EXPECT_FALSE(web_contents()->HasMouseLock(
root->current_frame_host()->GetRenderWidgetHost()));
if (crash_depth != 0)
EXPECT_FALSE(root->current_frame_host()->GetView()->IsMouseLocked());
else
EXPECT_EQ(nullptr, root->current_frame_host()->GetView());
}
}
IN_PROC_BROWSER_TEST_F(PointerLockBrowserTest, PointerLockWheelEventRouting) {
GURL main_url(embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(b)"));
......
......@@ -2507,15 +2507,18 @@ bool WebContentsImpl::HasMouseLock(RenderWidgetHostImpl* render_widget_host) {
// To verify if the mouse is locked, the mouse_lock_widget_ needs to be
// assigned to the widget that requested the mouse lock, and the top-level
// platform RenderWidgetHostView needs to hold the mouse lock from the OS.
return mouse_lock_widget_ == render_widget_host &&
GetTopLevelRenderWidgetHostView()->IsMouseLocked();
auto* widget_host = GetTopLevelRenderWidgetHostView();
return mouse_lock_widget_ == render_widget_host && widget_host &&
widget_host->IsMouseLocked();
}
RenderWidgetHostImpl* WebContentsImpl::GetMouseLockWidget() {
if (GetTopLevelRenderWidgetHostView()->IsMouseLocked() ||
auto* widget_host = GetTopLevelRenderWidgetHostView();
if ((widget_host && widget_host->IsMouseLocked()) ||
(GetFullscreenRenderWidgetHostView() &&
GetFullscreenRenderWidgetHostView()->IsMouseLocked()))
GetFullscreenRenderWidgetHostView()->IsMouseLocked())) {
return mouse_lock_widget_;
}
return nullptr;
}
......
......@@ -1065,6 +1065,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
PageDisableWithNoDialogManager);
FRIEND_TEST_ALL_PREFIXES(PointerLockBrowserTest,
PointerLockInnerContentsCrashes);
FRIEND_TEST_ALL_PREFIXES(PointerLockBrowserTest, PointerLockOopifCrashes);
// So |find_request_manager_| can be accessed for testing.
friend class FindRequestManagerTest;
......
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