| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "remoting/host/session_event_executor_win.h" | |
| 6 | |
| 7 #include <string> | |
| 8 | |
| 9 #include "base/bind.h" | |
| 10 #include "base/compiler_specific.h" | |
| 11 #include "base/location.h" | |
| 12 #include "base/single_thread_task_runner.h" | |
| 13 #include "base/win/windows_version.h" | |
| 14 #include "remoting/host/sas_injector.h" | |
| 15 #include "remoting/host/win/desktop.h" | |
| 16 #include "remoting/proto/event.pb.h" | |
| 17 | |
| 18 namespace { | |
| 19 | |
| 20 const uint32 kUsbLeftControl = 0x0700e0; | |
| 21 const uint32 kUsbRightControl = 0x0700e4; | |
| 22 const uint32 kUsbLeftAlt = 0x0700e2; | |
| 23 const uint32 kUsbRightAlt = 0x0700e6; | |
| 24 const uint32 kUsbDelete = 0x07004c; | |
| 25 | |
| 26 bool CheckCtrlAndAltArePressed(const std::set<uint32>& pressed_keys) { | |
| 27 size_t ctrl_keys = pressed_keys.count(kUsbLeftControl) + | |
| 28 pressed_keys.count(kUsbRightControl); | |
| 29 size_t alt_keys = pressed_keys.count(kUsbLeftAlt) + | |
| 30 pressed_keys.count(kUsbRightAlt); | |
| 31 return ctrl_keys != 0 && alt_keys != 0 && | |
| 32 (ctrl_keys + alt_keys == pressed_keys.size()); | |
| 33 } | |
| 34 | |
| 35 } // namespace | |
| 36 | |
| 37 namespace remoting { | |
| 38 | |
| 39 using protocol::ClipboardEvent; | |
| 40 using protocol::MouseEvent; | |
| 41 using protocol::KeyEvent; | |
| 42 | |
| 43 SessionEventExecutorWin::SessionEventExecutorWin( | |
| 44 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, | |
| 45 scoped_ptr<EventExecutor> nested_executor) | |
| 46 : nested_executor_(nested_executor.Pass()), | |
| 47 task_runner_(main_task_runner), | |
| 48 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), | |
| 49 weak_ptr_(weak_ptr_factory_.GetWeakPtr()) { | |
| 50 // Let |weak_ptr_| be used on the |task_runner_| thread. | |
| 51 // |weak_ptr_| and |weak_ptr_factory_| share a ThreadChecker, so the | |
| 52 // following line affects both of them. | |
| 53 weak_ptr_factory_.DetachFromThread(); | |
| 54 } | |
| 55 | |
| 56 SessionEventExecutorWin::~SessionEventExecutorWin() { | |
| 57 } | |
| 58 | |
| 59 void SessionEventExecutorWin::OnSessionStarted( | |
| 60 scoped_ptr<protocol::ClipboardStub> client_clipboard) { | |
| 61 if (!task_runner_->BelongsToCurrentThread()) { | |
| 62 task_runner_->PostTask( | |
| 63 FROM_HERE, | |
| 64 base::Bind(&SessionEventExecutorWin::OnSessionStarted, | |
| 65 weak_ptr_, base::Passed(&client_clipboard))); | |
| 66 return; | |
| 67 } | |
| 68 | |
| 69 nested_executor_->OnSessionStarted(client_clipboard.Pass()); | |
| 70 } | |
| 71 | |
| 72 void SessionEventExecutorWin::OnSessionFinished() { | |
| 73 if (!task_runner_->BelongsToCurrentThread()) { | |
| 74 task_runner_->PostTask( | |
| 75 FROM_HERE, | |
| 76 base::Bind(&SessionEventExecutorWin::OnSessionFinished, | |
| 77 weak_ptr_)); | |
| 78 return; | |
| 79 } | |
| 80 | |
| 81 nested_executor_->OnSessionFinished(); | |
| 82 } | |
| 83 | |
| 84 void SessionEventExecutorWin::InjectClipboardEvent( | |
| 85 const ClipboardEvent& event) { | |
| 86 if (!task_runner_->BelongsToCurrentThread()) { | |
| 87 task_runner_->PostTask( | |
| 88 FROM_HERE, | |
| 89 base::Bind(&SessionEventExecutorWin::InjectClipboardEvent, | |
| 90 weak_ptr_, event)); | |
| 91 return; | |
| 92 } | |
| 93 | |
| 94 nested_executor_->InjectClipboardEvent(event); | |
| 95 } | |
| 96 | |
| 97 void SessionEventExecutorWin::InjectKeyEvent(const KeyEvent& event) { | |
| 98 if (!task_runner_->BelongsToCurrentThread()) { | |
| 99 task_runner_->PostTask( | |
| 100 FROM_HERE, | |
| 101 base::Bind(&SessionEventExecutorWin::InjectKeyEvent, | |
| 102 weak_ptr_, event)); | |
| 103 return; | |
| 104 } | |
| 105 | |
| 106 // HostEventDispatcher should drop events lacking the pressed field. | |
| 107 DCHECK(event.has_pressed()); | |
| 108 | |
| 109 if (event.has_usb_keycode()) { | |
| 110 if (event.pressed()) { | |
| 111 // Simulate secure attention sequence if Ctrl-Alt-Del was just pressed. | |
| 112 if (event.usb_keycode() == kUsbDelete && | |
| 113 CheckCtrlAndAltArePressed(pressed_keys_)) { | |
| 114 VLOG(3) << "Sending Secure Attention Sequence to console"; | |
| 115 | |
| 116 if (sas_injector_.get() == NULL) | |
| 117 sas_injector_ = SasInjector::Create(); | |
| 118 sas_injector_->InjectSas(); | |
| 119 } | |
| 120 | |
| 121 pressed_keys_.insert(event.usb_keycode()); | |
| 122 } else { | |
| 123 pressed_keys_.erase(event.usb_keycode()); | |
| 124 } | |
| 125 } | |
| 126 | |
| 127 SwitchToInputDesktop(); | |
| 128 nested_executor_->InjectKeyEvent(event); | |
| 129 } | |
| 130 | |
| 131 void SessionEventExecutorWin::InjectMouseEvent(const MouseEvent& event) { | |
| 132 if (!task_runner_->BelongsToCurrentThread()) { | |
| 133 task_runner_->PostTask( | |
| 134 FROM_HERE, | |
| 135 base::Bind(&SessionEventExecutorWin::InjectMouseEvent, | |
| 136 weak_ptr_, event)); | |
| 137 return; | |
| 138 } | |
| 139 | |
| 140 SwitchToInputDesktop(); | |
| 141 nested_executor_->InjectMouseEvent(event); | |
| 142 } | |
| 143 | |
| 144 void SessionEventExecutorWin::SwitchToInputDesktop() { | |
| 145 // Switch to the desktop receiving user input if different from the current | |
| 146 // one. | |
| 147 scoped_ptr<Desktop> input_desktop = Desktop::GetInputDesktop(); | |
| 148 if (input_desktop.get() != NULL && !desktop_.IsSame(*input_desktop)) { | |
| 149 // If SetThreadDesktop() fails, the thread is still assigned a desktop. | |
| 150 // So we can continue capture screen bits, just from a diffected desktop. | |
| 151 desktop_.SetThreadDesktop(input_desktop.Pass()); | |
| 152 } | |
| 153 } | |
| 154 | |
| 155 } // namespace remoting | |
| OLD | NEW |