Commit 5c8c1f9c authored by Scott Violet's avatar Scott Violet Committed by Commit Bot

chromeos: adds timeout to waiting for events

This way, if a client is too slow we'll inject the next event. I have no
doubt we will need more sophisticated things, but this is a start to ensure
we don't get entirely wedged.

BUG=none
TEST=covered by test

Change-Id: If4c233431be3239476227fc0271a5bc18cfff479
Reviewed-on: https://chromium-review.googlesource.com/c/1303353
Commit-Queue: Scott Violet <sky@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#603695}
parent 2063ba8e
......@@ -18,6 +18,13 @@
namespace ws {
namespace {
constexpr base::TimeDelta kEventAckTimeout =
#if defined(NDEBUG)
base::TimeDelta::FromMilliseconds(100);
#else
base::TimeDelta::FromMilliseconds(1000);
#endif
bool IsQueableEvent(const ui::Event& event) {
return event.IsKeyEvent();
}
......@@ -92,6 +99,12 @@ HostEventQueue* EventQueue::GetHostEventQueueForDisplay(int64_t display_id) {
return nullptr;
}
void EventQueue::OnClientTookTooLongToAckEvent() {
DVLOG(1) << "Client took too long to respond to event";
DCHECK(in_flight_event_);
OnClientAckedEvent(in_flight_event_->client_id, in_flight_event_->event_id);
}
void EventQueue::OnHostEventQueueCreated(HostEventQueue* host) {
host_event_queues_.insert(host);
}
......@@ -137,7 +150,8 @@ void EventQueue::OnWillSendEventToClient(ClientSpecificId client_id,
in_flight_event_ = InFlightEvent();
in_flight_event_->client_id = client_id;
in_flight_event_->event_id = event_id;
// TODO(sky): kick off timer.
ack_timer_.Start(FROM_HERE, kEventAckTimeout, this,
&EventQueue::OnClientTookTooLongToAckEvent);
}
}
......@@ -148,6 +162,7 @@ void EventQueue::OnClientAckedEvent(ClientSpecificId client_id,
return;
}
in_flight_event_.reset();
ack_timer_.Stop();
DispatchNextQueuedEvent();
}
......
......@@ -16,6 +16,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/timer/timer.h"
#include "services/ws/ids.h"
#include "services/ws/window_service_observer.h"
......@@ -81,6 +82,10 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) EventQueue
uint32_t event_id = 0u;
};
// Called by |ack_timer_| if the client does not respond to the event in a
// timely manner.
void OnClientTookTooLongToAckEvent();
// Called when a HostEventQueue is created/deleted.
void OnHostEventQueueCreated(HostEventQueue* host);
void OnHostEventQueueDestroyed(HostEventQueue* host);
......@@ -112,6 +117,8 @@ class COMPONENT_EXPORT(WINDOW_SERVICE) EventQueue
// Set of HostEventQueues.
std::set<HostEventQueue*> host_event_queues_;
base::OneShotTimer ack_timer_;
// Because of destruction order HostEventQueues may outlive this.
base::WeakPtrFactory<EventQueue> weak_factory_{this};
......
......@@ -34,4 +34,8 @@ void EventQueueTestHelper::AckInFlightEvent() {
NOTREACHED();
}
void EventQueueTestHelper::RunAckTimer() {
event_queue_->ack_timer_.FireNow();
}
} // namespace ws
......@@ -21,6 +21,9 @@ class EventQueueTestHelper {
void AckInFlightEvent();
// Forces |EventQueue::ack_timer_| to run now.
void RunAckTimer();
private:
EventQueue* event_queue_;
......
......@@ -117,5 +117,33 @@ TEST(EventQueueTest, NotifyWhenReadyToDispatch) {
EXPECT_TRUE(was_dispatch_closure_run);
}
TEST(EventQueueTest, Timeout) {
WindowServiceTestSetup setup;
setup.set_ack_events_immediately(false);
// Events are only queued if they target a window with a remote client.
aura::Window* top_level =
setup.window_tree_test_helper()->NewTopLevelWindow();
ASSERT_TRUE(top_level);
top_level->Show();
top_level->Focus();
EXPECT_TRUE(top_level->HasFocus());
// Generate a single key event.
EventQueueTestHelper event_queue_test_helper(setup.service()->event_queue());
ui::test::EventGenerator event_generator(setup.root());
event_generator.PressKey(ui::VKEY_A, ui::EF_NONE);
EXPECT_TRUE(event_queue_test_helper.HasInFlightEvent());
// Add a closure to be run when the event is acked, or the timeout occurs.
bool was_dispatch_closure_run = false;
setup.service()->event_queue()->NotifyWhenReadyToDispatch(
base::BindLambdaForTesting([&]() { was_dispatch_closure_run = true; }));
EXPECT_FALSE(was_dispatch_closure_run);
event_queue_test_helper.RunAckTimer();
EXPECT_TRUE(was_dispatch_closure_run);
}
} // namespace
} // namespace ws
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