Chromium Code Reviews| 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() { |