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/win/session_event_executor.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::Start( | |
60 scoped_ptr<protocol::ClipboardStub> client_clipboard) { | |
61 if (!task_runner_->BelongsToCurrentThread()) { | |
62 task_runner_->PostTask( | |
63 FROM_HERE, | |
64 base::Bind(&SessionEventExecutorWin::Start, | |
65 weak_ptr_, base::Passed(&client_clipboard))); | |
66 return; | |
67 } | |
68 | |
69 nested_executor_->Start(client_clipboard.Pass()); | |
70 } | |
71 | |
72 void SessionEventExecutorWin::StopAndDelete() { | |
73 if (!task_runner_->BelongsToCurrentThread()) { | |
74 task_runner_->PostTask( | |
75 FROM_HERE, | |
76 base::Bind(&SessionEventExecutorWin::StopAndDelete, | |
77 weak_ptr_)); | |
78 return; | |
79 } | |
80 | |
81 nested_executor_.release()->StopAndDelete(); | |
82 delete this; | |
83 } | |
84 | |
85 void SessionEventExecutorWin::InjectClipboardEvent( | |
86 const ClipboardEvent& event) { | |
87 if (!task_runner_->BelongsToCurrentThread()) { | |
88 task_runner_->PostTask( | |
89 FROM_HERE, | |
90 base::Bind(&SessionEventExecutorWin::InjectClipboardEvent, | |
91 weak_ptr_, event)); | |
92 return; | |
93 } | |
94 | |
95 nested_executor_->InjectClipboardEvent(event); | |
96 } | |
97 | |
98 void SessionEventExecutorWin::InjectKeyEvent(const KeyEvent& event) { | |
99 if (!task_runner_->BelongsToCurrentThread()) { | |
100 task_runner_->PostTask( | |
101 FROM_HERE, | |
102 base::Bind(&SessionEventExecutorWin::InjectKeyEvent, | |
103 weak_ptr_, event)); | |
104 return; | |
105 } | |
106 | |
107 // HostEventDispatcher should drop events lacking the pressed field. | |
108 DCHECK(event.has_pressed()); | |
109 | |
110 if (event.has_usb_keycode()) { | |
111 if (event.pressed()) { | |
112 // Simulate secure attention sequence if Ctrl-Alt-Del was just pressed. | |
113 if (event.usb_keycode() == kUsbDelete && | |
114 CheckCtrlAndAltArePressed(pressed_keys_)) { | |
115 VLOG(3) << "Sending Secure Attention Sequence to console"; | |
116 | |
117 if (sas_injector_.get() == NULL) | |
118 sas_injector_ = SasInjector::Create(); | |
119 sas_injector_->InjectSas(); | |
120 } | |
121 | |
122 pressed_keys_.insert(event.usb_keycode()); | |
123 } else { | |
124 pressed_keys_.erase(event.usb_keycode()); | |
125 } | |
126 } | |
127 | |
128 SwitchToInputDesktop(); | |
129 nested_executor_->InjectKeyEvent(event); | |
130 } | |
131 | |
132 void SessionEventExecutorWin::InjectMouseEvent(const MouseEvent& event) { | |
133 if (!task_runner_->BelongsToCurrentThread()) { | |
134 task_runner_->PostTask( | |
135 FROM_HERE, | |
136 base::Bind(&SessionEventExecutorWin::InjectMouseEvent, | |
137 weak_ptr_, event)); | |
138 return; | |
139 } | |
140 | |
141 SwitchToInputDesktop(); | |
142 nested_executor_->InjectMouseEvent(event); | |
143 } | |
144 | |
145 void SessionEventExecutorWin::SwitchToInputDesktop() { | |
146 // Switch to the desktop receiving user input if different from the current | |
147 // one. | |
148 scoped_ptr<Desktop> input_desktop = Desktop::GetInputDesktop(); | |
149 if (input_desktop.get() != NULL && !desktop_.IsSame(*input_desktop)) { | |
150 // If SetThreadDesktop() fails, the thread is still assigned a desktop. | |
151 // So we can continue capture screen bits, just from a diffected desktop. | |
152 desktop_.SetThreadDesktop(input_desktop.Pass()); | |
153 } | |
154 } | |
155 | |
156 } // namespace remoting | |
OLD | NEW |