| Index: remoting/host/win/session_event_executor.cc
|
| diff --git a/remoting/host/win/session_event_executor.cc b/remoting/host/win/session_event_executor.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..027aef0ad172b889318d28bb09dbad2e6c8b0ee6
|
| --- /dev/null
|
| +++ b/remoting/host/win/session_event_executor.cc
|
| @@ -0,0 +1,156 @@
|
| +// 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/win/session_event_executor.h"
|
| +
|
| +#include <string>
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/compiler_specific.h"
|
| +#include "base/location.h"
|
| +#include "base/single_thread_task_runner.h"
|
| +#include "base/win/windows_version.h"
|
| +#include "remoting/host/sas_injector.h"
|
| +#include "remoting/host/win/desktop.h"
|
| +#include "remoting/proto/event.pb.h"
|
| +
|
| +namespace {
|
| +
|
| +const uint32 kUsbLeftControl = 0x0700e0;
|
| +const uint32 kUsbRightControl = 0x0700e4;
|
| +const uint32 kUsbLeftAlt = 0x0700e2;
|
| +const uint32 kUsbRightAlt = 0x0700e6;
|
| +const uint32 kUsbDelete = 0x07004c;
|
| +
|
| +bool CheckCtrlAndAltArePressed(const std::set<uint32>& pressed_keys) {
|
| + size_t ctrl_keys = pressed_keys.count(kUsbLeftControl) +
|
| + pressed_keys.count(kUsbRightControl);
|
| + size_t alt_keys = pressed_keys.count(kUsbLeftAlt) +
|
| + pressed_keys.count(kUsbRightAlt);
|
| + return ctrl_keys != 0 && alt_keys != 0 &&
|
| + (ctrl_keys + alt_keys == pressed_keys.size());
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +namespace remoting {
|
| +
|
| +using protocol::ClipboardEvent;
|
| +using protocol::MouseEvent;
|
| +using protocol::KeyEvent;
|
| +
|
| +SessionEventExecutorWin::SessionEventExecutorWin(
|
| + scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
|
| + scoped_ptr<EventExecutor> nested_executor)
|
| + : nested_executor_(nested_executor.Pass()),
|
| + task_runner_(main_task_runner),
|
| + ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)),
|
| + weak_ptr_(weak_ptr_factory_.GetWeakPtr()) {
|
| + // Let |weak_ptr_| be used on the |task_runner_| thread.
|
| + // |weak_ptr_| and |weak_ptr_factory_| share a ThreadChecker, so the
|
| + // following line affects both of them.
|
| + weak_ptr_factory_.DetachFromThread();
|
| +}
|
| +
|
| +SessionEventExecutorWin::~SessionEventExecutorWin() {
|
| +}
|
| +
|
| +void SessionEventExecutorWin::Start(
|
| + scoped_ptr<protocol::ClipboardStub> client_clipboard) {
|
| + if (!task_runner_->BelongsToCurrentThread()) {
|
| + task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&SessionEventExecutorWin::Start,
|
| + weak_ptr_, base::Passed(&client_clipboard)));
|
| + return;
|
| + }
|
| +
|
| + nested_executor_->Start(client_clipboard.Pass());
|
| +}
|
| +
|
| +void SessionEventExecutorWin::StopAndDelete() {
|
| + if (!task_runner_->BelongsToCurrentThread()) {
|
| + task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&SessionEventExecutorWin::StopAndDelete,
|
| + weak_ptr_));
|
| + return;
|
| + }
|
| +
|
| + nested_executor_.release()->StopAndDelete();
|
| + delete this;
|
| +}
|
| +
|
| +void SessionEventExecutorWin::InjectClipboardEvent(
|
| + const ClipboardEvent& event) {
|
| + if (!task_runner_->BelongsToCurrentThread()) {
|
| + task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&SessionEventExecutorWin::InjectClipboardEvent,
|
| + weak_ptr_, event));
|
| + return;
|
| + }
|
| +
|
| + nested_executor_->InjectClipboardEvent(event);
|
| +}
|
| +
|
| +void SessionEventExecutorWin::InjectKeyEvent(const KeyEvent& event) {
|
| + if (!task_runner_->BelongsToCurrentThread()) {
|
| + task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&SessionEventExecutorWin::InjectKeyEvent,
|
| + weak_ptr_, event));
|
| + return;
|
| + }
|
| +
|
| + // HostEventDispatcher should drop events lacking the pressed field.
|
| + DCHECK(event.has_pressed());
|
| +
|
| + if (event.has_usb_keycode()) {
|
| + if (event.pressed()) {
|
| + // Simulate secure attention sequence if Ctrl-Alt-Del was just pressed.
|
| + if (event.usb_keycode() == kUsbDelete &&
|
| + CheckCtrlAndAltArePressed(pressed_keys_)) {
|
| + VLOG(3) << "Sending Secure Attention Sequence to console";
|
| +
|
| + if (sas_injector_.get() == NULL)
|
| + sas_injector_ = SasInjector::Create();
|
| + sas_injector_->InjectSas();
|
| + }
|
| +
|
| + pressed_keys_.insert(event.usb_keycode());
|
| + } else {
|
| + pressed_keys_.erase(event.usb_keycode());
|
| + }
|
| + }
|
| +
|
| + SwitchToInputDesktop();
|
| + nested_executor_->InjectKeyEvent(event);
|
| +}
|
| +
|
| +void SessionEventExecutorWin::InjectMouseEvent(const MouseEvent& event) {
|
| + if (!task_runner_->BelongsToCurrentThread()) {
|
| + task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&SessionEventExecutorWin::InjectMouseEvent,
|
| + weak_ptr_, event));
|
| + return;
|
| + }
|
| +
|
| + SwitchToInputDesktop();
|
| + nested_executor_->InjectMouseEvent(event);
|
| +}
|
| +
|
| +void SessionEventExecutorWin::SwitchToInputDesktop() {
|
| + // Switch to the desktop receiving user input if different from the current
|
| + // one.
|
| + scoped_ptr<Desktop> input_desktop = Desktop::GetInputDesktop();
|
| + if (input_desktop.get() != NULL && !desktop_.IsSame(*input_desktop)) {
|
| + // If SetThreadDesktop() fails, the thread is still assigned a desktop.
|
| + // So we can continue capture screen bits, just from a diffected desktop.
|
| + desktop_.SetThreadDesktop(input_desktop.Pass());
|
| + }
|
| +}
|
| +
|
| +} // namespace remoting
|
|
|