diff options
author | simonmorris@chromium.org <simonmorris@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-11 17:03:14 +0000 |
---|---|---|
committer | simonmorris@chromium.org <simonmorris@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-11 17:03:14 +0000 |
commit | 6d17db9e7a87de58b11c79b30d8513cb9532cbf7 (patch) | |
tree | 6245094524ea32f7750529febc02699a49d5f747 /remoting | |
parent | 8658269ac4dfabf70fa9079309ef83229ba1b833 (diff) | |
download | chromium_src-6d17db9e7a87de58b11c79b30d8513cb9532cbf7.zip chromium_src-6d17db9e7a87de58b11c79b30d8513cb9532cbf7.tar.gz chromium_src-6d17db9e7a87de58b11c79b30d8513cb9532cbf7.tar.bz2 |
[Chromoting] Let a Windows IT2Me host write to the clipboard.
BUG=117473
Review URL: https://chromiumcodereview.appspot.com/10332042
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@136591 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting')
-rw-r--r-- | remoting/host/chromoting_host.cc | 4 | ||||
-rw-r--r-- | remoting/host/chromoting_host_unittest.cc | 12 | ||||
-rw-r--r-- | remoting/host/clipboard.h | 39 | ||||
-rw-r--r-- | remoting/host/clipboard_linux.cc | 42 | ||||
-rw-r--r-- | remoting/host/clipboard_mac.mm | 42 | ||||
-rw-r--r-- | remoting/host/clipboard_win.cc | 200 | ||||
-rw-r--r-- | remoting/host/desktop_environment.cc | 22 | ||||
-rw-r--r-- | remoting/host/desktop_environment.h | 13 | ||||
-rw-r--r-- | remoting/host/event_executor.h | 10 | ||||
-rw-r--r-- | remoting/host/event_executor_linux.cc | 18 | ||||
-rw-r--r-- | remoting/host/event_executor_mac.cc | 16 | ||||
-rw-r--r-- | remoting/host/event_executor_win.cc | 58 | ||||
-rw-r--r-- | remoting/host/host_mock_objects.h | 2 | ||||
-rw-r--r-- | remoting/host/session_event_executor_win.cc | 21 | ||||
-rw-r--r-- | remoting/host/session_event_executor_win.h | 14 | ||||
-rw-r--r-- | remoting/host/simple_host_process.cc | 2 | ||||
-rw-r--r-- | remoting/remoting.gyp | 4 |
17 files changed, 468 insertions, 51 deletions
diff --git a/remoting/host/chromoting_host.cc b/remoting/host/chromoting_host.cc index bce2a86..a1285544 100644 --- a/remoting/host/chromoting_host.cc +++ b/remoting/host/chromoting_host.cc @@ -216,6 +216,7 @@ void ChromotingHost::OnSessionChannelsConnected(ClientSession* client) { // Immediately add the connection and start the session. recorder_->AddConnection(client->connection()); recorder_->Start(); + desktop_environment_->OnSessionStarted(); // Notify observers that there is at least one authenticated client. const std::string& jid = client->client_jid(); @@ -257,10 +258,11 @@ void ChromotingHost::OnSessionClosed(ClientSession* client) { OnClientDisconnected(client->client_jid())); if (recorder_.get()) { - // Currently we don't allow more than one similtaneous connection, + // Currently we don't allow more than one simultaneous connection, // so we need to shutdown recorder when a client disconnects. StopScreenRecorder(); } + desktop_environment_->OnSessionFinished(); } void ChromotingHost::OnSessionSequenceNumber(ClientSession* session, diff --git a/remoting/host/chromoting_host_unittest.cc b/remoting/host/chromoting_host_unittest.cc index 03ff320..78401ee 100644 --- a/remoting/host/chromoting_host_unittest.cc +++ b/remoting/host/chromoting_host_unittest.cc @@ -87,11 +87,11 @@ class ChromotingHostTest : public testing::Test { .Times(AnyNumber()); scoped_ptr<Capturer> capturer(new CapturerFake()); - event_executor_ = new MockEventExecutor(); + scoped_ptr<EventExecutor> event_executor(new MockEventExecutor()); desktop_environment_ = DesktopEnvironment::CreateFake( &context_, capturer.Pass(), - scoped_ptr<protocol::HostEventStub>(event_executor_)); + event_executor.Pass()); host_ = new ChromotingHost( &context_, &signal_strategy_, desktop_environment_.get(), @@ -131,10 +131,10 @@ class ChromotingHostTest : public testing::Test { .Times(AnyNumber()); owned_connection_.reset(new MockConnectionToClient( - session_, &host_stub_, event_executor_)); + session_, &host_stub_, desktop_environment_->event_executor())); connection_ = owned_connection_.get(); owned_connection2_.reset(new MockConnectionToClient( - session2_, &host_stub2_, &event_executor2_)); + session2_, &host_stub2_, desktop_environment_->event_executor())); connection2_ = owned_connection2_.get(); ON_CALL(video_stub_, ProcessVideoPacketPtr(_, _)) @@ -183,7 +183,7 @@ class ChromotingHostTest : public testing::Test { PassAs<protocol::ConnectionToClient>(); protocol::ConnectionToClient* connection_ptr = connection.get(); ClientSession* client = new ClientSession( - host_.get(), connection.Pass(), event_executor_, + host_.get(), connection.Pass(), desktop_environment_->event_executor(), desktop_environment_->capturer()); connection->set_host_stub(client); @@ -250,10 +250,8 @@ class ChromotingHostTest : public testing::Test { MockVideoStub video_stub2_; MockClientStub client_stub2_; MockHostStub host_stub2_; - MockEventExecutor event_executor2_; // Owned by |host_|. - MockEventExecutor* event_executor_; MockDisconnectWindow* disconnect_window_; MockContinueWindow* continue_window_; MockLocalInputMonitor* local_input_monitor_; diff --git a/remoting/host/clipboard.h b/remoting/host/clipboard.h new file mode 100644 index 0000000..c21a8ba --- /dev/null +++ b/remoting/host/clipboard.h @@ -0,0 +1,39 @@ +// Copyright (c) 2012 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_CLIPBOARD_H_ +#define REMOTING_HOST_CLIPBOARD_H_ + +#include <string> + +#include "base/callback.h" + +namespace remoting { + +namespace protocol { +class ClipboardEvent; +} // namespace protocol + +class Clipboard { + public: + virtual ~Clipboard() {}; + + // Initialises any objects needed to read from or write to the clipboard. + // This method must be called on the desktop thread. + virtual void Start() = 0; + + // Destroys any objects initialised by Start(). + // This method must be called on the desktop thread. + virtual void Stop() = 0; + + // Writes an item to the clipboard. + // This method must be called on the desktop thread, after Start(). + virtual void InjectClipboardEvent(const protocol::ClipboardEvent& event) = 0; + + static scoped_ptr<Clipboard> Create(); +}; + +} // namespace remoting + +#endif // REMOTING_HOST_CLIPBOARD_H_ diff --git a/remoting/host/clipboard_linux.cc b/remoting/host/clipboard_linux.cc new file mode 100644 index 0000000..56fa37b --- /dev/null +++ b/remoting/host/clipboard_linux.cc @@ -0,0 +1,42 @@ +// Copyright (c) 2012 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. + +#include "remoting/host/clipboard.h" + +#include "base/logging.h" + +namespace remoting { + +class ClipboardLinux : public Clipboard { + public: + ClipboardLinux(); + + // Must be called on the UI thread. + virtual void Start() OVERRIDE; + virtual void InjectClipboardEvent( + const protocol::ClipboardEvent& event) OVERRIDE; + virtual void Stop() OVERRIDE; + + private: + DISALLOW_COPY_AND_ASSIGN(ClipboardLinux); +}; + +void ClipboardLinux::Start() { + NOTIMPLEMENTED(); +} + +void ClipboardLinux::InjectClipboardEvent( + const protocol::ClipboardEvent& event) { + NOTIMPLEMENTED(); +} + +void ClipboardLinux::Stop() { + NOTIMPLEMENTED(); +} + +scoped_ptr<Clipboard> Clipboard::Create() { + return scoped_ptr<Clipboard>(new ClipboardLinux()); +} + +} // namespace remoting diff --git a/remoting/host/clipboard_mac.mm b/remoting/host/clipboard_mac.mm new file mode 100644 index 0000000..fb400b3 --- /dev/null +++ b/remoting/host/clipboard_mac.mm @@ -0,0 +1,42 @@ +// Copyright (c) 2012 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. + +#include "remoting/host/clipboard.h" + +#include "base/logging.h" + +namespace remoting { + +class ClipboardMac : public Clipboard { + public: + ClipboardMac(); + + // Must be called on the UI thread. + virtual void Start() OVERRIDE; + virtual void InjectClipboardEvent( + const protocol::ClipboardEvent& event) OVERRIDE; + virtual void Stop() OVERRIDE; + + private: + DISALLOW_COPY_AND_ASSIGN(ClipboardMac); +}; + +void ClipboardMac::Start() { + NOTIMPLEMENTED(); +} + +void ClipboardMac::InjectClipboardEvent( + const protocol::ClipboardEvent& event) { + NOTIMPLEMENTED(); +} + +void ClipboardMac::Stop() { + NOTIMPLEMENTED(); +} + +scoped_ptr<Clipboard> Clipboard::Create() { + return scoped_ptr<Clipboard>(new ClipboardMac()); +} + +} // namespace remoting diff --git a/remoting/host/clipboard_win.cc b/remoting/host/clipboard_win.cc new file mode 100644 index 0000000..d812d2f --- /dev/null +++ b/remoting/host/clipboard_win.cc @@ -0,0 +1,200 @@ +// Copyright (c) 2012 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. + +#include "remoting/host/clipboard.h" + +#include <windows.h> + +#include "base/basictypes.h" +#include "base/bind.h" +#include "base/logging.h" +#include "base/process_util.h" +#include "base/string16.h" +#include "base/utf_string_conversions.h" +#include "base/win/wrapped_window_proc.h" +#include "remoting/base/constants.h" +#include "remoting/proto/event.pb.h" + +namespace { + +const WCHAR kWindowClassName[] = L"clipboardWindowClass"; +const WCHAR kWindowName[] = L"clipboardWindow"; + +// A scoper class that opens and closes the clipboard. +// This class was adapted from the ScopedClipboard class in +// ui/base/clipboard/clipboard_win.cc. +class ScopedClipboard { + public: + ScopedClipboard() : opened_(false) { + } + + ~ScopedClipboard() { + if (opened_) { + ::CloseClipboard(); + } + } + + bool Init(HWND owner) { + const int kMaxAttemptsToOpenClipboard = 5; + const base::TimeDelta kSleepTimeBetweenAttempts = + base::TimeDelta::FromMilliseconds(5); + + if (opened_) { + NOTREACHED(); + return true; + } + + // This code runs on the desktop thread, so blocking briefly is acceptable. + for (int attempt = 0; attempt < kMaxAttemptsToOpenClipboard; ++attempt) { + if (attempt > 0) { + base::PlatformThread::Sleep(kSleepTimeBetweenAttempts); + } + if (::OpenClipboard(owner)) { + opened_ = true; + return true; + } + } + return false; + } + + BOOL Empty() { + if (!opened_) { + NOTREACHED(); + return false; + } + return ::EmptyClipboard(); + } + + void SetData(UINT uFormat, HANDLE hMem) { + if (!opened_) { + NOTREACHED(); + return; + } + // The caller must not close the handle that ::SetClipboardData returns. + ::SetClipboardData(uFormat, hMem); + } + + private: + bool opened_; +}; + +} // namespace + +namespace remoting { + +class ClipboardWin : public Clipboard { + public: + ClipboardWin(); + + virtual void Start() OVERRIDE; + virtual void InjectClipboardEvent( + const protocol::ClipboardEvent& event) OVERRIDE; + virtual void Stop() OVERRIDE; + + private: + static LRESULT CALLBACK WndProc(HWND hwmd, UINT msg, WPARAM wParam, + LPARAM lParam); + + static bool RegisterWindowClass(); + + HWND hwnd_; + + DISALLOW_COPY_AND_ASSIGN(ClipboardWin); +}; + +ClipboardWin::ClipboardWin() : hwnd_(NULL) { +} + +void ClipboardWin::Start() { + if (!RegisterWindowClass()) { + LOG(FATAL) << "Couldn't register clipboard window class."; + return; + } + hwnd_ = ::CreateWindow(kWindowClassName, + kWindowName, + 0, 0, 0, 0, 0, + HWND_MESSAGE, + NULL, + base::GetModuleFromAddress(&WndProc), + this); + if (!hwnd_) { + LOG(FATAL) << "Couldn't create clipboard window."; + return; + } +} + +void ClipboardWin::Stop() { + if (hwnd_) { + ::DestroyWindow(hwnd_); + hwnd_ = NULL; + } +} + +void ClipboardWin::InjectClipboardEvent( + const protocol::ClipboardEvent& event) { + if (!hwnd_) { + return; + } + // Currently we only handle UTF-8 text. + if (event.mime_type().compare(kMimeTypeTextUtf8)) { + return; + } + string16 text = UTF8ToUTF16(event.data()); + + ScopedClipboard clipboard; + if (!clipboard.Init(hwnd_)) { + LOG(WARNING) << "Couldn't open the clipboard."; + return; + } + + clipboard.Empty(); + + HGLOBAL text_global = + ::GlobalAlloc(GMEM_MOVEABLE, (text.size() + 1) * sizeof(WCHAR)); + if (!text_global) { + LOG(WARNING) << "Couldn't allocate global memory."; + return; + } + + LPWSTR text_global_locked = + reinterpret_cast<LPWSTR>(::GlobalLock(text_global)); + memcpy(text_global_locked, text.data(), text.size() * sizeof(WCHAR)); + text_global_locked[text.size()] = (WCHAR)0; + ::GlobalUnlock(text_global); + + clipboard.SetData(CF_UNICODETEXT, text_global); +} + +LRESULT CALLBACK ClipboardWin::WndProc(HWND hwnd, UINT msg, WPARAM wParam, + LPARAM lParam) { + return ::DefWindowProc(hwnd, msg, wParam, lParam); +} + +bool ClipboardWin::RegisterWindowClass() { + // This method is only called on the desktop thread, so it doesn't matter + // that the following test is not thread-safe. + static bool registered = false; + if (registered) { + return true; + } + + WNDCLASSEX window_class; + base::win::InitializeWindowClass( + kWindowClassName, + base::win::WrappedWindowProc<WndProc>, + 0, 0, 0, NULL, NULL, NULL, NULL, NULL, + &window_class); + if (!::RegisterClassEx(&window_class)) { + return false; + } + + registered = true; + return true; +} + +scoped_ptr<Clipboard> Clipboard::Create() { + return scoped_ptr<Clipboard>(new ClipboardWin()); +} + +} // namespace remoting diff --git a/remoting/host/desktop_environment.cc b/remoting/host/desktop_environment.cc index 97586f9..412c27e 100644 --- a/remoting/host/desktop_environment.cc +++ b/remoting/host/desktop_environment.cc @@ -21,9 +21,8 @@ namespace remoting { scoped_ptr<DesktopEnvironment> DesktopEnvironment::Create( ChromotingHostContext* context) { scoped_ptr<Capturer> capturer(Capturer::Create()); - scoped_ptr<protocol::HostEventStub> event_executor = - EventExecutor::Create(context->desktop_message_loop(), - capturer.get()); + scoped_ptr<EventExecutor> event_executor = + EventExecutor::Create(context->desktop_message_loop(), capturer.get()); if (capturer.get() == NULL || event_executor.get() == NULL) { LOG(ERROR) << "Unable to create DesktopEnvironment"; @@ -40,9 +39,8 @@ scoped_ptr<DesktopEnvironment> DesktopEnvironment::Create( scoped_ptr<DesktopEnvironment> DesktopEnvironment::CreateForService( ChromotingHostContext* context) { scoped_ptr<Capturer> capturer(Capturer::Create()); - scoped_ptr<protocol::HostEventStub> event_executor = - EventExecutor::Create(context->desktop_message_loop(), - capturer.get()); + scoped_ptr<EventExecutor> event_executor = + EventExecutor::Create(context->desktop_message_loop(), capturer.get()); if (capturer.get() == NULL || event_executor.get() == NULL) { LOG(ERROR) << "Unable to create DesktopEnvironment"; @@ -66,7 +64,7 @@ scoped_ptr<DesktopEnvironment> DesktopEnvironment::CreateForService( scoped_ptr<DesktopEnvironment> DesktopEnvironment::CreateFake( ChromotingHostContext* context, scoped_ptr<Capturer> capturer, - scoped_ptr<protocol::HostEventStub> event_executor) { + scoped_ptr<EventExecutor> event_executor) { return scoped_ptr<DesktopEnvironment>( new DesktopEnvironment(context, capturer.Pass(), @@ -76,7 +74,7 @@ scoped_ptr<DesktopEnvironment> DesktopEnvironment::CreateFake( DesktopEnvironment::DesktopEnvironment( ChromotingHostContext* context, scoped_ptr<Capturer> capturer, - scoped_ptr<protocol::HostEventStub> event_executor) + scoped_ptr<EventExecutor> event_executor) : host_(NULL), context_(context), capturer_(capturer.Pass()), @@ -86,4 +84,12 @@ DesktopEnvironment::DesktopEnvironment( DesktopEnvironment::~DesktopEnvironment() { } +void DesktopEnvironment::OnSessionStarted() { + event_executor_->OnSessionStarted(); +} + +void DesktopEnvironment::OnSessionFinished() { + event_executor_->OnSessionFinished(); +} + } // namespace remoting diff --git a/remoting/host/desktop_environment.h b/remoting/host/desktop_environment.h index 237f94b..e27e33a 100644 --- a/remoting/host/desktop_environment.h +++ b/remoting/host/desktop_environment.h @@ -12,6 +12,7 @@ #include "base/memory/scoped_ptr.h" #include "base/time.h" #include "remoting/base/scoped_thread_proxy.h" +#include "remoting/host/event_executor.h" namespace remoting { @@ -36,21 +37,21 @@ class DesktopEnvironment { static scoped_ptr<DesktopEnvironment> CreateFake( ChromotingHostContext* context, scoped_ptr<Capturer> capturer, - scoped_ptr<protocol::HostEventStub> event_executor); + scoped_ptr<EventExecutor> event_executor); virtual ~DesktopEnvironment(); void set_host(ChromotingHost* host) { host_ = host; } Capturer* capturer() const { return capturer_.get(); } - protocol::HostEventStub* event_executor() const { - return event_executor_.get(); - } + EventExecutor* event_executor() const { return event_executor_.get(); } + void OnSessionStarted(); + void OnSessionFinished(); private: DesktopEnvironment(ChromotingHostContext* context, scoped_ptr<Capturer> capturer, - scoped_ptr<protocol::HostEventStub> event_executor); + scoped_ptr<EventExecutor> event_executor); // The host that owns this DesktopEnvironment. ChromotingHost* host_; @@ -63,7 +64,7 @@ class DesktopEnvironment { scoped_ptr<Capturer> capturer_; // Executes input and clipboard events received from the client. - scoped_ptr<protocol::HostEventStub> event_executor_; + scoped_ptr<EventExecutor> event_executor_; DISALLOW_COPY_AND_ASSIGN(DesktopEnvironment); }; diff --git a/remoting/host/event_executor.h b/remoting/host/event_executor.h index 3acde7a..eb0a886 100644 --- a/remoting/host/event_executor.h +++ b/remoting/host/event_executor.h @@ -17,8 +17,14 @@ class Capturer; class EventExecutor : public protocol::HostEventStub { public: // Creates default event executor for the current platform. - static scoped_ptr<protocol::HostEventStub> Create(MessageLoop* message_loop, - Capturer* capturer); + static scoped_ptr<EventExecutor> Create(MessageLoop* message_loop, + Capturer* capturer); + + // Initialises any objects needed to execute events. + virtual void OnSessionStarted() = 0; + + // Destroys any objects constructed by Start(). + virtual void OnSessionFinished() = 0; }; } // namespace remoting diff --git a/remoting/host/event_executor_linux.cc b/remoting/host/event_executor_linux.cc index ff07af7..bf8856f 100644 --- a/remoting/host/event_executor_linux.cc +++ b/remoting/host/event_executor_linux.cc @@ -47,6 +47,10 @@ class EventExecutorLinux : public EventExecutor { virtual void InjectKeyEvent(const KeyEvent& event) OVERRIDE; virtual void InjectMouseEvent(const MouseEvent& event) OVERRIDE; + // EventExecutor interface. + virtual void OnSessionStarted() OVERRIDE; + virtual void OnSessionFinished() OVERRIDE; + private: // |mode| is one of the AutoRepeatModeOn, AutoRepeatModeOff, // AutoRepeatModeDefault constants defined by the XChangeKeyboardControl() @@ -415,15 +419,23 @@ void EventExecutorLinux::InjectMouseEvent(const MouseEvent& event) { XFlush(display_); } +void EventExecutorLinux::OnSessionStarted() { + return; +} + +void EventExecutorLinux::OnSessionFinished() { + return; +} + } // namespace -scoped_ptr<protocol::HostEventStub> EventExecutor::Create( +scoped_ptr<EventExecutor> EventExecutor::Create( MessageLoop* message_loop, Capturer* capturer) { scoped_ptr<EventExecutorLinux> executor( new EventExecutorLinux(message_loop)); if (!executor->Init()) - return scoped_ptr<protocol::HostEventStub>(NULL); - return executor.PassAs<protocol::HostEventStub>(); + return scoped_ptr<EventExecutor>(NULL); + return executor.PassAs<EventExecutor>(); } } // namespace remoting diff --git a/remoting/host/event_executor_mac.cc b/remoting/host/event_executor_mac.cc index 29b6dda..aaf2187 100644 --- a/remoting/host/event_executor_mac.cc +++ b/remoting/host/event_executor_mac.cc @@ -41,6 +41,10 @@ class EventExecutorMac : public EventExecutor { virtual void InjectKeyEvent(const KeyEvent& event) OVERRIDE; virtual void InjectMouseEvent(const MouseEvent& event) OVERRIDE; + // EventExecutor interface. + virtual void OnSessionStarted() OVERRIDE; + virtual void OnSessionFinished() OVERRIDE; + private: MessageLoop* message_loop_; SkIPoint mouse_pos_; @@ -322,11 +326,19 @@ void EventExecutorMac::InjectMouseEvent(const MouseEvent& event) { } } +void EventExecutorMac::OnSessionStarted() { + return; +} + +void EventExecutorMac::OnSessionFinished() { + return; +} + } // namespace -scoped_ptr<protocol::HostEventStub> EventExecutor::Create( +scoped_ptr<EventExecutor> EventExecutor::Create( MessageLoop* message_loop, Capturer* capturer) { - return scoped_ptr<protocol::HostEventStub>( + return scoped_ptr<EventExecutor>( new EventExecutorMac(message_loop)); } diff --git a/remoting/host/event_executor_win.cc b/remoting/host/event_executor_win.cc index 2b553e5..007f31b 100644 --- a/remoting/host/event_executor_win.cc +++ b/remoting/host/event_executor_win.cc @@ -10,6 +10,7 @@ #include "base/compiler_specific.h" #include "base/message_loop.h" #include "remoting/host/capturer.h" +#include "remoting/host/clipboard.h" #include "remoting/proto/event.pb.h" #include "ui/base/keycodes/keyboard_codes.h" @@ -39,13 +40,20 @@ class EventExecutorWin : public EventExecutor { virtual void InjectKeyEvent(const KeyEvent& event) OVERRIDE; virtual void InjectMouseEvent(const MouseEvent& event) OVERRIDE; + // EventExecutor interface. + virtual void OnSessionStarted() OVERRIDE; + virtual void OnSessionFinished() OVERRIDE; + private: HKL GetForegroundKeyboardLayout(); void HandleKey(const KeyEvent& event); void HandleMouse(const MouseEvent& event); + void HandleSessionStarted(); + void HandleSessionFinished(); MessageLoop* message_loop_; Capturer* capturer_; + scoped_ptr<Clipboard> clipboard_; DISALLOW_COPY_AND_ASSIGN(EventExecutorWin); }; @@ -53,11 +61,21 @@ class EventExecutorWin : public EventExecutor { EventExecutorWin::EventExecutorWin(MessageLoop* message_loop, Capturer* capturer) : message_loop_(message_loop), - capturer_(capturer) { + capturer_(capturer), + clipboard_(Clipboard::Create()) { } void EventExecutorWin::InjectClipboardEvent(const ClipboardEvent& event) { - // TODO(simonmorris): Implement clipboard injection. + if (MessageLoop::current() != message_loop_) { + message_loop_->PostTask( + FROM_HERE, + base::Bind(&EventExecutorWin::InjectClipboardEvent, + base::Unretained(this), + event)); + return; + } + + clipboard_->InjectClipboardEvent(event); } void EventExecutorWin::InjectKeyEvent(const KeyEvent& event) { @@ -84,6 +102,30 @@ void EventExecutorWin::InjectMouseEvent(const MouseEvent& event) { HandleMouse(event); } +void EventExecutorWin::OnSessionStarted() { + if (MessageLoop::current() != message_loop_) { + message_loop_->PostTask( + FROM_HERE, + base::Bind(&EventExecutorWin::OnSessionStarted, + base::Unretained(this))); + return; + } + + HandleSessionStarted(); +} + +void EventExecutorWin::OnSessionFinished() { + if (MessageLoop::current() != message_loop_) { + message_loop_->PostTask( + FROM_HERE, + base::Bind(&EventExecutorWin::OnSessionFinished, + base::Unretained(this))); + return; + } + + HandleSessionFinished(); +} + HKL EventExecutorWin::GetForegroundKeyboardLayout() { HKL layout = 0; @@ -236,11 +278,19 @@ void EventExecutorWin::HandleMouse(const MouseEvent& event) { } } +void EventExecutorWin::HandleSessionStarted() { + clipboard_->Start(); +} + +void EventExecutorWin::HandleSessionFinished() { + clipboard_->Stop(); +} + } // namespace -scoped_ptr<protocol::HostEventStub> EventExecutor::Create( +scoped_ptr<EventExecutor> EventExecutor::Create( MessageLoop* message_loop, Capturer* capturer) { - return scoped_ptr<protocol::HostEventStub>( + return scoped_ptr<EventExecutor>( new EventExecutorWin(message_loop, capturer)); } diff --git a/remoting/host/host_mock_objects.h b/remoting/host/host_mock_objects.h index b6e0870..abb19d52 100644 --- a/remoting/host/host_mock_objects.h +++ b/remoting/host/host_mock_objects.h @@ -125,6 +125,8 @@ class MockEventExecutor : public EventExecutor { void(const protocol::ClipboardEvent& event)); MOCK_METHOD1(InjectKeyEvent, void(const protocol::KeyEvent& event)); MOCK_METHOD1(InjectMouseEvent, void(const protocol::MouseEvent& event)); + MOCK_METHOD0(OnSessionStarted, void()); + MOCK_METHOD0(OnSessionFinished, void()); private: DISALLOW_COPY_AND_ASSIGN(MockEventExecutor); diff --git a/remoting/host/session_event_executor_win.cc b/remoting/host/session_event_executor_win.cc index 75920f0..002375f 100644 --- a/remoting/host/session_event_executor_win.cc +++ b/remoting/host/session_event_executor_win.cc @@ -48,7 +48,7 @@ using protocol::KeyEvent; SessionEventExecutorWin::SessionEventExecutorWin( MessageLoop* message_loop, base::MessageLoopProxy* io_message_loop, - scoped_ptr<protocol::HostEventStub> nested_executor) + scoped_ptr<EventExecutor> nested_executor) : nested_executor_(nested_executor.Pass()), message_loop_(message_loop) { std::string channel_name = @@ -68,18 +68,17 @@ SessionEventExecutorWin::SessionEventExecutorWin( SessionEventExecutorWin::~SessionEventExecutorWin() { } +void SessionEventExecutorWin::OnSessionStarted() { + // TODO(simonmorris): Delegate to the nested executor. +} + +void SessionEventExecutorWin::OnSessionFinished() { + // TODO(simonmorris): Delegate to the nested executor. +} + void SessionEventExecutorWin::InjectClipboardEvent( const ClipboardEvent& event) { - if (MessageLoop::current() != message_loop_) { - message_loop_->PostTask( - FROM_HERE, - base::Bind(&SessionEventExecutorWin::InjectClipboardEvent, - base::Unretained(this), event)); - return; - } - - SwitchToInputDesktop(); - nested_executor_->InjectClipboardEvent(event); + // TODO(simonmorris): Delegate to the nested executor. } void SessionEventExecutorWin::InjectKeyEvent(const KeyEvent& event) { diff --git a/remoting/host/session_event_executor_win.h b/remoting/host/session_event_executor_win.h index 0d1f12f..267fe59 100644 --- a/remoting/host/session_event_executor_win.h +++ b/remoting/host/session_event_executor_win.h @@ -27,19 +27,21 @@ class ChannelProxy; namespace remoting { -class SessionEventExecutorWin : public protocol::HostEventStub, +class SessionEventExecutorWin : public EventExecutor, public IPC::Channel::Listener { public: SessionEventExecutorWin(MessageLoop* message_loop, base::MessageLoopProxy* io_message_loop, - scoped_ptr<protocol::HostEventStub> nested_executor); + scoped_ptr<EventExecutor> nested_executor); ~SessionEventExecutorWin(); - // ClipboardStub interface. + // EventExecutor implementation. + virtual void OnSessionStarted() OVERRIDE; + virtual void OnSessionFinished() OVERRIDE; + + // protocol::HostStub implementation. virtual void InjectClipboardEvent( const protocol::ClipboardEvent& event) OVERRIDE; - - // protocol::InputStub implementation. virtual void InjectKeyEvent(const protocol::KeyEvent& event) OVERRIDE; virtual void InjectMouseEvent(const protocol::MouseEvent& event) OVERRIDE; @@ -52,7 +54,7 @@ class SessionEventExecutorWin : public protocol::HostEventStub, void SwitchToInputDesktop(); // Pointer to the next event executor. - scoped_ptr<protocol::HostEventStub> nested_executor_; + scoped_ptr<EventExecutor> nested_executor_; MessageLoop* message_loop_; diff --git a/remoting/host/simple_host_process.cc b/remoting/host/simple_host_process.cc index 114802b..932f32e 100644 --- a/remoting/host/simple_host_process.cc +++ b/remoting/host/simple_host_process.cc @@ -218,7 +218,7 @@ class SimpleHost : public HeartbeatSender::Listener { if (fake_) { scoped_ptr<Capturer> capturer(new CapturerFake()); - scoped_ptr<protocol::HostEventStub> event_executor = + scoped_ptr<EventExecutor> event_executor = EventExecutor::Create( context_.desktop_message_loop(), capturer.get()); desktop_environment_ = DesktopEnvironment::CreateFake( diff --git a/remoting/remoting.gyp b/remoting/remoting.gyp index da81e1f..0195b5a 100644 --- a/remoting/remoting.gyp +++ b/remoting/remoting.gyp @@ -1114,6 +1114,10 @@ 'host/chromoting_host_context.h', 'host/client_session.cc', 'host/client_session.h', + 'host/clipboard.h', + 'host/clipboard_linux.cc', + 'host/clipboard_mac.mm', + 'host/clipboard_win.cc', 'host/constants.h', 'host/continue_window.h', 'host/continue_window_mac.mm', |