Chromium Code Reviews| 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 |