OLD | NEW |
---|---|
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "remoting/host/win/rdp_client_window.h" | 5 #include "remoting/host/win/rdp_client_window.h" |
6 | 6 |
7 #include <wtsdefs.h> | 7 #include <wtsdefs.h> |
8 | 8 |
9 #include "base/lazy_instance.h" | |
9 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/threading/thread_local.h" | |
10 #include "base/utf_string_conversions.h" | 12 #include "base/utf_string_conversions.h" |
11 #include "base/win/scoped_bstr.h" | 13 #include "base/win/scoped_bstr.h" |
12 | 14 |
15 namespace remoting { | |
16 | |
17 namespace { | |
18 | |
13 // RDP connection disconnect reasons codes that should not be interpreted as | 19 // RDP connection disconnect reasons codes that should not be interpreted as |
14 // errors. | 20 // errors. |
15 const long kDisconnectReasonNoInfo = 0; | 21 const long kDisconnectReasonNoInfo = 0; |
16 const long kDisconnectReasonLocalNotError = 1; | 22 const long kDisconnectReasonLocalNotError = 1; |
17 const long kDisconnectReasonRemoteByUser = 2; | 23 const long kDisconnectReasonRemoteByUser = 2; |
18 const long kDisconnectReasonByServer = 3; | 24 const long kDisconnectReasonByServer = 3; |
19 | 25 |
20 namespace remoting { | 26 // Points to a per-thread instance of the window actication hook handle. |
garykac
2013/04/15 18:23:49
activation
alexeypa (please no reviews)
2013/04/15 18:26:53
Done.
| |
27 base::LazyInstance<base::ThreadLocalPointer<RdpClientWindow::WindowHook> > | |
28 g_window_hook = LAZY_INSTANCE_INITIALIZER; | |
29 | |
30 } // namespace | |
31 | |
32 // Used to close any windows activated on a particular thread. It installs\ | |
garykac
2013/04/15 18:23:49
'\'?
alexeypa (please no reviews)
2013/04/15 18:26:53
Done.
| |
33 // a WH_CBT window hook to track window activations and close all activated | |
34 // windows. There should be only one instance of |WindowHook| per thread | |
35 // at any given moment. | |
36 class RdpClientWindow::WindowHook | |
37 : public base::RefCounted<WindowHook> { | |
38 public: | |
39 static scoped_refptr<WindowHook> Create(); | |
40 | |
41 private: | |
42 friend class base::RefCounted<WindowHook>; | |
43 | |
44 WindowHook(); | |
45 virtual ~WindowHook(); | |
46 | |
47 static LRESULT CALLBACK CloseWindowOnActivation( | |
48 int code, WPARAM wparam, LPARAM lparam); | |
49 | |
50 HHOOK hook_; | |
51 | |
52 DISALLOW_COPY_AND_ASSIGN(WindowHook); | |
53 }; | |
21 | 54 |
22 RdpClientWindow::RdpClientWindow(const net::IPEndPoint& server_endpoint, | 55 RdpClientWindow::RdpClientWindow(const net::IPEndPoint& server_endpoint, |
23 EventHandler* event_handler) | 56 EventHandler* event_handler) |
24 : event_handler_(event_handler), | 57 : event_handler_(event_handler), |
25 screen_size_(SkISize::Make(0, 0)), | 58 screen_size_(SkISize::Make(0, 0)), |
26 server_endpoint_(server_endpoint) { | 59 server_endpoint_(server_endpoint) { |
27 } | 60 } |
28 | 61 |
29 RdpClientWindow::~RdpClientWindow() { | 62 RdpClientWindow::~RdpClientWindow() { |
30 if (m_hWnd) | 63 if (m_hWnd) |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
193 | 226 |
194 return 0; | 227 return 0; |
195 } | 228 } |
196 | 229 |
197 void RdpClientWindow::OnDestroy() { | 230 void RdpClientWindow::OnDestroy() { |
198 client_.Release(); | 231 client_.Release(); |
199 client_settings_.Release(); | 232 client_settings_.Release(); |
200 } | 233 } |
201 | 234 |
202 HRESULT RdpClientWindow::OnAuthenticationWarningDisplayed() { | 235 HRESULT RdpClientWindow::OnAuthenticationWarningDisplayed() { |
203 LOG(ERROR) << "RDP: authentication warning is about to be shown. Closing " | 236 LOG(WARNING) << "RDP: authentication warning is about to be shown."; |
204 "the connection because the modal UI will block any further " | |
205 "progress"; | |
206 | 237 |
207 DestroyWindow(); | 238 // Hook window activation to cancel any modal UI shown by the RDP control. |
208 NotifyDisconnected(); | 239 // This does not affect creation other instances of the RDP control on this |
garykac
2013/04/15 18:23:49
...affect the creation of other...
alexeypa (please no reviews)
2013/04/15 18:26:53
Done.
| |
240 // thread because the RDP control's window is hidden and is not activated. | |
241 window_activate_hook_ = WindowHook::Create(); | |
209 return S_OK; | 242 return S_OK; |
210 } | 243 } |
211 | 244 |
245 HRESULT RdpClientWindow::OnAuthenticationWarningDismissed() { | |
246 LOG(WARNING) << "RDP: authentication warning has been dismissed."; | |
247 | |
248 window_activate_hook_ = NULL; | |
249 return S_OK; | |
250 } | |
251 | |
212 HRESULT RdpClientWindow::OnConnected() { | 252 HRESULT RdpClientWindow::OnConnected() { |
213 VLOG(1) << "RDP: successfully connected to " << server_endpoint_.ToString(); | 253 VLOG(1) << "RDP: successfully connected to " << server_endpoint_.ToString(); |
214 | 254 |
215 NotifyConnected(); | 255 NotifyConnected(); |
216 return S_OK; | 256 return S_OK; |
217 } | 257 } |
218 | 258 |
219 HRESULT RdpClientWindow::OnDisconnected(long reason) { | 259 HRESULT RdpClientWindow::OnDisconnected(long reason) { |
220 if (reason == kDisconnectReasonNoInfo || | 260 if (reason == kDisconnectReasonNoInfo || |
221 reason == kDisconnectReasonLocalNotError || | 261 reason == kDisconnectReasonLocalNotError || |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
273 } | 313 } |
274 | 314 |
275 void RdpClientWindow::NotifyDisconnected() { | 315 void RdpClientWindow::NotifyDisconnected() { |
276 if (event_handler_) { | 316 if (event_handler_) { |
277 EventHandler* event_handler = event_handler_; | 317 EventHandler* event_handler = event_handler_; |
278 event_handler_ = NULL; | 318 event_handler_ = NULL; |
279 event_handler->OnDisconnected(); | 319 event_handler->OnDisconnected(); |
280 } | 320 } |
281 } | 321 } |
282 | 322 |
323 scoped_refptr<RdpClientWindow::WindowHook> | |
324 RdpClientWindow::WindowHook::Create() { | |
325 scoped_refptr<WindowHook> window_hook = g_window_hook.Pointer()->Get(); | |
326 | |
327 if (!window_hook) | |
328 window_hook = new WindowHook(); | |
329 | |
330 return window_hook; | |
331 } | |
332 | |
333 RdpClientWindow::WindowHook::WindowHook() : hook_(NULL) { | |
334 DCHECK(!g_window_hook.Pointer()->Get()); | |
335 | |
336 // Install a window hook to be called on window activation. | |
337 hook_ = SetWindowsHookEx(WH_CBT, | |
338 &WindowHook::CloseWindowOnActivation, | |
339 NULL, | |
340 GetCurrentThreadId()); | |
341 // Without the hook installed, RdpClientWindow will not be able to cancel | |
342 // modal UI windows. This will block the UI message loop so it is better to | |
343 // terminate the process now. | |
344 CHECK(hook_); | |
345 | |
346 // Let CloseWindowOnActivation() to access the hook handle. | |
347 g_window_hook.Pointer()->Set(this); | |
348 } | |
349 | |
350 RdpClientWindow::WindowHook::~WindowHook() { | |
351 DCHECK(g_window_hook.Pointer()->Get() == this); | |
352 | |
353 g_window_hook.Pointer()->Set(NULL); | |
354 | |
355 BOOL result = UnhookWindowsHookEx(hook_); | |
356 DCHECK(result); | |
357 } | |
358 | |
359 // static | |
360 LRESULT CALLBACK RdpClientWindow::WindowHook::CloseWindowOnActivation( | |
361 int code, WPARAM wparam, LPARAM lparam) { | |
362 // Get the hook handle. | |
363 HHOOK hook = g_window_hook.Pointer()->Get()->hook_; | |
364 | |
365 if (code != HCBT_ACTIVATE) | |
366 return CallNextHookEx(hook, code, wparam, lparam); | |
367 | |
368 // Close the window once all pending window messages are processed. | |
369 HWND window = reinterpret_cast<HWND>(wparam); | |
370 LOG(WARNING) << "RDP: closing a window: " << std::hex << window << std::dec; | |
371 ::PostMessage(window, WM_CLOSE, 0, 0); | |
372 return 0; | |
373 } | |
374 | |
283 } // namespace remoting | 375 } // namespace remoting |
OLD | NEW |