Commit eccc2d43 authored by alexeypa@google.com's avatar alexeypa@google.com

Revert 176126 - the reverted change depends on another CL, so reverting it...

Revert 176126 - the reverted change depends on another CL, so reverting it breaks the build. Undoing the revert.

> Revert 175648 because it causes http://crbug.com/169126.
> 
> > Connect to DesktopEnvironment's stubs only when audio/video schedulers are about to be created.
> > 
> > This CL localizes usage of DesktopEnvironment to a single method that creates audio/video schedulers and hook up the event executor. This prepares further refactoring of DesktopEnvironment that should become a factory for classes interacting with the specific desktop environment.
> > 
> > Related changes in this CL:
> >   - MouseClampingFilter receives screen size on the proper thread.
> >   - ClientSessionTest.* tests now run asynchronously to support MouseClampingFilter change.
> >   - ClientSession does not expose DesktopEnvironment.
> >   - InputEventTracker can be re-attached to a different InputStub.
> > 
> > BUG=104544
> > 
> > 
> > Review URL: https://chromiumcodereview.appspot.com/11781003
> 
> TBR=alexeypa@chromium.org
> BUG=104544,169126
> Review URL: https://codereview.chromium.org/11817048

TBR=alexeypa@google.com

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@176130 0039d316-1c4b-4281-b951-d872f2087c98
parent 7dcba24f
...@@ -12,8 +12,8 @@ namespace remoting { ...@@ -12,8 +12,8 @@ namespace remoting {
// VideoFrameCapturerFake generates a white picture of size kWidth x kHeight // VideoFrameCapturerFake generates a white picture of size kWidth x kHeight
// with a rectangle of size kBoxWidth x kBoxHeight. The rectangle moves kSpeed // with a rectangle of size kBoxWidth x kBoxHeight. The rectangle moves kSpeed
// pixels per frame along both axes, and bounces off the sides of the screen. // pixels per frame along both axes, and bounces off the sides of the screen.
static const int kWidth = 800; static const int kWidth = VideoFrameCapturerFake::kWidth;
static const int kHeight = 600; static const int kHeight = VideoFrameCapturerFake::kHeight;
static const int kBoxWidth = 140; static const int kBoxWidth = 140;
static const int kBoxHeight = 140; static const int kBoxHeight = 140;
static const int kSpeed = 20; static const int kSpeed = 20;
......
...@@ -17,6 +17,10 @@ namespace remoting { ...@@ -17,6 +17,10 @@ namespace remoting {
// See remoting/host/video_frame_capturer.h. // See remoting/host/video_frame_capturer.h.
class VideoFrameCapturerFake : public VideoFrameCapturer { class VideoFrameCapturerFake : public VideoFrameCapturer {
public: public:
// VideoFrameCapturerFake generates a picture of size kWidth x kHeight.
static const int kWidth = 800;
static const int kHeight = 600;
VideoFrameCapturerFake(); VideoFrameCapturerFake();
virtual ~VideoFrameCapturerFake(); virtual ~VideoFrameCapturerFake();
......
...@@ -244,8 +244,6 @@ class ChromotingHostTest : public testing::Test { ...@@ -244,8 +244,6 @@ class ChromotingHostTest : public testing::Test {
desktop_environment_factory_.get(), desktop_environment_factory_.get(),
base::TimeDelta()); base::TimeDelta());
connection_ptr->set_host_stub(client); connection_ptr->set_host_stub(client);
connection_ptr->set_input_stub(
client->desktop_environment()->event_executor());
ui_task_runner_->PostTask( ui_task_runner_->PostTask(
FROM_HERE, base::Bind(&ChromotingHostTest::AddClientToHost, FROM_HERE, base::Bind(&ChromotingHostTest::AddClientToHost,
......
...@@ -41,13 +41,10 @@ ClientSession::ClientSession( ...@@ -41,13 +41,10 @@ ClientSession::ClientSession(
connection_factory_(connection_.get()), connection_factory_(connection_.get()),
desktop_environment_(desktop_environment_factory->Create()), desktop_environment_(desktop_environment_factory->Create()),
client_jid_(connection_->session()->jid()), client_jid_(connection_->session()->jid()),
host_clipboard_stub_(desktop_environment_->event_executor()), input_tracker_(&host_input_filter_),
host_input_stub_(desktop_environment_->event_executor()),
input_tracker_(host_input_stub_),
remote_input_filter_(&input_tracker_), remote_input_filter_(&input_tracker_),
mouse_clamping_filter_(desktop_environment_->video_capturer(), mouse_clamping_filter_(&remote_input_filter_, connection_->video_stub()),
&remote_input_filter_), disable_input_filter_(mouse_clamping_filter_.input_filter()),
disable_input_filter_(&mouse_clamping_filter_),
disable_clipboard_filter_(clipboard_echo_filter_.host_filter()), disable_clipboard_filter_(clipboard_echo_filter_.host_filter()),
auth_input_filter_(&disable_input_filter_), auth_input_filter_(&disable_input_filter_),
auth_clipboard_filter_(&disable_clipboard_filter_), auth_clipboard_filter_(&disable_clipboard_filter_),
...@@ -66,7 +63,6 @@ ClientSession::ClientSession( ...@@ -66,7 +63,6 @@ ClientSession::ClientSession(
connection_->set_clipboard_stub(&auth_clipboard_filter_); connection_->set_clipboard_stub(&auth_clipboard_filter_);
connection_->set_host_stub(this); connection_->set_host_stub(this);
connection_->set_input_stub(&auth_input_filter_); connection_->set_input_stub(&auth_input_filter_);
clipboard_echo_filter_.set_host_stub(host_clipboard_stub_);
// |auth_*_filter_|'s states reflect whether the session is authenticated. // |auth_*_filter_|'s states reflect whether the session is authenticated.
auth_input_filter_.set_enabled(false); auth_input_filter_.set_enabled(false);
...@@ -127,6 +123,11 @@ void ClientSession::OnConnectionChannelsConnected( ...@@ -127,6 +123,11 @@ void ClientSession::OnConnectionChannelsConnected(
protocol::ConnectionToClient* connection) { protocol::ConnectionToClient* connection) {
DCHECK(CalledOnValidThread()); DCHECK(CalledOnValidThread());
DCHECK_EQ(connection_.get(), connection); DCHECK_EQ(connection_.get(), connection);
// Connect the host clipboard and input stubs.
host_input_filter_.set_input_stub(desktop_environment_->event_executor());
clipboard_echo_filter_.set_host_stub(desktop_environment_->event_executor());
SetDisableInputs(false); SetDisableInputs(false);
// Let the desktop environment notify us of local clipboard changes. // Let the desktop environment notify us of local clipboard changes.
...@@ -148,7 +149,7 @@ void ClientSession::OnConnectionChannelsConnected( ...@@ -148,7 +149,7 @@ void ClientSession::OnConnectionChannelsConnected(
desktop_environment_->video_capturer(), desktop_environment_->video_capturer(),
video_encoder.Pass(), video_encoder.Pass(),
connection_->client_stub(), connection_->client_stub(),
connection_->video_stub()); &mouse_clamping_filter_);
++active_recorders_; ++active_recorders_;
// Create an AudioScheduler if audio is enabled, to pump audio samples. // Create an AudioScheduler if audio is enabled, to pump audio samples.
......
...@@ -133,10 +133,6 @@ class ClientSession ...@@ -133,10 +133,6 @@ class ClientSession
return connection_.get(); return connection_.get();
} }
DesktopEnvironment* desktop_environment() const {
return desktop_environment_.get();
}
const std::string& client_jid() { return client_jid_; } const std::string& client_jid() { return client_jid_; }
bool is_authenticated() { return auth_input_filter_.enabled(); } bool is_authenticated() { return auth_input_filter_.enabled(); }
...@@ -181,11 +177,8 @@ class ClientSession ...@@ -181,11 +177,8 @@ class ClientSession
std::string client_jid_; std::string client_jid_;
// The host clipboard and input stubs to which this object delegates. // Filter used as the final element in the input pipeline.
// These are the final elements in the clipboard & input pipelines, which protocol::InputFilter host_input_filter_;
// appear in order below.
protocol::ClipboardStub* host_clipboard_stub_;
protocol::InputStub* host_input_stub_;
// Tracker used to release pressed keys and buttons when disconnecting. // Tracker used to release pressed keys and buttons when disconnecting.
protocol::InputEventTracker input_tracker_; protocol::InputEventTracker input_tracker_;
...@@ -197,7 +190,8 @@ class ClientSession ...@@ -197,7 +190,8 @@ class ClientSession
MouseClampingFilter mouse_clamping_filter_; MouseClampingFilter mouse_clamping_filter_;
// Filter to used to stop clipboard items sent from the client being echoed // Filter to used to stop clipboard items sent from the client being echoed
// back to it. // back to it. It is the final element in the clipboard (client -> host)
// pipeline.
protocol::ClipboardEchoFilter clipboard_echo_filter_; protocol::ClipboardEchoFilter clipboard_echo_filter_;
// Filters used to manage enabling & disabling of input & clipboard. // Filters used to manage enabling & disabling of input & clipboard.
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "remoting/base/auto_thread_task_runner.h" #include "remoting/base/auto_thread_task_runner.h"
#include "remoting/base/constants.h" #include "remoting/base/constants.h"
#include "remoting/capturer/video_capturer_mock_objects.h" #include "remoting/capturer/video_capturer_mock_objects.h"
#include "remoting/capturer/video_frame_capturer_fake.h"
#include "remoting/host/audio_capturer.h" #include "remoting/host/audio_capturer.h"
#include "remoting/host/client_session.h" #include "remoting/host/client_session.h"
#include "remoting/host/desktop_environment.h" #include "remoting/host/desktop_environment.h"
...@@ -26,111 +27,68 @@ using protocol::SessionConfig; ...@@ -26,111 +27,68 @@ using protocol::SessionConfig;
using testing::_; using testing::_;
using testing::AnyNumber; using testing::AnyNumber;
using testing::DeleteArg; using testing::DeleteArg;
using testing::DoAll;
using testing::Expectation; using testing::Expectation;
using testing::InSequence; using testing::InSequence;
using testing::Return; using testing::Return;
using testing::ReturnRef; using testing::ReturnRef;
namespace {
ACTION_P2(InjectClipboardEvent, connection, event) {
connection->clipboard_stub()->InjectClipboardEvent(event);
}
ACTION_P2(InjectKeyEvent, connection, event) {
connection->input_stub()->InjectKeyEvent(event);
}
ACTION_P2(InjectMouseEvent, connection, event) {
connection->input_stub()->InjectMouseEvent(event);
}
ACTION_P2(LocalMouseMoved, client_session, event) {
client_session->LocalMouseMoved(SkIPoint::Make(event.x(), event.y()));
}
} // namespace
class ClientSessionTest : public testing::Test { class ClientSessionTest : public testing::Test {
public: public:
ClientSessionTest() : event_executor_(NULL) {} ClientSessionTest()
: client_jid_("user@domain/rest-of-jid"),
virtual void SetUp() OVERRIDE { event_executor_(NULL) {}
ui_task_runner_ = new AutoThreadTaskRunner(
message_loop_.message_loop_proxy(),
base::Bind(&ClientSessionTest::QuitMainMessageLoop,
base::Unretained(this)));
client_jid_ = "user@domain/rest-of-jid";
desktop_environment_factory_.reset(new MockDesktopEnvironmentFactory());
EXPECT_CALL(*desktop_environment_factory_, CreatePtr())
.Times(AnyNumber())
.WillRepeatedly(Invoke(this,
&ClientSessionTest::CreateDesktopEnvironment));
// Set up a large default screen size that won't affect most tests.
screen_size_.set(1000, 1000);
session_config_ = SessionConfig::ForTest();
// Mock protocol::Session APIs called directly by ClientSession.
protocol::MockSession* session = new MockSession();
EXPECT_CALL(*session, config()).WillRepeatedly(ReturnRef(session_config_));
EXPECT_CALL(*session, jid()).WillRepeatedly(ReturnRef(client_jid_));
EXPECT_CALL(*session, SetEventHandler(_));
// Mock protocol::ConnectionToClient APIs called directly by ClientSession.
// HostStub is not touched by ClientSession, so we can safely pass NULL.
scoped_ptr<MockConnectionToClient> connection(
new MockConnectionToClient(session, NULL));
EXPECT_CALL(*connection, session()).WillRepeatedly(Return(session));
EXPECT_CALL(*connection, client_stub())
.WillRepeatedly(Return(&client_stub_));
EXPECT_CALL(*connection, video_stub()).WillRepeatedly(Return(&video_stub_));
EXPECT_CALL(*connection, Disconnect());
connection_ = connection.get();
client_session_ = new ClientSession(
&session_event_handler_,
ui_task_runner_, // Audio thread.
ui_task_runner_, // Capture thread.
ui_task_runner_, // Encode thread.
ui_task_runner_, // Network thread.
connection.PassAs<protocol::ConnectionToClient>(),
desktop_environment_factory_.get(),
base::TimeDelta());
}
virtual void TearDown() OVERRIDE { virtual void SetUp() OVERRIDE;
// MockClientSessionEventHandler won't trigger Stop, so fake it. virtual void TearDown() OVERRIDE;
client_session_->Stop(base::Bind(
&ClientSessionTest::OnClientStopped, base::Unretained(this)));
// Run message loop before destroying because the session is destroyed // Disconnects the client session.
// asynchronously. void DisconnectClientSession();
ui_task_runner_ = NULL;
message_loop_.Run();
// Verify that the client session has been stopped. // Asynchronously stops the client session. OnClientStopped() will be called
EXPECT_TRUE(client_session_.get() == NULL); // once the client session is fully stopped.
} void StopClientSession();
protected: protected:
DesktopEnvironment* CreateDesktopEnvironment() { // Creates a DesktopEnvironment with a fake VideoFrameCapturer, to mock
MockVideoFrameCapturer* capturer = new MockVideoFrameCapturer(); // DesktopEnvironmentFactory::Create().
EXPECT_CALL(*capturer, Start(_)); DesktopEnvironment* CreateDesktopEnvironment();
EXPECT_CALL(*capturer, Stop());
EXPECT_CALL(*capturer, InvalidateRegion(_)).Times(AnyNumber());
EXPECT_CALL(*capturer, CaptureFrame()).Times(AnyNumber());
EXPECT_CALL(*capturer, size_most_recent())
.WillRepeatedly(ReturnRef(screen_size_));
EXPECT_TRUE(!event_executor_);
event_executor_ = new MockEventExecutor();
return new DesktopEnvironment(scoped_ptr<AudioCapturer>(NULL),
scoped_ptr<EventExecutor>(event_executor_),
scoped_ptr<VideoFrameCapturer>(capturer));
}
void DisconnectClientSession() { // Notifies the client session that the client connection has been
client_session_->Disconnect(); // authenticated and channels have been connected. This effectively enables
// MockSession won't trigger OnConnectionClosed, so fake it. // the input pipe line and starts video capturing.
client_session_->OnConnectionClosed(client_session_->connection(), void ConnectClientSession();
protocol::OK);
}
void QuitMainMessageLoop() { // Invoked when the last reference to the AutoThreadTaskRunner has been
message_loop_.PostTask(FROM_HERE, MessageLoop::QuitClosure()); // released and quits the message loop to finish the test.
} void QuitMainMessageLoop();
void OnClientStopped() { // Releases the ClientSession when it has been fully stopped, allowing
client_session_ = NULL; // the MessageLoop to quit.
} void OnClientStopped();
// Message loop passed to |client_session_| to perform all functions on. // Message loop passed to |client_session_| to perform all functions on.
MessageLoop message_loop_; MessageLoop message_loop_;
scoped_refptr<AutoThreadTaskRunner> ui_task_runner_;
// ClientSession instance under test. // ClientSession instance under test.
scoped_refptr<ClientSession> client_session_; scoped_refptr<ClientSession> client_session_;
...@@ -138,12 +96,9 @@ class ClientSessionTest : public testing::Test { ...@@ -138,12 +96,9 @@ class ClientSessionTest : public testing::Test {
// ClientSession::EventHandler mock for use in tests. // ClientSession::EventHandler mock for use in tests.
MockClientSessionEventHandler session_event_handler_; MockClientSessionEventHandler session_event_handler_;
// Screen size that the fake VideoFrameCapturer should report.
SkISize screen_size_;
// Storage for values to be returned by the protocol::Session mock. // Storage for values to be returned by the protocol::Session mock.
SessionConfig session_config_; SessionConfig session_config_;
std::string client_jid_; const std::string client_jid_;
// Stubs returned to |client_session_| components by |connection_|. // Stubs returned to |client_session_| components by |connection_|.
MockClientStub client_stub_; MockClientStub client_stub_;
...@@ -159,6 +114,90 @@ class ClientSessionTest : public testing::Test { ...@@ -159,6 +114,90 @@ class ClientSessionTest : public testing::Test {
scoped_ptr<MockDesktopEnvironmentFactory> desktop_environment_factory_; scoped_ptr<MockDesktopEnvironmentFactory> desktop_environment_factory_;
}; };
void ClientSessionTest::SetUp() {
// Arrange to run |message_loop_| until no components depend on it.
scoped_refptr<AutoThreadTaskRunner> ui_task_runner = new AutoThreadTaskRunner(
message_loop_.message_loop_proxy(),
base::Bind(&ClientSessionTest::QuitMainMessageLoop,
base::Unretained(this)));
desktop_environment_factory_.reset(new MockDesktopEnvironmentFactory());
EXPECT_CALL(*desktop_environment_factory_, CreatePtr())
.Times(AnyNumber())
.WillRepeatedly(Invoke(this,
&ClientSessionTest::CreateDesktopEnvironment));
session_config_ = SessionConfig::ForTest();
// Mock protocol::Session APIs called directly by ClientSession.
protocol::MockSession* session = new MockSession();
EXPECT_CALL(*session, config()).WillRepeatedly(ReturnRef(session_config_));
EXPECT_CALL(*session, jid()).WillRepeatedly(ReturnRef(client_jid_));
EXPECT_CALL(*session, SetEventHandler(_));
// Mock protocol::ConnectionToClient APIs called directly by ClientSession.
// HostStub is not touched by ClientSession, so we can safely pass NULL.
scoped_ptr<MockConnectionToClient> connection(
new MockConnectionToClient(session, NULL));
EXPECT_CALL(*connection, session()).WillRepeatedly(Return(session));
EXPECT_CALL(*connection, client_stub())
.WillRepeatedly(Return(&client_stub_));
EXPECT_CALL(*connection, video_stub()).WillRepeatedly(Return(&video_stub_));
EXPECT_CALL(*connection, Disconnect());
connection_ = connection.get();
client_session_ = new ClientSession(
&session_event_handler_,
ui_task_runner, // Audio thread.
ui_task_runner, // Capture thread.
ui_task_runner, // Encode thread.
ui_task_runner, // Network thread.
connection.PassAs<protocol::ConnectionToClient>(),
desktop_environment_factory_.get(),
base::TimeDelta());
}
void ClientSessionTest::TearDown() {
// Verify that the client session has been stopped.
EXPECT_TRUE(client_session_.get() == NULL);
}
void ClientSessionTest::DisconnectClientSession() {
client_session_->Disconnect();
// MockSession won't trigger OnConnectionClosed, so fake it.
client_session_->OnConnectionClosed(client_session_->connection(),
protocol::OK);
}
void ClientSessionTest::StopClientSession() {
// MockClientSessionEventHandler won't trigger Stop, so fake it.
client_session_->Stop(base::Bind(
&ClientSessionTest::OnClientStopped, base::Unretained(this)));
}
DesktopEnvironment* ClientSessionTest::CreateDesktopEnvironment() {
scoped_ptr<VideoFrameCapturer> video_capturer(new VideoFrameCapturerFake());
EXPECT_TRUE(!event_executor_);
event_executor_ = new MockEventExecutor();
return new DesktopEnvironment(scoped_ptr<AudioCapturer>(NULL),
scoped_ptr<EventExecutor>(event_executor_),
video_capturer.Pass());
}
void ClientSessionTest::ConnectClientSession() {
client_session_->OnConnectionAuthenticated(client_session_->connection());
client_session_->OnConnectionChannelsConnected(client_session_->connection());
}
void ClientSessionTest::QuitMainMessageLoop() {
message_loop_.PostTask(FROM_HERE, MessageLoop::QuitClosure());
}
void ClientSessionTest::OnClientStopped() {
client_session_ = NULL;
}
MATCHER_P2(EqualsClipboardEvent, m, d, "") { MATCHER_P2(EqualsClipboardEvent, m, d, "") {
return (strcmp(arg.mime_type().c_str(), m) == 0 && return (strcmp(arg.mime_type().c_str(), m) == 0 &&
memcmp(arg.data().data(), d, arg.data().size()) == 0); memcmp(arg.data().data(), d, arg.data().size()) == 0);
...@@ -181,6 +220,19 @@ TEST_F(ClientSessionTest, ClipboardStubFilter) { ...@@ -181,6 +220,19 @@ TEST_F(ClientSessionTest, ClipboardStubFilter) {
EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)); EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_));
EXPECT_CALL(*event_executor_, StartPtr(_)); EXPECT_CALL(*event_executor_, StartPtr(_));
EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_)); EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_));
// Wait for the first video packet to be captured to make sure that
// the injected input will go though. Otherwise mouse events will be blocked
// by the mouse clamping filter.
EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
.WillOnce(DoAll(
// This event should get through to the clipboard stub.
InjectClipboardEvent(connection_, clipboard_event2),
InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
// This event should not get through to the clipboard stub,
// because the client has disconnected.
InjectClipboardEvent(connection_, clipboard_event3),
InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
EXPECT_CALL(*event_executor_, InjectClipboardEvent(EqualsClipboardEvent( EXPECT_CALL(*event_executor_, InjectClipboardEvent(EqualsClipboardEvent(
kMimeTypeTextUtf8, "b"))); kMimeTypeTextUtf8, "b")));
EXPECT_CALL(session_event_handler_, OnSessionClosed(_)); EXPECT_CALL(session_event_handler_, OnSessionClosed(_));
...@@ -188,14 +240,9 @@ TEST_F(ClientSessionTest, ClipboardStubFilter) { ...@@ -188,14 +240,9 @@ TEST_F(ClientSessionTest, ClipboardStubFilter) {
// This event should not get through to the clipboard stub, // This event should not get through to the clipboard stub,
// because the client isn't authenticated yet. // because the client isn't authenticated yet.
connection_->clipboard_stub()->InjectClipboardEvent(clipboard_event1); connection_->clipboard_stub()->InjectClipboardEvent(clipboard_event1);
client_session_->OnConnectionAuthenticated(client_session_->connection());
client_session_->OnConnectionChannelsConnected(client_session_->connection()); ConnectClientSession();
// This event should get through to the clipboard stub. message_loop_.Run();
connection_->clipboard_stub()->InjectClipboardEvent(clipboard_event2);
DisconnectClientSession();
// This event should not get through to the clipboard stub,
// because the client has disconnected.
connection_->clipboard_stub()->InjectClipboardEvent(clipboard_event3);
} }
MATCHER_P2(EqualsUsbEvent, usb_keycode, pressed, "") { MATCHER_P2(EqualsUsbEvent, usb_keycode, pressed, "") {
...@@ -244,6 +291,22 @@ TEST_F(ClientSessionTest, InputStubFilter) { ...@@ -244,6 +291,22 @@ TEST_F(ClientSessionTest, InputStubFilter) {
EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)); EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_));
EXPECT_CALL(*event_executor_, StartPtr(_)); EXPECT_CALL(*event_executor_, StartPtr(_));
EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_)); EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_));
// Wait for the first video packet to be captured to make sure that
// the injected input will go though. Otherwise mouse events will be blocked
// by the mouse clamping filter.
EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
.WillOnce(DoAll(
// These events should get through to the input stub.
InjectKeyEvent(connection_, key_event2_down),
InjectKeyEvent(connection_, key_event2_up),
InjectMouseEvent(connection_, mouse_event2),
InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
// These events should not get through to the input stub,
// because the client has disconnected.
InjectKeyEvent(connection_, key_event3),
InjectMouseEvent(connection_, mouse_event3),
InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
EXPECT_CALL(*event_executor_, InjectKeyEvent(EqualsUsbEvent(2, true))); EXPECT_CALL(*event_executor_, InjectKeyEvent(EqualsUsbEvent(2, true)));
EXPECT_CALL(*event_executor_, InjectKeyEvent(EqualsUsbEvent(2, false))); EXPECT_CALL(*event_executor_, InjectKeyEvent(EqualsUsbEvent(2, false)));
EXPECT_CALL(*event_executor_, InjectMouseEvent(EqualsMouseEvent(200, 201))); EXPECT_CALL(*event_executor_, InjectMouseEvent(EqualsMouseEvent(200, 201)));
...@@ -253,17 +316,9 @@ TEST_F(ClientSessionTest, InputStubFilter) { ...@@ -253,17 +316,9 @@ TEST_F(ClientSessionTest, InputStubFilter) {
// because the client isn't authenticated yet. // because the client isn't authenticated yet.
connection_->input_stub()->InjectKeyEvent(key_event1); connection_->input_stub()->InjectKeyEvent(key_event1);
connection_->input_stub()->InjectMouseEvent(mouse_event1); connection_->input_stub()->InjectMouseEvent(mouse_event1);
client_session_->OnConnectionAuthenticated(client_session_->connection());
client_session_->OnConnectionChannelsConnected(client_session_->connection()); ConnectClientSession();
// These events should get through to the input stub. message_loop_.Run();
connection_->input_stub()->InjectKeyEvent(key_event2_down);
connection_->input_stub()->InjectKeyEvent(key_event2_up);
connection_->input_stub()->InjectMouseEvent(mouse_event2);
DisconnectClientSession();
// These events should not get through to the input stub,
// because the client has disconnected.
connection_->input_stub()->InjectKeyEvent(key_event3);
connection_->input_stub()->InjectMouseEvent(mouse_event3);
} }
TEST_F(ClientSessionTest, LocalInputTest) { TEST_F(ClientSessionTest, LocalInputTest) {
...@@ -281,25 +336,30 @@ TEST_F(ClientSessionTest, LocalInputTest) { ...@@ -281,25 +336,30 @@ TEST_F(ClientSessionTest, LocalInputTest) {
EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)); EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_));
EXPECT_CALL(*event_executor_, StartPtr(_)); EXPECT_CALL(*event_executor_, StartPtr(_));
EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_)); EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_));
// Wait for the first video packet to be captured to make sure that
// the injected input will go though. Otherwise mouse events will be blocked
// by the mouse clamping filter.
EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
.WillOnce(DoAll(
// This event should get through to the input stub.
InjectMouseEvent(connection_, mouse_event1),
// This one should too because the local event echoes the remote one.
LocalMouseMoved(client_session_.get(), mouse_event1),
InjectMouseEvent(connection_, mouse_event2),
// This one should not.
LocalMouseMoved(client_session_.get(), mouse_event1),
InjectMouseEvent(connection_, mouse_event3),
// TODO(jamiewalch): Verify that remote inputs are re-enabled
// eventually (via dependency injection, not sleep!)
InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
EXPECT_CALL(*event_executor_, InjectMouseEvent(EqualsMouseEvent(100, 101))); EXPECT_CALL(*event_executor_, InjectMouseEvent(EqualsMouseEvent(100, 101)));
EXPECT_CALL(*event_executor_, InjectMouseEvent(EqualsMouseEvent(200, 201))); EXPECT_CALL(*event_executor_, InjectMouseEvent(EqualsMouseEvent(200, 201)));
EXPECT_CALL(session_event_handler_, OnSessionClosed(_)); EXPECT_CALL(session_event_handler_, OnSessionClosed(_));
client_session_->OnConnectionAuthenticated(client_session_->connection()); ConnectClientSession();
client_session_->OnConnectionChannelsConnected(client_session_->connection()); message_loop_.Run();
// This event should get through to the input stub.
connection_->input_stub()->InjectMouseEvent(mouse_event1);
// This one should too because the local event echoes the remote one.
client_session_->LocalMouseMoved(SkIPoint::Make(mouse_event1.x(),
mouse_event1.y()));
connection_->input_stub()->InjectMouseEvent(mouse_event2);
// This one should not.
client_session_->LocalMouseMoved(SkIPoint::Make(mouse_event1.x(),
mouse_event1.y()));
connection_->input_stub()->InjectMouseEvent(mouse_event3);
// TODO(jamiewalch): Verify that remote inputs are re-enabled eventually
// (via dependency injection, not sleep!)
DisconnectClientSession();
} }
TEST_F(ClientSessionTest, RestoreEventState) { TEST_F(ClientSessionTest, RestoreEventState) {
...@@ -319,6 +379,17 @@ TEST_F(ClientSessionTest, RestoreEventState) { ...@@ -319,6 +379,17 @@ TEST_F(ClientSessionTest, RestoreEventState) {
EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)); EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_));
EXPECT_CALL(*event_executor_, StartPtr(_)); EXPECT_CALL(*event_executor_, StartPtr(_));
EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_)); EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_));
// Wait for the first video packet to be captured to make sure that
// the injected input will go though. Otherwise mouse events will be blocked
// by the mouse clamping filter.
EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
.WillOnce(DoAll(
InjectKeyEvent(connection_, key1),
InjectKeyEvent(connection_, key2),
InjectMouseEvent(connection_, mousedown),
InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
EXPECT_CALL(*event_executor_, InjectKeyEvent(EqualsUsbEvent(1, true))); EXPECT_CALL(*event_executor_, InjectKeyEvent(EqualsUsbEvent(1, true)));
EXPECT_CALL(*event_executor_, InjectKeyEvent(EqualsUsbEvent(2, true))); EXPECT_CALL(*event_executor_, InjectKeyEvent(EqualsUsbEvent(2, true)));
EXPECT_CALL(*event_executor_, InjectMouseEvent(EqualsMouseButtonEvent( EXPECT_CALL(*event_executor_, InjectMouseEvent(EqualsMouseButtonEvent(
...@@ -329,48 +400,62 @@ TEST_F(ClientSessionTest, RestoreEventState) { ...@@ -329,48 +400,62 @@ TEST_F(ClientSessionTest, RestoreEventState) {
protocol::MouseEvent::BUTTON_LEFT, false))); protocol::MouseEvent::BUTTON_LEFT, false)));
EXPECT_CALL(session_event_handler_, OnSessionClosed(_)); EXPECT_CALL(session_event_handler_, OnSessionClosed(_));
client_session_->OnConnectionAuthenticated(client_session_->connection()); ConnectClientSession();
client_session_->OnConnectionChannelsConnected(client_session_->connection()); message_loop_.Run();
connection_->input_stub()->InjectKeyEvent(key1);
connection_->input_stub()->InjectKeyEvent(key2);
connection_->input_stub()->InjectMouseEvent(mousedown);
DisconnectClientSession();
} }
TEST_F(ClientSessionTest, ClampMouseEvents) { TEST_F(ClientSessionTest, ClampMouseEvents) {
screen_size_.set(200, 100);
EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_)); EXPECT_CALL(session_event_handler_, OnSessionAuthenticated(_));
EXPECT_CALL(*event_executor_, StartPtr(_)); EXPECT_CALL(*event_executor_, StartPtr(_));
Expectation connected = Expectation connected =
EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_)); EXPECT_CALL(session_event_handler_, OnSessionChannelsConnected(_));
EXPECT_CALL(session_event_handler_, OnSessionClosed(_)); EXPECT_CALL(session_event_handler_, OnSessionClosed(_));
client_session_->OnConnectionAuthenticated(client_session_->connection());
client_session_->OnConnectionChannelsConnected(client_session_->connection());
int input_x[3] = { -999, 100, 999 }; int input_x[3] = { -999, 100, 999 };
int expected_x[3] = { 0, 100, 199 }; int expected_x[3] = { 0, 100, VideoFrameCapturerFake::kWidth - 1 };
int input_y[3] = { -999, 50, 999 }; int input_y[3] = { -999, 50, 999 };
int expected_y[3] = { 0, 50, 99 }; int expected_y[3] = { 0, 50, VideoFrameCapturerFake::kHeight - 1 };
protocol::MouseEvent event; // Inject the 1st event once a video packet has been received.
protocol::MouseEvent injected_event;
injected_event.set_x(input_x[0]);
injected_event.set_y(input_y[0]);
connected =
EXPECT_CALL(video_stub_, ProcessVideoPacketPtr(_, _))
.After(connected)
.WillOnce(InjectMouseEvent(connection_, injected_event));
protocol::MouseEvent expected_event;
for (int j = 0; j < 3; j++) { for (int j = 0; j < 3; j++) {
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
event.set_x(input_x[i]); // Skip the first iteration since the 1st event has been injected already.
event.set_y(input_y[j]); if (i > 0 || j > 0) {
connected = injected_event.set_x(input_x[i]);
EXPECT_CALL(*event_executor_, injected_event.set_y(input_y[j]);
InjectMouseEvent(EqualsMouseEvent(expected_x[i], connected =
expected_y[j]))) EXPECT_CALL(*event_executor_,
.After(connected); InjectMouseEvent(EqualsMouseEvent(expected_event.x(),
connection_->input_stub()->InjectMouseEvent(event); expected_event.y())))
.After(connected)
.WillOnce(InjectMouseEvent(connection_, injected_event));
}
expected_event.set_x(expected_x[i]);
expected_event.set_y(expected_y[j]);
} }
} }
DisconnectClientSession(); // Shutdown the connection once the last event has been received.
EXPECT_CALL(*event_executor_,
InjectMouseEvent(EqualsMouseEvent(expected_event.x(),
expected_event.y())))
.After(connected)
.WillOnce(DoAll(
InvokeWithoutArgs(this, &ClientSessionTest::DisconnectClientSession),
InvokeWithoutArgs(this, &ClientSessionTest::StopClientSession)));
ConnectClientSession();
message_loop_.Run();
} }
} // namespace remoting } // namespace remoting
...@@ -4,24 +4,34 @@ ...@@ -4,24 +4,34 @@
#include "remoting/host/mouse_clamping_filter.h" #include "remoting/host/mouse_clamping_filter.h"
#include "remoting/capturer/video_frame_capturer.h"
#include "remoting/proto/event.pb.h" #include "remoting/proto/event.pb.h"
#include "remoting/proto/video.pb.h"
namespace remoting { namespace remoting {
MouseClampingFilter::MouseClampingFilter(VideoFrameCapturer* capturer, MouseClampingFilter::MouseClampingFilter(
protocol::InputStub* input_stub) protocol::InputStub* input_stub,
: MouseInputFilter(input_stub), capturer_(capturer) { protocol::VideoStub* video_stub)
: input_filter_(input_stub),
video_stub_(video_stub) {
} }
MouseClampingFilter::~MouseClampingFilter() { MouseClampingFilter::~MouseClampingFilter() {
} }
void MouseClampingFilter::InjectMouseEvent(const protocol::MouseEvent& event) { void MouseClampingFilter::ProcessVideoPacket(
// Ensure that the MouseInputFilter is clamping to the current dimensions. scoped_ptr<VideoPacket> video_packet,
set_output_size(capturer_->size_most_recent()); const base::Closure& done) {
set_input_size(capturer_->size_most_recent()); // Configure the MouseInputFilter to clamp to the video dimensions.
MouseInputFilter::InjectMouseEvent(event); if (video_packet->format().has_screen_width() &&
video_packet->format().has_screen_height()) {
SkISize screen_size = SkISize::Make(video_packet->format().screen_width(),
video_packet->format().screen_height());
input_filter_.set_input_size(screen_size);
input_filter_.set_output_size(screen_size);
}
video_stub_->ProcessVideoPacket(video_packet.Pass(), done);
} }
} // namespace remoting } // namespace remoting
...@@ -7,25 +7,30 @@ ...@@ -7,25 +7,30 @@
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "remoting/protocol/mouse_input_filter.h" #include "remoting/protocol/mouse_input_filter.h"
#include "remoting/protocol/video_stub.h"
namespace remoting { namespace remoting {
class VideoFrameCapturer; // Filtering VideoStub implementation which configures a MouseInputFilter to
// clamp mouse events to fall within the dimensions of the most-recently
// Filtering InputStub implementation which clamps mouse each mouse event to // received video frame.
// the current dimensions of a VideoFrameCapturer instance before passing class MouseClampingFilter : public protocol::VideoStub {
// them on to the target |input_stub|.
class MouseClampingFilter : public protocol::MouseInputFilter {
public: public:
MouseClampingFilter(VideoFrameCapturer* capturer, MouseClampingFilter(protocol::InputStub* input_stub,
protocol::InputStub* input_stub); protocol::VideoStub* video_stub);
virtual ~MouseClampingFilter(); virtual ~MouseClampingFilter();
// InputStub overrides. protocol::InputStub* input_filter() { return &input_filter_; }
virtual void InjectMouseEvent(const protocol::MouseEvent& event) OVERRIDE;
// protocol::VideoStub implementation.
virtual void ProcessVideoPacket(scoped_ptr<VideoPacket> video_packet,
const base::Closure& done) OVERRIDE;
private: private:
VideoFrameCapturer* capturer_; // Clamps mouse event coordinates to the video dimensions.
protocol::MouseInputFilter input_filter_;
protocol::VideoStub* video_stub_;
DISALLOW_COPY_AND_ASSIGN(MouseClampingFilter); DISALLOW_COPY_AND_ASSIGN(MouseClampingFilter);
}; };
......
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