diff options
author | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-16 19:53:35 +0000 |
---|---|---|
committer | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-11-16 19:53:35 +0000 |
commit | 6fd3d6a1648a754d8023924074612d55c187b4cf (patch) | |
tree | 102ac605e52b8cf1a4e423b5403a0302a5ee9f76 | |
parent | 3e4155c723ab73c8f754a82d81f0eb247c83536f (diff) | |
download | chromium_src-6fd3d6a1648a754d8023924074612d55c187b4cf.zip chromium_src-6fd3d6a1648a754d8023924074612d55c187b4cf.tar.gz chromium_src-6fd3d6a1648a754d8023924074612d55c187b4cf.tar.bz2 |
Implement input stub in the host side for chromoting
Implement InputStub for the host.
BUG=None
TEST=None
Review URL: http://codereview.chromium.org/4726003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@66314 0039d316-1c4b-4281-b951-d872f2087c98
25 files changed, 300 insertions, 251 deletions
diff --git a/chrome/service/service_process.cc b/chrome/service/service_process.cc index 6660c29..f04e082 100644 --- a/chrome/service/service_process.cc +++ b/chrome/service/service_process.cc @@ -286,24 +286,27 @@ bool ServiceProcess::StartChromotingHost() { // Create capturer and executor. The ownership will be transfered // to the chromoting host. scoped_ptr<remoting::Capturer> capturer; - scoped_ptr<remoting::EventExecutor> executor; + scoped_ptr<remoting::protocol::InputStub> input_stub; #if defined(OS_WIN) capturer.reset(new remoting::CapturerGdi()); - executor.reset(new remoting::EventExecutorWin(capturer.get())); + input_stub.reset(new remoting::EventExecutorWin( + chromoting_context_->capture_message_loop(), capturer.get())); #elif defined(OS_LINUX) capturer.reset(new remoting::CapturerLinux()); - executor.reset(new remoting::EventExecutorLinux(capturer.get())); + input_stub.reset(new remoting::EventExecutorLinux( + chromoting_context_->capture_message_loop(), capturer.get())); #elif defined(OS_MACOSX) capturer.reset(new remoting::CapturerMac()); - executor.reset(new remoting::EventExecutorMac(capturer.get())); + input_stub.reset(new remoting::EventExecutorMac( + chromoting_context_->capture_message_loop(), capturer.get())); #endif // Create a chromoting host object. chromoting_host_ = new remoting::ChromotingHost(chromoting_context_.get(), chromoting_config_, capturer.release(), - executor.release()); + input_stub.release()); // Then start the chromoting host. // When ChromotingHost is shutdown because of failure or a request that diff --git a/remoting/host/chromoting_host.cc b/remoting/host/chromoting_host.cc index 8a62459..9fad9cbf 100644 --- a/remoting/host/chromoting_host.cc +++ b/remoting/host/chromoting_host.cc @@ -14,7 +14,6 @@ #include "remoting/base/encoder_zlib.h" #include "remoting/host/chromoting_host_context.h" #include "remoting/host/capturer.h" -#include "remoting/host/event_executor.h" #include "remoting/host/host_config.h" #include "remoting/host/session_manager.h" #include "remoting/protocol/session_config.h" @@ -28,11 +27,11 @@ namespace remoting { ChromotingHost::ChromotingHost(ChromotingHostContext* context, MutableHostConfig* config, Capturer* capturer, - EventExecutor* executor) + protocol::InputStub* input_stub) : context_(context), config_(config), capturer_(capturer), - executor_(executor), + input_stub_(input_stub), state_(kInitial) { } @@ -180,16 +179,6 @@ void ChromotingHost::OnClientDisconnected(ConnectionToClient* connection) { //////////////////////////////////////////////////////////////////////////// // protocol::ConnectionToClient::EventHandler implementations -void ChromotingHost::HandleMessage(ConnectionToClient* connection, - ChromotingClientMessage* message) { - DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); - - // Delegate the messages to EventExecutor and delete the unhandled - // messages. - DCHECK(executor_.get()); - executor_->HandleInputEvent(message); -} - void ChromotingHost::OnConnectionOpened(ConnectionToClient* connection) { DCHECK_EQ(context_->main_message_loop(), MessageLoop::current()); @@ -283,7 +272,8 @@ void ChromotingHost::OnNewClientSession( // If we accept the connected then create a client object and set the // callback. - connection_ = new ConnectionToClient(context_->main_message_loop(), this); + connection_ = new ConnectionToClient(context_->main_message_loop(), + this, NULL, input_stub_.get()); connection_->Init(session); } diff --git a/remoting/host/chromoting_host.h b/remoting/host/chromoting_host.h index 6616c24..ab285ab 100644 --- a/remoting/host/chromoting_host.h +++ b/remoting/host/chromoting_host.h @@ -11,10 +11,10 @@ #include "remoting/base/encoder.h" #include "remoting/host/access_verifier.h" #include "remoting/host/capturer.h" -#include "remoting/host/event_executor.h" #include "remoting/host/heartbeat_sender.h" #include "remoting/jingle_glue/jingle_client.h" #include "remoting/jingle_glue/jingle_thread.h" +#include "remoting/protocol/input_stub.h" #include "remoting/protocol/session_manager.h" #include "remoting/protocol/connection_to_client.h" @@ -30,7 +30,6 @@ class SessionConfig; class Capturer; class ChromotingHostContext; class Encoder; -class EventExecutor; class MutableHostConfig; class SessionManager; @@ -46,7 +45,7 @@ class SessionManager; // a ConnectionToClient object that wraps around linjingle for transport. // Also create a SessionManager with appropriate Encoder and Capturer and // add the ConnectionToClient to this SessionManager for transporting the -// screen captures. A EventExecutor is created and registered with the +// screen captures. An InputStub is created and registered with the // ConnectionToClient to receive mouse / keyboard events from the remote // client. // This is also the right time to create multiple threads to host @@ -64,7 +63,7 @@ class ChromotingHost : public base::RefCountedThreadSafe<ChromotingHost>, public JingleClient::Callback { public: ChromotingHost(ChromotingHostContext* context, MutableHostConfig* config, - Capturer* capturer, EventExecutor* executor); + Capturer* capturer, protocol::InputStub* input_stub); virtual ~ChromotingHost(); // Asynchronously start the host process. @@ -89,8 +88,6 @@ class ChromotingHost : public base::RefCountedThreadSafe<ChromotingHost>, //////////////////////////////////////////////////////////////////////////// // protocol::ConnectionToClient::EventHandler implementations - virtual void HandleMessage(protocol::ConnectionToClient* client, - ChromotingClientMessage* message); virtual void OnConnectionOpened(protocol::ConnectionToClient* client); virtual void OnConnectionClosed(protocol::ConnectionToClient* client); virtual void OnConnectionFailed(protocol::ConnectionToClient* client); @@ -133,8 +130,8 @@ class ChromotingHost : public base::RefCountedThreadSafe<ChromotingHost>, // constructed this is set to NULL. scoped_ptr<Encoder> encoder_; - // EventExecutor executes input events received from the client. - scoped_ptr<EventExecutor> executor_; + // InputStub in the host executes input events received from the client. + scoped_ptr<protocol::InputStub> input_stub_; // The libjingle client. This is used to connect to the talk network to // receive connection requests from chromoting client. diff --git a/remoting/host/chromoting_host_context.h b/remoting/host/chromoting_host_context.h index 713afb8..f5b2783 100644 --- a/remoting/host/chromoting_host_context.h +++ b/remoting/host/chromoting_host_context.h @@ -28,6 +28,8 @@ class ChromotingHostContext { virtual void Stop(); virtual JingleThread* jingle_thread(); + + // TODO(hclam): Change these all to MessageLoopProxy. virtual MessageLoop* main_message_loop(); virtual MessageLoop* capture_message_loop(); virtual MessageLoop* encode_message_loop(); diff --git a/remoting/host/event_executor.h b/remoting/host/event_executor.h deleted file mode 100644 index 3f87ea7..0000000 --- a/remoting/host/event_executor.h +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef REMOTING_HOST_EVENT_EXECUTOR_H_ -#define REMOTING_HOST_EVENT_EXECUTOR_H_ - -#include <vector> - -#include "base/basictypes.h" - -namespace remoting { - -class Capturer; -class ChromotingClientMessage; - -// An interface that defines the behavior of an event executor object. -// An event executor is to perform actions on the host machine. For example -// moving the mouse cursor, generating keyboard events and manipulating -// clipboards. -class EventExecutor { - public: - explicit EventExecutor(Capturer* capturer) - : capturer_(capturer) { - } - virtual ~EventExecutor() {} - - // Handles input events from ClientMessageList and removes them from the - // list. - virtual void HandleInputEvent(ChromotingClientMessage* message) = 0; - // TODO(hclam): Define actions for clipboards. - - protected: - Capturer* capturer_; - - private: - DISALLOW_COPY_AND_ASSIGN(EventExecutor); -}; - -} // namespace remoting - -#endif // REMOTING_HOST_EVENT_EXECUTOR_H_ diff --git a/remoting/host/event_executor_linux.cc b/remoting/host/event_executor_linux.cc index f8212f1..1421277 100644 --- a/remoting/host/event_executor_linux.cc +++ b/remoting/host/event_executor_linux.cc @@ -9,6 +9,8 @@ #include <X11/extensions/XTest.h> #include "base/logging.h" +#include "base/message_loop.h" +#include "base/task.h" #include "remoting/proto/internal.pb.h" namespace remoting { @@ -200,8 +202,8 @@ class EventExecutorLinuxPimpl { ~EventExecutorLinuxPimpl(); bool Init(); // TODO(ajwong): Do we really want this to be synchronous? - - void HandleInputEvent(ChromotingClientMessage* message); + void HandleMouse(const MouseEvent* message); + void HandleKey(const KeyEvent* key_event); private: void HandleMouseSetPosition(const MouseSetPositionEvent& position_event); @@ -209,7 +211,6 @@ class EventExecutorLinuxPimpl { void HandleMouseWheel(const MouseWheelEvent& wheel_event); void HandleMouseButtonDown(const MouseDownEvent& mouse_down_event); void HandleMouseButtonUp(const MouseUpEvent& mouse_up_event); - void HandleKey(const KeyEvent& key_event); void DeinitXlib(); // Reference to containing class so we can access friend functions. @@ -227,19 +228,6 @@ class EventExecutorLinuxPimpl { int test_error_base_; }; -EventExecutorLinux::EventExecutorLinux(Capturer* capturer) - : EventExecutor(capturer), - pimpl_(new EventExecutorLinuxPimpl(this)) { - CHECK(pimpl_->Init()); -} - -EventExecutorLinux::~EventExecutorLinux() { -} - -void EventExecutorLinux::HandleInputEvent(ChromotingClientMessage* message) { - pimpl_->HandleInputEvent(message); -} - EventExecutorLinuxPimpl::EventExecutorLinuxPimpl(EventExecutorLinux* executor) : executor_(executor), display_(NULL), @@ -302,22 +290,17 @@ bool EventExecutorLinuxPimpl::Init() { return true; } -void EventExecutorLinuxPimpl::HandleInputEvent( - ChromotingClientMessage* message) { - if (message->has_mouse_set_position_event()) { - HandleMouseSetPosition(message->mouse_set_position_event()); - } else if (message->has_mouse_move_event()) { - HandleMouseMove(message->mouse_move_event()); - } else if (message->has_mouse_wheel_event()) { - HandleMouseWheel(message->mouse_wheel_event()); - } else if (message->has_mouse_down_event()) { - HandleMouseButtonDown(message->mouse_down_event()); - } else if (message->has_mouse_up_event()) { - HandleMouseButtonUp(message->mouse_up_event()); - } else if (message->has_key_event()) { - HandleKey(message->key_event()); +void EventExecutorLinuxPimpl::HandleMouse( + const MouseEvent* mouse_event) { + if (mouse_event->has_set_position()) { + HandleMouseSetPosition(mouse_event->set_position()); + } else if (mouse_event->has_wheel()) { + HandleMouseWheel(mouse_event->wheel()); + } else if (mouse_event->has_down()) { + HandleMouseButtonDown(mouse_event->down()); + } else if (mouse_event->has_up()) { + HandleMouseButtonUp(mouse_event->up()); } - delete message; } void EventExecutorLinuxPimpl::HandleMouseSetPosition( @@ -376,12 +359,12 @@ void EventExecutorLinuxPimpl::HandleMouseButtonUp( XTestFakeButtonEvent(display_, button_number, False, CurrentTime); } -void EventExecutorLinuxPimpl::HandleKey(const KeyEvent& key_event) { +void EventExecutorLinuxPimpl::HandleKey(const KeyEvent* key_event) { // TODO(ajwong): This will only work for QWERTY keyboards. - int keysym = ChromotocolKeycodeToX11Keysym(key_event.key()); + int keysym = ChromotocolKeycodeToX11Keysym(key_event->key()); if (keysym == -1) { - LOG(WARNING) << "Ignoring unknown key: " << key_event.key(); + LOG(WARNING) << "Ignoring unknown key: " << key_event->key(); return; } @@ -389,14 +372,14 @@ void EventExecutorLinuxPimpl::HandleKey(const KeyEvent& key_event) { int keycode = XKeysymToKeycode(display_, keysym); if (keycode == 0) { LOG(WARNING) << "Ignoring undefined keysym: " << keysym - << " for key: " << key_event.key(); + << " for key: " << key_event->key(); return; } - VLOG(3) << "Got pepper key: " << key_event.key() + VLOG(3) << "Got pepper key: " << key_event->key() << " sending keysym: " << keysym << " to keycode: " << keycode; - XTestFakeKeyEvent(display_, keycode, key_event.pressed(), CurrentTime); + XTestFakeKeyEvent(display_, keycode, key_event->pressed(), CurrentTime); } void EventExecutorLinuxPimpl::DeinitXlib() { @@ -416,4 +399,42 @@ void EventExecutorLinuxPimpl::DeinitXlib() { } } +EventExecutorLinux::EventExecutorLinux( + MessageLoop* message_loop, Capturer* capturer) + : message_loop_(message_loop), + capturer_(capturer), + pimpl_(new EventExecutorLinuxPimpl(this)) { + CHECK(pimpl_->Init()); +} + +EventExecutorLinux::~EventExecutorLinux() { +} + +void EventExecutorLinux::InjectKeyEvent(const KeyEvent* event, Task* done) { + if (MessageLoop::current() != message_loop_) { + message_loop_->PostTask( + FROM_HERE, + NewRunnableMethod(this, &EventExecutorLinux::InjectKeyEvent, + event, done)); + return; + } + pimpl_->HandleKey(event); + done->Run(); + delete done; +} + +void EventExecutorLinux::InjectMouseEvent(const MouseEvent* event, + Task* done) { + if (MessageLoop::current() != message_loop_) { + message_loop_->PostTask( + FROM_HERE, + NewRunnableMethod(this, &EventExecutorLinux::InjectMouseEvent, + event, done)); + return; + } + pimpl_->HandleMouse(event); + done->Run(); + delete done; +} + } // namespace remoting diff --git a/remoting/host/event_executor_linux.h b/remoting/host/event_executor_linux.h index cda6476..ef28660 100644 --- a/remoting/host/event_executor_linux.h +++ b/remoting/host/event_executor_linux.h @@ -5,22 +5,34 @@ #ifndef REMOTING_HOST_EVENT_EXECUTOR_LINUX_H_ #define REMOTING_HOST_EVENT_EXECUTOR_LINUX_H_ +#include <vector> + +#include "base/task.h" +#include "base/basictypes.h" #include "base/scoped_ptr.h" -#include "remoting/host/event_executor.h" +#include "remoting/protocol/input_stub.h" + +class MessageLoop; namespace remoting { +class Capturer; +class ChromotingClientMessage; class EventExecutorLinuxPimpl; // A class to generate events on Linux. -class EventExecutorLinux : public EventExecutor { +class EventExecutorLinux : public protocol::InputStub { public: - EventExecutorLinux(Capturer* capturer); + EventExecutorLinux(MessageLoop* message_loop, + Capturer* capturer); virtual ~EventExecutorLinux(); - virtual void HandleInputEvent(ChromotingClientMessage* message); + virtual void InjectKeyEvent(const KeyEvent* event, Task* done); + virtual void InjectMouseEvent(const MouseEvent* event, Task* done); private: + MessageLoop* message_loop_; + Capturer* capturer_; scoped_ptr<EventExecutorLinuxPimpl> pimpl_; DISALLOW_COPY_AND_ASSIGN(EventExecutorLinux); @@ -28,4 +40,6 @@ class EventExecutorLinux : public EventExecutor { } // namespace remoting +DISABLE_RUNNABLE_METHOD_REFCOUNT(remoting::EventExecutorLinux); + #endif // REMOTING_HOST_EVENT_EXECUTOR_LINUX_H_ diff --git a/remoting/host/event_executor_mac.cc b/remoting/host/event_executor_mac.cc index 7e64324..553222a 100644 --- a/remoting/host/event_executor_mac.cc +++ b/remoting/host/event_executor_mac.cc @@ -4,20 +4,29 @@ #include "remoting/host/event_executor_mac.h" -#include "remoting/proto/internal.pb.h" +#include "base/message_loop.h" +#include "base/task.h" #include "remoting/protocol/message_decoder.h" namespace remoting { -EventExecutorMac::EventExecutorMac(Capturer* capturer) - : EventExecutor(capturer) { +EventExecutorMac::EventExecutorMac( + MessageLoop* message_loop, Capturer* capturer) + : message_loop_(message_loop), + capturer_(capturer) { } EventExecutorMac::~EventExecutorMac() { } -void EventExecutorMac::HandleInputEvent(ChromotingClientMessage* message) { - delete message; +void EventExecutorMac::InjectKeyEvent(const KeyEvent* event, Task* done) { + done->Run(); + delete done; +} + +void EventExecutorMac::InjectMouseEvent(const MouseEvent* event, Task* done) { + done->Run(); + delete done; } } // namespace remoting diff --git a/remoting/host/event_executor_mac.h b/remoting/host/event_executor_mac.h index f8934b1..052ca48 100644 --- a/remoting/host/event_executor_mac.h +++ b/remoting/host/event_executor_mac.h @@ -7,19 +7,29 @@ #include <vector> -#include "remoting/host/event_executor.h" +#include "base/basictypes.h" +#include "remoting/protocol/input_stub.h" + +class MessageLoop; namespace remoting { +class Capturer; +class ChromotingClientMessage; + // A class to generate events on Mac. -class EventExecutorMac : public EventExecutor { +class EventExecutorMac : public protocol::InputStub { public: - EventExecutorMac(Capturer* capturer); + EventExecutorMac(MessageLoop* message_loop, Capturer* capturer); virtual ~EventExecutorMac(); - virtual void HandleInputEvent(ChromotingClientMessage* message); + virtual void InjectKeyEvent(const KeyEvent* event, Task* done); + virtual void InjectMouseEvent(const MouseEvent* event, Task* done); private: + MessageLoop* message_loop_; + Capturer* capturer_; + DISALLOW_COPY_AND_ASSIGN(EventExecutorMac); }; diff --git a/remoting/host/event_executor_win.cc b/remoting/host/event_executor_win.cc index 283d4aa..2ee24bd 100644 --- a/remoting/host/event_executor_win.cc +++ b/remoting/host/event_executor_win.cc @@ -5,43 +5,64 @@ #include "remoting/host/event_executor_win.h" #include <windows.h> + #include "app/keyboard_codes.h" +#include "base/message_loop.h" #include "base/stl_util-inl.h" #include "remoting/host/capturer.h" -// TODO(hclam): Should not include internal.pb.h here. -#include "remoting/proto/internal.pb.h" +#include "remoting/proto/event.pb.h" namespace remoting { -EventExecutorWin::EventExecutorWin(Capturer* capturer) - : EventExecutor(capturer) { +EventExecutorWin::EventExecutorWin( + MessageLoop* message_loop, Capturer* capturer) + : message_loop_(message_loop), capturer_(capturer) { } EventExecutorWin::~EventExecutorWin() { } -void EventExecutorWin::HandleInputEvent(ChromotingClientMessage* msg) { - if (msg->has_mouse_set_position_event()) { - HandleMouseSetPosition(msg); - } else if (msg->has_mouse_move_event()) { - HandleMouseMove(msg); - } else if (msg->has_mouse_wheel_event()) { - HandleMouseWheel(msg); - } else if (msg->has_mouse_down_event()) { - HandleMouseButtonDown(msg); - } else if (msg->has_mouse_up_event()) { - HandleMouseButtonUp(msg); - } else if (msg->has_key_event()) { - HandleKey(msg); +void EventExecutorWin::InjectKeyEvent(const KeyEvent* event, Task* done) { + if (MessageLoop::current() != message_loop_) { + message_loop_->PostTask( + FROM_HERE, + NewRunnableMethod(this, &EventExecutorWin::InjectKeyEvent, + event, done)); + return; + } + HandleKey(*event); + done->Run(); + delete done; +} + +void EventExecutorWin::InjectMouseEvent(const MouseEvent* event, + Task* done) { + if (MessageLoop::current() != message_loop_) { + message_loop_->PostTask( + FROM_HERE, + NewRunnableMethod(this, &EventExecutorWin::InjectMouseEvent, + event, done)); + return; + } + if (event->has_set_position()) { + HandleMouseSetPosition(event->set_position()); + } else if (event->has_wheel()) { + HandleMouseWheel(event->wheel()); + } else if (event->has_down()) { + HandleMouseButtonDown(event->down()); + } else if (event->has_up()) { + HandleMouseButtonUp(event->up()); } - delete msg; + done->Run(); + delete done; } -void EventExecutorWin::HandleMouseSetPosition(ChromotingClientMessage* msg) { - int x = msg->mouse_set_position_event().x(); - int y = msg->mouse_set_position_event().y(); - int width = msg->mouse_set_position_event().width(); - int height = msg->mouse_set_position_event().height(); +void EventExecutorWin::HandleMouseSetPosition( + const MouseSetPositionEvent& event) { + int x = event.x(); + int y = event.y(); + int width = event.width(); + int height = event.height(); // Get width and height from the capturer if they are missing from the // message. @@ -62,23 +83,14 @@ void EventExecutorWin::HandleMouseSetPosition(ChromotingClientMessage* msg) { SendInput(1, &input, sizeof(INPUT)); } -void EventExecutorWin::HandleMouseMove(ChromotingClientMessage* msg) { - INPUT input; - input.type = INPUT_MOUSE; - input.mi.time = 0; - input.mi.dx = msg->mouse_move_event().offset_x(); - input.mi.dy = msg->mouse_move_event().offset_y(); - input.mi.dwFlags = MOUSEEVENTF_MOVE; - SendInput(1, &input, sizeof(INPUT)); -} - -void EventExecutorWin::HandleMouseWheel(ChromotingClientMessage* msg) { +void EventExecutorWin::HandleMouseWheel( + const MouseWheelEvent& event) { INPUT input; input.type = INPUT_MOUSE; input.mi.time = 0; - int dx = msg->mouse_wheel_event().offset_x(); - int dy = msg->mouse_wheel_event().offset_y(); + int dx = event.offset_x(); + int dy = event.offset_y(); if (dx != 0) { input.mi.mouseData = dx; @@ -92,14 +104,14 @@ void EventExecutorWin::HandleMouseWheel(ChromotingClientMessage* msg) { } } -void EventExecutorWin::HandleMouseButtonDown(ChromotingClientMessage* msg) { +void EventExecutorWin::HandleMouseButtonDown(const MouseDownEvent& event) { INPUT input; input.type = INPUT_MOUSE; input.mi.time = 0; input.mi.dx = 0; input.mi.dy = 0; - MouseButton button = msg->mouse_down_event().button(); + MouseButton button = event.button(); if (button == MouseButtonLeft) { input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN; } else if (button == MouseButtonMiddle) { @@ -113,14 +125,14 @@ void EventExecutorWin::HandleMouseButtonDown(ChromotingClientMessage* msg) { SendInput(1, &input, sizeof(INPUT)); } -void EventExecutorWin::HandleMouseButtonUp(ChromotingClientMessage* msg) { +void EventExecutorWin::HandleMouseButtonUp(const MouseUpEvent& event) { INPUT input; input.type = INPUT_MOUSE; input.mi.time = 0; input.mi.dx = 0; input.mi.dy = 0; - MouseButton button = msg->mouse_down_event().button(); + MouseButton button = event.button(); if (button == MouseButtonLeft) { input.mi.dwFlags = MOUSEEVENTF_LEFTUP; } else if (button == MouseButtonMiddle) { @@ -134,9 +146,9 @@ void EventExecutorWin::HandleMouseButtonUp(ChromotingClientMessage* msg) { SendInput(1, &input, sizeof(INPUT)); } -void EventExecutorWin::HandleKey(ChromotingClientMessage* msg) { - int key = msg->key_event().key(); - bool down = msg->key_event().pressed(); +void EventExecutorWin::HandleKey(const KeyEvent& event) { + int key = event.key(); + bool down = event.pressed(); // Calculate scan code from virtual key. HKL hkl = GetKeyboardLayout(0); diff --git a/remoting/host/event_executor_win.h b/remoting/host/event_executor_win.h index e9a0269..b98d7be 100644 --- a/remoting/host/event_executor_win.h +++ b/remoting/host/event_executor_win.h @@ -7,29 +7,46 @@ #include <vector> -#include "remoting/host/event_executor.h" +#include "base/task.h" +#include "base/basictypes.h" +#include "base/scoped_ptr.h" +#include "remoting/protocol/input_stub.h" + +class MessageLoop; namespace remoting { +class Capturer; +class KeyEvent; +class MouseDownEvent; +class MouseSetPositionEvent; +class MouseUpEvent; +class MouseWheelEvent; + // A class to generate events on Windows. -class EventExecutorWin : public EventExecutor { +class EventExecutorWin : public protocol::InputStub { public: - EventExecutorWin(Capturer* capturer); + EventExecutorWin(MessageLoop* message_loop, Capturer* capturer); virtual ~EventExecutorWin(); - virtual void HandleInputEvent(ChromotingClientMessage* message); + virtual void InjectKeyEvent(const KeyEvent* event, Task* done); + virtual void InjectMouseEvent(const MouseEvent* event, Task* done); private: - void HandleMouseSetPosition(ChromotingClientMessage* msg); - void HandleMouseMove(ChromotingClientMessage* msg); - void HandleMouseWheel(ChromotingClientMessage* msg); - void HandleMouseButtonDown(ChromotingClientMessage* msg); - void HandleMouseButtonUp(ChromotingClientMessage* msg); - void HandleKey(ChromotingClientMessage* msg); + void HandleMouseSetPosition(const MouseSetPositionEvent& event); + void HandleMouseWheel(const MouseWheelEvent& event); + void HandleMouseButtonDown(const MouseDownEvent& event); + void HandleMouseButtonUp(const MouseUpEvent& event); + void HandleKey(const KeyEvent& event); + + MessageLoop* message_loop_; + Capturer* capturer_; DISALLOW_COPY_AND_ASSIGN(EventExecutorWin); }; } // namespace remoting +DISABLE_RUNNABLE_METHOD_REFCOUNT(remoting::EventExecutorWin); + #endif // REMOTING_HOST_EVENT_EXECUTOR_WIN_H_ diff --git a/remoting/host/mock_objects.h b/remoting/host/mock_objects.h index 8541d62..3c51097 100644 --- a/remoting/host/mock_objects.h +++ b/remoting/host/mock_objects.h @@ -6,8 +6,6 @@ #define REMOTING_HOST_MOCK_OBJECTS_H_ #include "remoting/host/capturer.h" -#include "remoting/host/event_executor.h" -#include "remoting/proto/internal.pb.h" #include "testing/gmock/include/gmock/gmock.h" namespace remoting { @@ -30,16 +28,6 @@ class MockCapturer : public Capturer { DISALLOW_COPY_AND_ASSIGN(MockCapturer); }; -class MockEventExecutor : public EventExecutor { - public: - MockEventExecutor(Capturer* capturer) : EventExecutor(capturer) {} - - MOCK_METHOD1(HandleInputEvent, void(ChromotingClientMessage* messages)); - - private: - DISALLOW_COPY_AND_ASSIGN(MockEventExecutor); -}; - } // namespace remoting #endif // REMOTING_HOST_MOCK_OBJECTS_H_ diff --git a/remoting/host/session_manager_unittest.cc b/remoting/host/session_manager_unittest.cc index bfe1fa4..5c853b28 100644 --- a/remoting/host/session_manager_unittest.cc +++ b/remoting/host/session_manager_unittest.cc @@ -37,11 +37,9 @@ class SessionManagerTest : public testing::Test { capturer_ = new MockCapturer(); encoder_ = new MockEncoder(); connection_ = new MockConnectionToClient(); - record_ = new SessionManager(&message_loop_, - &message_loop_, - &message_loop_, - capturer_, - encoder_); + record_ = new SessionManager( + &message_loop_, &message_loop_, &message_loop_, + capturer_, encoder_); } scoped_refptr<SessionManager> record_; diff --git a/remoting/host/simple_host_process.cc b/remoting/host/simple_host_process.cc index 98d9303..0d4b80e 100644 --- a/remoting/host/simple_host_process.cc +++ b/remoting/host/simple_host_process.cc @@ -71,20 +71,26 @@ int main(int argc, char** argv) { const CommandLine* cmd_line = CommandLine::ForCurrentProcess(); base::AtExitManager exit_manager; - base::EnsureNSPRInit(); + // Allocate a chromoting context and starts it. + remoting::ChromotingHostContext context; + context.Start(); + scoped_ptr<remoting::Capturer> capturer; - scoped_ptr<remoting::EventExecutor> event_handler; + scoped_ptr<remoting::protocol::InputStub> input_stub; #if defined(OS_WIN) capturer.reset(new remoting::CapturerGdi()); - event_handler.reset(new remoting::EventExecutorWin(capturer.get())); + input_stub.reset(new remoting::EventExecutorWin( + context.capture_message_loop(), capturer.get())); #elif defined(OS_LINUX) capturer.reset(new remoting::CapturerLinux()); - event_handler.reset(new remoting::EventExecutorLinux(capturer.get())); + input_stub.reset(new remoting::EventExecutorLinux( + context.capture_message_loop(), capturer.get())); #elif defined(OS_MACOSX) capturer.reset(new remoting::CapturerMac()); - event_handler.reset(new remoting::EventExecutorMac(capturer.get())); + input_stub.reset(new remoting::EventExecutorMac( + context.capture_message_loop(), capturer.get())); #endif // Check the argument to see if we should use a fake capturer. @@ -117,13 +123,10 @@ int main(int argc, char** argv) { if (!config->Read()) { LOG(ERROR) << "Failed to read configuration file " << config_path.value(); + context.Stop(); return 1; } - // Allocate a chromoting context and starts it. - remoting::ChromotingHostContext context; - context.Start(); - FilePath module_path; PathService::Get(base::DIR_MODULE, &module_path); CHECK(media::InitializeMediaLibrary(module_path)) @@ -134,7 +137,7 @@ int main(int argc, char** argv) { new remoting::ChromotingHost(&context, config, capturer.release(), - event_handler.release())); + input_stub.release())); // Let the chromoting host run until the shutdown task is executed. MessageLoop message_loop(MessageLoop::TYPE_UI); diff --git a/remoting/proto/event.proto b/remoting/proto/event.proto index 1f14c9dc..f6ca3f9 100644 --- a/remoting/proto/event.proto +++ b/remoting/proto/event.proto @@ -69,16 +69,16 @@ message MouseUpEvent { // Defines a mouse event message on the event channel. message MouseEvent { // Mouse position information. - optional int32 mouse_x = 1; - optional int32 mouse_y = 2; + optional MouseSetPositionEvent set_position = 1; // Mouse wheel information. - optional int32 wheel_offset_x = 3; - optional int32 wheel_offset_y = 4; + optional MouseWheelEvent wheel = 2; - // Mouse button information. - optional MouseButton button = 5; - optional bool button_down = 6; + // Mouse down event. + optional MouseDownEvent down = 3; + + // Mouse up event. + optional MouseUpEvent up = 4; } // Defines an event message on the event channel. diff --git a/remoting/protocol/connection_to_client.cc b/remoting/protocol/connection_to_client.cc index c3c695d..0661be3 100644 --- a/remoting/protocol/connection_to_client.cc +++ b/remoting/protocol/connection_to_client.cc @@ -7,6 +7,7 @@ #include "google/protobuf/message.h" #include "net/base/io_buffer.h" #include "remoting/protocol/client_control_sender.h" +#include "remoting/protocol/host_message_dispatcher.h" // TODO(hclam): Remove this header once MessageDispatcher is used. #include "remoting/base/compound_buffer.h" @@ -19,9 +20,13 @@ namespace protocol { static const size_t kAverageUpdateStream = 10; ConnectionToClient::ConnectionToClient(MessageLoop* message_loop, - EventHandler* handler) + EventHandler* handler, + HostStub* host_stub, + InputStub* input_stub) : loop_(message_loop), - handler_(handler) { + handler_(handler), + host_stub_(host_stub), + input_stub_(input_stub) { DCHECK(loop_); DCHECK(handler_); } @@ -74,23 +79,17 @@ void ConnectionToClient::OnSessionStateChange( protocol::Session::State state) { if (state == protocol::Session::CONNECTED) { client_stub_.reset(new ClientControlSender(session_->control_channel())); - event_reader_.Init<ChromotingClientMessage>( - session_->event_channel(), - NewCallback(this, &ConnectionToClient::OnMessageReceived)); video_writer_.reset(VideoWriter::Create(session_->config())); video_writer_->Init(session_); + + dispatcher_.reset(new HostMessageDispatcher()); + dispatcher_->Initialize(session_.get(), host_stub_, input_stub_); } loop_->PostTask(FROM_HERE, NewRunnableMethod(this, &ConnectionToClient::StateChangeTask, state)); } -void ConnectionToClient::OnMessageReceived(ChromotingClientMessage* message) { - loop_->PostTask(FROM_HERE, - NewRunnableMethod(this, &ConnectionToClient::MessageReceivedTask, - message)); -} - void ConnectionToClient::StateChangeTask(protocol::Session::State state) { DCHECK_EQ(loop_, MessageLoop::current()); @@ -114,12 +113,6 @@ void ConnectionToClient::StateChangeTask(protocol::Session::State state) { } } -void ConnectionToClient::MessageReceivedTask(ChromotingClientMessage* message) { - DCHECK_EQ(loop_, MessageLoop::current()); - DCHECK(handler_); - handler_->HandleMessage(this, message); -} - // OnClosed() is used as a callback for protocol::Session::Close(). void ConnectionToClient::OnClosed() { } diff --git a/remoting/protocol/connection_to_client.h b/remoting/protocol/connection_to_client.h index 769b0a8..546db76 100644 --- a/remoting/protocol/connection_to_client.h +++ b/remoting/protocol/connection_to_client.h @@ -11,7 +11,6 @@ #include "base/message_loop.h" #include "base/ref_counted.h" #include "base/scoped_ptr.h" -#include "remoting/protocol/message_reader.h" #include "remoting/protocol/session.h" #include "remoting/protocol/stream_writer.h" #include "remoting/protocol/video_writer.h" @@ -20,6 +19,9 @@ namespace remoting { namespace protocol { class ClientStub; +class HostStub; +class InputStub; +class HostMessageDispatcher; // This class represents a remote viewer connected to the chromoting host // through a libjingle connection. A viewer object is responsible for sending @@ -27,19 +29,12 @@ class ClientStub; // responsible for receiving and parsing data from the remote viewer and // delegating events to the event handler. class ConnectionToClient : - public base::RefCountedThreadSafe<ConnectionToClient> { + public base::RefCountedThreadSafe<ConnectionToClient> { public: class EventHandler { public: virtual ~EventHandler() {} - // Handles an event received by the ConnectionToClient. Receiver will own - // the ClientMessages in ClientMessageList and needs to delete them. - // Note that the sender of messages will not reference messages - // again so it is okay to clear |messages| in this method. - virtual void HandleMessage(ConnectionToClient* connection, - ChromotingClientMessage* message) = 0; - // Called when the network connection is opened. virtual void OnConnectionOpened(ConnectionToClient* connection) = 0; @@ -55,7 +50,9 @@ class ConnectionToClient : // a libjingle channel, these events are delegated to |handler|. // It is guranteed that |handler| is called only on the |message_loop|. ConnectionToClient(MessageLoop* message_loop, - EventHandler* handler); + EventHandler* handler, + HostStub* host_stub, + InputStub* input_stub); virtual ~ConnectionToClient(); @@ -90,21 +87,14 @@ class ConnectionToClient : // Callback for protocol Session. void OnSessionStateChange(protocol::Session::State state); - // Callback for MessageReader. - void OnMessageReceived(ChromotingClientMessage* message); - // Process a libjingle state change event on the |loop_|. void StateChangeTask(protocol::Session::State state); - // Process a data buffer received from libjingle. - void MessageReceivedTask(ChromotingClientMessage* message); - void OnClosed(); // The libjingle channel used to send and receive data from the remote client. scoped_refptr<protocol::Session> session_; - MessageReader event_reader_; scoped_ptr<VideoWriter> video_writer_; // ClientStub for sending messages to the client. @@ -116,6 +106,15 @@ class ConnectionToClient : // Event handler for handling events sent from this object. EventHandler* handler_; + // HostStub for receiving control events from the client. + HostStub* host_stub_; + + // InputStub for receiving input events from the client. + InputStub* input_stub_; + + // Dispatcher for submitting messages to stubs. + scoped_ptr<HostMessageDispatcher> dispatcher_; + DISALLOW_COPY_AND_ASSIGN(ConnectionToClient); }; diff --git a/remoting/protocol/connection_to_client_unittest.cc b/remoting/protocol/connection_to_client_unittest.cc index e199c12..eaea342 100644 --- a/remoting/protocol/connection_to_client_unittest.cc +++ b/remoting/protocol/connection_to_client_unittest.cc @@ -27,7 +27,8 @@ class ConnectionToClientTest : public testing::Test { session_->set_message_loop(&message_loop_); // Allocate a ClientConnection object with the mock objects. - viewer_ = new ConnectionToClient(&message_loop_, &handler_); + viewer_ = new ConnectionToClient(&message_loop_, &handler_, + &host_stub_, &input_stub_); viewer_->Init(session_); EXPECT_CALL(handler_, OnConnectionOpened(viewer_.get())); session_->state_change_callback()->Run( @@ -37,6 +38,8 @@ class ConnectionToClientTest : public testing::Test { MessageLoop message_loop_; MockConnectionToClientEventHandler handler_; + MockHostStub host_stub_; + MockInputStub input_stub_; scoped_refptr<ConnectionToClient> viewer_; scoped_refptr<protocol::FakeSession> session_; diff --git a/remoting/protocol/connection_to_host.h b/remoting/protocol/connection_to_host.h index e2b0ce2..d34b9ee 100644 --- a/remoting/protocol/connection_to_host.h +++ b/remoting/protocol/connection_to_host.h @@ -10,7 +10,6 @@ #include "base/ref_counted.h" #include "base/scoped_ptr.h" #include "remoting/proto/internal.pb.h" -#include "remoting/protocol/message_decoder.h" namespace remoting { namespace protocol { diff --git a/remoting/protocol/host_message_dispatcher.cc b/remoting/protocol/host_message_dispatcher.cc index 7ad9cac..13fa803 100644 --- a/remoting/protocol/host_message_dispatcher.cc +++ b/remoting/protocol/host_message_dispatcher.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/ref_counted.h" #include "net/base/io_buffer.h" #include "remoting/proto/control.pb.h" #include "remoting/proto/event.pb.h" @@ -77,13 +78,24 @@ void HostMessageDispatcher::OnControlMessageReceived(ControlMessage* message) { new RefCountedMessage<ControlMessage>(message); if (message->has_suggest_resolution()) { host_stub_->SuggestResolution( - message->suggest_resolution(), NewDeleteTask(ref_msg)); + &message->suggest_resolution(), NewDeleteTask(ref_msg)); } } void HostMessageDispatcher::OnEventMessageReceived( EventMessage* message) { - // TODO(hclam): Implement. + scoped_refptr<RefCountedMessage<EventMessage> > ref_msg = + new RefCountedMessage<EventMessage>(message); + for (int i = 0; i < message->event_size(); ++i) { + if (message->event(i).has_key()) { + input_stub_->InjectKeyEvent( + &message->event(i).key(), NewDeleteTask(ref_msg)); + } + if (message->event(i).has_mouse()) { + input_stub_->InjectMouseEvent( + &message->event(i).mouse(), NewDeleteTask(ref_msg)); + } + } } } // namespace protocol diff --git a/remoting/protocol/host_message_dispatcher.h b/remoting/protocol/host_message_dispatcher.h index cd95b26..c8b7a39 100644 --- a/remoting/protocol/host_message_dispatcher.h +++ b/remoting/protocol/host_message_dispatcher.h @@ -6,7 +6,6 @@ #define REMOTING_PROTOCOL_HOST_MESSAGE_DISPATCHER_H_ #include "base/basictypes.h" -#include "base/ref_counted.h" #include "base/scoped_ptr.h" #include "base/task.h" @@ -32,8 +31,7 @@ class Session; // // Object of this class is owned by ChromotingHost to dispatch messages // to itself. -class HostMessageDispatcher : - public base::RefCountedThreadSafe<HostMessageDispatcher> { +class HostMessageDispatcher { public: // Construct a message dispatcher. HostMessageDispatcher(); diff --git a/remoting/protocol/host_stub.h b/remoting/protocol/host_stub.h index a9e2fa5..cf14daa 100644 --- a/remoting/protocol/host_stub.h +++ b/remoting/protocol/host_stub.h @@ -24,7 +24,7 @@ class HostStub { virtual ~HostStub() {}; virtual void SuggestResolution( - const SuggestResolutionRequest& msg, Task* done) = 0; + const SuggestResolutionRequest* msg, Task* done) = 0; private: DISALLOW_COPY_AND_ASSIGN(HostStub); diff --git a/remoting/protocol/input_stub.h b/remoting/protocol/input_stub.h index 201dda3..c36ff07 100644 --- a/remoting/protocol/input_stub.h +++ b/remoting/protocol/input_stub.h @@ -22,8 +22,8 @@ class InputStub { InputStub() {} virtual ~InputStub() {} - virtual void InjectKeyEvent(const KeyEvent& event, Task* done) = 0; - virtual void InjectMouseEvent(const MouseEvent& event, Task* done) = 0; + virtual void InjectKeyEvent(const KeyEvent* event, Task* done) = 0; + virtual void InjectMouseEvent(const MouseEvent* event, Task* done) = 0; private: DISALLOW_COPY_AND_ASSIGN(InputStub); diff --git a/remoting/protocol/mock_objects.h b/remoting/protocol/mock_objects.h index 5acb131..b10c139 100644 --- a/remoting/protocol/mock_objects.h +++ b/remoting/protocol/mock_objects.h @@ -7,6 +7,8 @@ #include "remoting/proto/internal.pb.h" #include "remoting/protocol/connection_to_client.h" +#include "remoting/protocol/host_stub.h" +#include "remoting/protocol/input_stub.h" #include "testing/gmock/include/gmock/gmock.h" namespace remoting { @@ -44,6 +46,28 @@ class MockConnectionToClientEventHandler : DISALLOW_COPY_AND_ASSIGN(MockConnectionToClientEventHandler); }; +class MockInputStub : public InputStub { + public: + MockInputStub() {} + + MOCK_METHOD2(InjectKeyEvent, void(const KeyEvent* event, Task* done)); + MOCK_METHOD2(InjectMouseEvent, void(const MouseEvent* event, Task* done)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockInputStub); +}; + +class MockHostStub : public HostStub { + public: + MockHostStub() {} + + MOCK_METHOD2(SuggestResolution, void(const SuggestResolutionRequest* msg, + Task* done)); + + private: + DISALLOW_COPY_AND_ASSIGN(MockHostStub); +}; + } // namespace protocol } // namespace remoting diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp index 4402230..e1b20d3 100644 --- a/remoting/remoting.gyp +++ b/remoting/remoting.gyp @@ -197,7 +197,6 @@ 'host/differ.cc', 'host/differ_block.h', 'host/differ_block.cc', - 'host/event_executor.h', 'host/session_manager.cc', 'host/session_manager.h', 'host/heartbeat_sender.cc', |