summaryrefslogtreecommitdiffstats
path: root/remoting
diff options
context:
space:
mode:
authorsimonmorris@chromium.org <simonmorris@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-11 17:03:14 +0000
committersimonmorris@chromium.org <simonmorris@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-11 17:03:14 +0000
commit6d17db9e7a87de58b11c79b30d8513cb9532cbf7 (patch)
tree6245094524ea32f7750529febc02699a49d5f747 /remoting
parent8658269ac4dfabf70fa9079309ef83229ba1b833 (diff)
downloadchromium_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.cc4
-rw-r--r--remoting/host/chromoting_host_unittest.cc12
-rw-r--r--remoting/host/clipboard.h39
-rw-r--r--remoting/host/clipboard_linux.cc42
-rw-r--r--remoting/host/clipboard_mac.mm42
-rw-r--r--remoting/host/clipboard_win.cc200
-rw-r--r--remoting/host/desktop_environment.cc22
-rw-r--r--remoting/host/desktop_environment.h13
-rw-r--r--remoting/host/event_executor.h10
-rw-r--r--remoting/host/event_executor_linux.cc18
-rw-r--r--remoting/host/event_executor_mac.cc16
-rw-r--r--remoting/host/event_executor_win.cc58
-rw-r--r--remoting/host/host_mock_objects.h2
-rw-r--r--remoting/host/session_event_executor_win.cc21
-rw-r--r--remoting/host/session_event_executor_win.h14
-rw-r--r--remoting/host/simple_host_process.cc2
-rw-r--r--remoting/remoting.gyp4
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',