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 |