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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « remoting/host/win/rdp_client_window.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: remoting/host/win/rdp_client_window.cc
diff --git a/remoting/host/win/rdp_client_window.cc b/remoting/host/win/rdp_client_window.cc
index fa02a80ca6a6d6ae74b34c516860b3e72d3b981e..1f81538e582fe8e8c19ca43408c79c3134923479 100644
--- a/remoting/host/win/rdp_client_window.cc
+++ b/remoting/host/win/rdp_client_window.cc
@@ -6,10 +6,16 @@
#include <wtsdefs.h>
+#include "base/lazy_instance.h"
#include "base/logging.h"
+#include "base/threading/thread_local.h"
#include "base/utf_string_conversions.h"
#include "base/win/scoped_bstr.h"
+namespace remoting {
+
+namespace {
+
// RDP connection disconnect reasons codes that should not be interpreted as
// errors.
const long kDisconnectReasonNoInfo = 0;
@@ -17,7 +23,34 @@ const long kDisconnectReasonLocalNotError = 1;
const long kDisconnectReasonRemoteByUser = 2;
const long kDisconnectReasonByServer = 3;
-namespace remoting {
+// Points to a per-thread instance of the window activation hook handle.
+base::LazyInstance<base::ThreadLocalPointer<RdpClientWindow::WindowHook> >
+ g_window_hook = LAZY_INSTANCE_INITIALIZER;
+
+} // namespace
+
+// Used to close any windows activated on a particular thread. It installs
+// a WH_CBT window hook to track window activations and close all activated
+// windows. There should be only one instance of |WindowHook| per thread
+// at any given moment.
+class RdpClientWindow::WindowHook
+ : public base::RefCounted<WindowHook> {
+ public:
+ static scoped_refptr<WindowHook> Create();
+
+ private:
+ friend class base::RefCounted<WindowHook>;
+
+ WindowHook();
+ virtual ~WindowHook();
+
+ static LRESULT CALLBACK CloseWindowOnActivation(
+ int code, WPARAM wparam, LPARAM lparam);
+
+ HHOOK hook_;
+
+ DISALLOW_COPY_AND_ASSIGN(WindowHook);
+};
RdpClientWindow::RdpClientWindow(const net::IPEndPoint& server_endpoint,
EventHandler* event_handler)
@@ -200,12 +233,19 @@ void RdpClientWindow::OnDestroy() {
}
HRESULT RdpClientWindow::OnAuthenticationWarningDisplayed() {
- LOG(ERROR) << "RDP: authentication warning is about to be shown. Closing "
- "the connection because the modal UI will block any further "
- "progress";
+ LOG(WARNING) << "RDP: authentication warning is about to be shown.";
- DestroyWindow();
- NotifyDisconnected();
+ // Hook window activation to cancel any modal UI shown by the RDP control.
+ // This does not affect creation of other instances of the RDP control on this
+ // thread because the RDP control's window is hidden and is not activated.
+ window_activate_hook_ = WindowHook::Create();
+ return S_OK;
+}
+
+HRESULT RdpClientWindow::OnAuthenticationWarningDismissed() {
+ LOG(WARNING) << "RDP: authentication warning has been dismissed.";
+
+ window_activate_hook_ = NULL;
return S_OK;
}
@@ -280,4 +320,56 @@ void RdpClientWindow::NotifyDisconnected() {
}
}
+scoped_refptr<RdpClientWindow::WindowHook>
+RdpClientWindow::WindowHook::Create() {
+ scoped_refptr<WindowHook> window_hook = g_window_hook.Pointer()->Get();
+
+ if (!window_hook)
+ window_hook = new WindowHook();
+
+ return window_hook;
+}
+
+RdpClientWindow::WindowHook::WindowHook() : hook_(NULL) {
+ DCHECK(!g_window_hook.Pointer()->Get());
+
+ // Install a window hook to be called on window activation.
+ hook_ = SetWindowsHookEx(WH_CBT,
+ &WindowHook::CloseWindowOnActivation,
+ NULL,
+ GetCurrentThreadId());
+ // Without the hook installed, RdpClientWindow will not be able to cancel
+ // modal UI windows. This will block the UI message loop so it is better to
+ // terminate the process now.
+ CHECK(hook_);
+
+ // Let CloseWindowOnActivation() to access the hook handle.
+ g_window_hook.Pointer()->Set(this);
+}
+
+RdpClientWindow::WindowHook::~WindowHook() {
+ DCHECK(g_window_hook.Pointer()->Get() == this);
+
+ g_window_hook.Pointer()->Set(NULL);
+
+ BOOL result = UnhookWindowsHookEx(hook_);
+ DCHECK(result);
+}
+
+// static
+LRESULT CALLBACK RdpClientWindow::WindowHook::CloseWindowOnActivation(
+ int code, WPARAM wparam, LPARAM lparam) {
+ // Get the hook handle.
+ HHOOK hook = g_window_hook.Pointer()->Get()->hook_;
+
+ if (code != HCBT_ACTIVATE)
+ return CallNextHookEx(hook, code, wparam, lparam);
+
+ // Close the window once all pending window messages are processed.
+ HWND window = reinterpret_cast<HWND>(wparam);
+ LOG(WARNING) << "RDP: closing a window: " << std::hex << window << std::dec;
+ ::PostMessage(window, WM_CLOSE, 0, 0);
+ return 0;
+}
+
} // namespace remoting
« 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