Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(164)

Side by Side Diff: remoting/host/win/rdp_client_window.cc

Issue 14261008: Cancel any modal UI shown by the RDP control. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: CR feedback. Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « remoting/host/win/rdp_client_window.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 activation hook handle.
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
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
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 of other instances of the RDP control on this
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
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
OLDNEW
« no previous file with comments | « remoting/host/win/rdp_client_window.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698