Commit 47f53f43 authored by Scott Violet's avatar Scott Violet Committed by Commit Bot

window-service: disallow capture with kEmbedFlagEmbedderInterceptsEvents

This is primarily to prevent a bad renderer from forcing capture.

BUG=621234
TEST=none

Change-Id: I66475bff12f260f8adaf95c1ee0d65d3931bf58d
Reviewed-on: https://chromium-review.googlesource.com/1241834
Commit-Queue: Scott Violet <sky@chromium.org>
Reviewed-by: default avatarMichael Wasserman <msw@chromium.org>
Cr-Commit-Position: refs/heads/master@{#593817}
parent 6c37e934
......@@ -451,6 +451,15 @@ bool WindowTree::IsWindowRootOfAnotherClient(aura::Window* window) const {
server_window->embedded_window_tree() != this;
}
bool WindowTree::DoesAnyAncestorInterceptEvents(ServerWindow* window) {
if (window->embedding() && window->embedding()->embedding_tree() != this &&
window->embedding()->embedding_tree_intercepts_events()) {
return true;
}
ServerWindow* parent = ServerWindow::GetMayBeNull(window->window()->parent());
return parent && DoesAnyAncestorInterceptEvents(parent);
}
void WindowTree::OnCaptureLost(aura::Window* lost_capture) {
DCHECK(IsWindowKnown(lost_capture));
window_tree_client_->OnCaptureChanged(kInvalidTransportId,
......@@ -772,6 +781,14 @@ bool WindowTree::SetCaptureImpl(const ClientWindowId& window_id) {
ServerWindow* server_window = ServerWindow::GetMayBeNull(window);
if (DoesAnyAncestorInterceptEvents(server_window)) {
// If an ancestor is intercepting events, than the descendants are not
// allowed to set capture. This is primarily to prevent renderers from
// setting capture.
DVLOG(1) << "SetCapture failed (ancestor intercepts events)";
return false;
}
wm::CaptureController* capture_controller = wm::CaptureController::Get();
DCHECK(capture_controller);
......
......@@ -208,6 +208,9 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) WindowTree
bool IsWindowRootOfAnotherClient(aura::Window* window) const;
// Returns true if |window| has an ancestor that intercepts events.
bool DoesAnyAncestorInterceptEvents(ServerWindow* window);
// Called when one of the windows known to the client loses capture.
// |lost_capture| is the window that had capture.
void OnCaptureLost(aura::Window* lost_capture);
......
......@@ -962,6 +962,21 @@ TEST(WindowTreeTest, Capture) {
EXPECT_TRUE(setup.window_tree_test_helper()->ReleaseCapture(window));
}
TEST(WindowTreeTest, CaptureDisallowedWhenEmbedderInterceptsEvents) {
WindowServiceTestSetup setup;
aura::Window* top_level =
setup.window_tree_test_helper()->NewTopLevelWindow();
ASSERT_TRUE(top_level);
top_level->Show();
aura::Window* window = setup.window_tree_test_helper()->NewWindow();
top_level->AddChild(window);
window->Show();
std::unique_ptr<EmbeddingHelper> embedding_helper =
setup.CreateEmbedding(window, mojom::kEmbedFlagEmbedderInterceptsEvents);
ASSERT_TRUE(embedding_helper);
EXPECT_FALSE(embedding_helper->window_tree_test_helper->SetCapture(window));
}
TEST(WindowTreeTest, TransferCaptureToClient) {
EventRecordingWindowDelegate window_delegate;
WindowServiceTestSetup setup;
......@@ -1166,52 +1181,6 @@ TEST(WindowTreeTest, EventsGoToCaptureWindow) {
LocatedEventToEventTypeAndLocation(drag_event.event.get()));
}
TEST(WindowTreeTest, InterceptEventsOnEmbeddedWindowWithCapture) {
EventRecordingWindowDelegate window_delegate;
WindowServiceTestSetup setup;
aura::Window* window = setup.window_tree_test_helper()->NewWindow();
ASSERT_TRUE(window);
setup.delegate()->set_delegate_for_next_top_level(&window_delegate);
aura::Window* top_level =
setup.window_tree_test_helper()->NewTopLevelWindow();
ASSERT_TRUE(top_level);
top_level->AddChild(window);
top_level->Show();
window->Show();
// Create an embedding, and a new window in the embedding.
std::unique_ptr<EmbeddingHelper> embedding_helper =
setup.CreateEmbedding(window, mojom::kEmbedFlagEmbedderInterceptsEvents);
ASSERT_TRUE(embedding_helper);
aura::Window* window_in_child =
embedding_helper->window_tree_test_helper->NewWindow();
ASSERT_TRUE(window_in_child);
window_in_child->Show();
window->AddChild(window_in_child);
EXPECT_TRUE(
embedding_helper->window_tree_test_helper->SetCapture(window_in_child));
// Do an initial move (which generates some additional events) and clear
// everything out.
ui::test::EventGenerator event_generator(setup.root());
event_generator.MoveMouseTo(5, 5);
setup.window_tree_client()->ClearInputEvents();
window_delegate.ClearEvents();
embedding_helper->window_tree_client.ClearInputEvents();
// Move the mouse. Even though the window in the embedding has capture, the
// event should go to the parent client (setup.window_tree_client()), because
// the embedding was created such that the embedder (parent) intercepts the
// events.
event_generator.MoveMouseTo(6, 6);
EXPECT_TRUE(window_delegate.events().empty());
EXPECT_EQ("POINTER_MOVED",
EventToEventType(
setup.window_tree_client()->PopInputEvent().event.get()));
EXPECT_TRUE(setup.window_tree_client()->input_events().empty());
EXPECT_TRUE(embedding_helper->window_tree_client.input_events().empty());
}
TEST(WindowTreeTest, PointerDownResetOnCaptureChange) {
WindowServiceTestSetup setup;
aura::Window* window = setup.window_tree_test_helper()->NewWindow();
......
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