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

Unified Diff: remoting/host/plugin/daemon_controller_win.cc

Issue 10161034: Making sure that UAC promts fired by the Chromoting plugin get focus (instead of being shown in the… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: A fixup Created 8 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
Index: remoting/host/plugin/daemon_controller_win.cc
diff --git a/remoting/host/plugin/daemon_controller_win.cc b/remoting/host/plugin/daemon_controller_win.cc
index 678b695629c18124c8affcf9c7ff782832697494..446bcaf813ff840f303b740bafe34d57627e3615 100644
--- a/remoting/host/plugin/daemon_controller_win.cc
+++ b/remoting/host/plugin/daemon_controller_win.cc
@@ -18,6 +18,8 @@
#include "base/string16.h"
#include "base/stringize_macros.h"
#include "base/threading/thread.h"
+#include "base/time.h"
+#include "base/timer.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "base/win/scoped_bstr.h"
@@ -37,7 +39,7 @@ namespace remoting {
namespace {
-// The COM elevation moniker for the elevated controller.
+// The COM elevation moniker for the Elevated Controller.
const char16 kDaemonControllerElevationMoniker[] =
TO_L_STRING("Elevation:Administrator!new:")
TO_L_STRING("ChromotingElevatedController.ElevatedController");
@@ -45,6 +47,9 @@ const char16 kDaemonControllerElevationMoniker[] =
// Name of the Daemon Controller's worker thread.
const char kDaemonControllerThreadName[] = "Daemon Controller thread";
+// The maximum interval between showing UAC prompts.
+const int kUacTimeoutSec = 15 * 60;
Jamie 2012/04/25 21:20:37 Is this strictly needed as part of this CL? It fee
alexeypa (please no reviews) 2012/04/25 21:59:24 I'll move it to a separate CL.
+
// A base::Thread implementation that initializes COM on the new thread.
class ComThread : public base::Thread {
public:
@@ -53,7 +58,8 @@ class ComThread : public base::Thread {
// Activates an elevated instance of the controller and returns the pointer
// to the control interface in |control_out|. This class keeps the ownership
// of the pointer so the caller should not call call AddRef() or Release().
- HRESULT ActivateElevatedController(IDaemonControl** control_out);
+ HRESULT ActivateElevatedController(void* window_handle,
Jamie 2012/04/25 21:20:37 HWND?
alexeypa (please no reviews) 2012/04/25 21:59:24 Done.
+ IDaemonControl** control_out);
bool Start();
@@ -61,8 +67,13 @@ class ComThread : public base::Thread {
virtual void Init() OVERRIDE;
virtual void CleanUp() OVERRIDE;
+ void ReleaseElevatedController();
+
ScopedComPtr<IDaemonControl> control_;
+ // This timer is used to release |control_| after a timeout.
+ base::OneShotTimer<ComThread> release_timer_;
+
DISALLOW_COPY_AND_ASSIGN(ComThread);
};
@@ -79,6 +90,7 @@ class DaemonControllerWin : public remoting::DaemonController {
virtual void UpdateConfig(scoped_ptr<base::DictionaryValue> config,
const CompletionCallback& done_callback) OVERRIDE;
virtual void Stop(const CompletionCallback& done_callback) OVERRIDE;
+ virtual void SetWindow(void* window_handle) OVERRIDE;
private:
// Converts a Windows service status code to a Daemon state.
@@ -106,6 +118,10 @@ class DaemonControllerWin : public remoting::DaemonController {
void DoUpdateConfig(scoped_ptr<base::DictionaryValue> config,
const CompletionCallback& done_callback);
void DoStop(const CompletionCallback& done_callback);
+ void DoSetWindow(void* window_handle);
+
+ // Handle of the plugin window.
+ void* window_handle_;
Jamie 2012/04/25 21:20:37 Store as an HWND?
alexeypa (please no reviews) 2012/04/25 21:59:24 Done.
// The worker thread used for servicing long running operations.
ComThread worker_thread_;
@@ -118,24 +134,17 @@ class DaemonControllerWin : public remoting::DaemonController {
ComThread::ComThread(const char* name) : base::Thread(name), control_(NULL) {
}
-void ComThread::Init() {
- CoInitialize(NULL);
-}
-
-void ComThread::CleanUp() {
- control_.Release();
- CoUninitialize();
-}
-
HRESULT ComThread::ActivateElevatedController(
+ void* window_handle,
IDaemonControl** control_out) {
- // Chache the instance of Elevated Controller to prevent a UAC prompt on every
- // operation.
+ // Cache an instance of the Elevated Controller to prevent a UAC prompt on
+ // every operation.
if (control_.get() == NULL) {
BIND_OPTS3 bind_options;
memset(&bind_options, 0, sizeof(bind_options));
bind_options.cbStruct = sizeof(bind_options);
- bind_options.hwnd = NULL;
+ bind_options.hwnd =
+ GetTopLevelWindow(reinterpret_cast<HWND>(window_handle));
bind_options.dwClassContext = CLSCTX_LOCAL_SERVER;
HRESULT hr = ::CoGetObject(
@@ -146,6 +155,11 @@ HRESULT ComThread::ActivateElevatedController(
if (FAILED(hr)) {
return hr;
}
+
+ // Release |control_| upon expiration of the timeout.
+ release_timer_.Start(FROM_HERE,
+ base::TimeDelta::FromSeconds(kUacTimeoutSec),
+ this, &ComThread::ReleaseElevatedController);
}
*control_out = control_.get();
@@ -158,8 +172,22 @@ bool ComThread::Start() {
return StartWithOptions(thread_options);
}
+void ComThread::Init() {
+ CoInitialize(NULL);
+}
+
+void ComThread::CleanUp() {
+ ReleaseElevatedController();
+ CoUninitialize();
+}
+
+void ComThread::ReleaseElevatedController() {
+ control_.Release();
+}
+
Jamie 2012/04/25 21:20:37 It's not clear to me which of the previous functio
alexeypa (please no reviews) 2012/04/25 21:59:24 I'll move the timeout change to a separate CL.
DaemonControllerWin::DaemonControllerWin()
- : worker_thread_(kDaemonControllerThreadName) {
+ : window_handle_(NULL),
+ worker_thread_(kDaemonControllerThreadName) {
if (!worker_thread_.Start()) {
LOG(FATAL) << "Failed to start the Daemon Controller worker thread.";
}
@@ -227,6 +255,13 @@ void DaemonControllerWin::Stop(const CompletionCallback& done_callback) {
done_callback));
}
+void DaemonControllerWin::SetWindow(void* window_handle) {
+ worker_thread_.message_loop_proxy()->PostTask(
+ FROM_HERE, base::Bind(
+ &DaemonControllerWin::DoSetWindow, base::Unretained(this),
+ window_handle));
+}
+
// static
remoting::DaemonController::State DaemonControllerWin::ConvertToDaemonState(
DWORD service_state) {
@@ -367,7 +402,8 @@ void DaemonControllerWin::DoInstallAsNeededAndStart(
DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
IDaemonControl* control = NULL;
- HRESULT hr = worker_thread_.ActivateElevatedController(&control);
+ HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_,
+ &control);
// Just configure and start the Daemon Controller if it is installed already.
if (SUCCEEDED(hr)) {
@@ -378,6 +414,7 @@ void DaemonControllerWin::DoInstallAsNeededAndStart(
// Otherwise, install it if its COM registration entry is missing.
if (hr == CO_E_CLASSSTRING) {
scoped_ptr<DaemonInstallerWin> installer = DaemonInstallerWin::Create(
+ window_handle_,
base::Bind(&DaemonControllerWin::OnInstallationComplete,
base::Unretained(this),
base::Passed(&config),
@@ -400,7 +437,8 @@ void DaemonControllerWin::DoSetConfigAndStart(
DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
IDaemonControl* control = NULL;
- HRESULT hr = worker_thread_.ActivateElevatedController(&control);
+ HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_,
+ &control);
if (FAILED(hr)) {
done_callback.Run(HResultToAsyncResult(hr));
return;
@@ -435,7 +473,8 @@ void DaemonControllerWin::DoUpdateConfig(
DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
IDaemonControl* control = NULL;
- HRESULT hr = worker_thread_.ActivateElevatedController(&control);
+ HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_,
+ &control);
if (FAILED(hr)) {
done_callback.Run(HResultToAsyncResult(hr));
return;
@@ -459,7 +498,8 @@ void DaemonControllerWin::DoStop(const CompletionCallback& done_callback) {
DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
IDaemonControl* control = NULL;
- HRESULT hr = worker_thread_.ActivateElevatedController(&control);
+ HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_,
+ &control);
if (FAILED(hr)) {
done_callback.Run(HResultToAsyncResult(hr));
return;
@@ -469,6 +509,10 @@ void DaemonControllerWin::DoStop(const CompletionCallback& done_callback) {
done_callback.Run(HResultToAsyncResult(hr));
}
+void DaemonControllerWin::DoSetWindow(void* window_handle) {
+ window_handle_ = window_handle;
+}
+
} // namespace
scoped_ptr<DaemonController> remoting::DaemonController::Create() {

Powered by Google App Engine
This is Rietveld 408576698