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 49b1809b831ebb2ea27ee93ac5379812e3c49bc8..77ff89f9bfed85985a9ac1d2199cc2bf10fc73cd 100644 |
| --- a/remoting/host/plugin/daemon_controller_win.cc |
| +++ b/remoting/host/plugin/daemon_controller_win.cc |
| @@ -55,25 +55,12 @@ class ComThread : public base::Thread { |
| public: |
| explicit ComThread(const char* name); |
| - // 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(HWND window_handle, |
| - IDaemonControl** control_out); |
| - |
| bool Start(); |
| protected: |
| 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); |
| }; |
| @@ -93,11 +80,12 @@ class DaemonControllerWin : public remoting::DaemonController { |
| virtual void SetWindow(void* window_handle) OVERRIDE; |
| private: |
| - // Converts a Windows service status code to a Daemon state. |
| - static State ConvertToDaemonState(DWORD service_state); |
| + // Activates an elevated instance of the controller and stores the pointer |
|
simonmorris
2012/05/01 17:29:12
"...and caches it." Or "stores" it?
alexeypa (please no reviews)
2012/05/01 18:00:01
Done.
|
| + // in |control_|. |
| + HRESULT ActivateElevatedController(); |
| - // Converts HRESULT to the AsyncResult. |
| - static AsyncResult HResultToAsyncResult(HRESULT hr); |
| + // Releases the cached instance of the evelated controller. |
|
simonmorris
2012/05/01 17:29:12
evelated -> elevated
cached -> stored?
alexeypa (please no reviews)
2012/05/01 18:00:01
Done.
|
| + void ReleaseElevatedController(); |
| // Procedes with the daemon configuration if the installation succeeded, |
| // otherwise reports the error. |
| @@ -112,6 +100,12 @@ class DaemonControllerWin : public remoting::DaemonController { |
| static void ConfigToString(const base::DictionaryValue& config, |
| ScopedBstr* out); |
| + // Converts a Windows service status code to a Daemon state. |
| + static State ConvertToDaemonState(DWORD service_state); |
| + |
| + // Converts HRESULT to the AsyncResult. |
| + static AsyncResult HResultToAsyncResult(HRESULT hr); |
| + |
| // The functions that actually do the work. They should be called in |
| // the context of |worker_thread_|; |
| void DoGetConfig(const GetConfigCallback& callback); |
| @@ -124,6 +118,11 @@ class DaemonControllerWin : public remoting::DaemonController { |
| void DoStop(const CompletionCallback& done_callback); |
| void DoSetWindow(void* window_handle); |
| + ScopedComPtr<IDaemonControl> control_; |
| + |
| + // This timer is used to release |control_| after a timeout. |
| + scoped_ptr<base::OneShotTimer<DaemonControllerWin> > release_timer_; |
| + |
| // Handle of the plugin window. |
| HWND window_handle_; |
| @@ -135,38 +134,7 @@ class DaemonControllerWin : public remoting::DaemonController { |
| DISALLOW_COPY_AND_ASSIGN(DaemonControllerWin); |
| }; |
| -ComThread::ComThread(const char* name) : base::Thread(name), control_(NULL) { |
| -} |
| - |
| -HRESULT ComThread::ActivateElevatedController( |
| - HWND window_handle, |
| - IDaemonControl** control_out) { |
| - // 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 = GetTopLevelWindow(window_handle); |
| - bind_options.dwClassContext = CLSCTX_LOCAL_SERVER; |
| - |
| - HRESULT hr = ::CoGetObject( |
| - kDaemonControllerElevationMoniker, |
| - &bind_options, |
| - IID_IDaemonControl, |
| - control_.ReceiveVoid()); |
| - 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(); |
| - return S_OK; |
| +ComThread::ComThread(const char* name) : base::Thread(name) { |
| } |
| bool ComThread::Start() { |
| @@ -180,14 +148,9 @@ void ComThread::Init() { |
| } |
| void ComThread::CleanUp() { |
| - ReleaseElevatedController(); |
| CoUninitialize(); |
| } |
| -void ComThread::ReleaseElevatedController() { |
| - control_.Release(); |
| -} |
| - |
| DaemonControllerWin::DaemonControllerWin() |
| : window_handle_(NULL), |
| worker_thread_(kDaemonControllerThreadName) { |
| @@ -197,6 +160,11 @@ DaemonControllerWin::DaemonControllerWin() |
| } |
| DaemonControllerWin::~DaemonControllerWin() { |
| + // Clean up resources allocated on the worker thread. |
| + worker_thread_.message_loop_proxy()->PostTask( |
| + FROM_HERE, |
| + base::Bind(&DaemonControllerWin::ReleaseElevatedController, |
| + base::Unretained(this))); |
|
simonmorris
2012/05/01 17:29:12
How does this guarantee that ReleaseElevatedContro
alexeypa (please no reviews)
2012/05/01 18:00:01
worker_thread_.Stop() waits synchronously until al
|
| worker_thread_.Stop(); |
| } |
| @@ -265,40 +233,43 @@ void DaemonControllerWin::SetWindow(void* window_handle) { |
| window_handle)); |
| } |
| -// static |
| -remoting::DaemonController::State DaemonControllerWin::ConvertToDaemonState( |
| - DWORD service_state) { |
| - switch (service_state) { |
| - case SERVICE_RUNNING: |
| - return STATE_STARTED; |
| - |
| - case SERVICE_CONTINUE_PENDING: |
| - case SERVICE_START_PENDING: |
| - return STATE_STARTING; |
| - break; |
| +HRESULT DaemonControllerWin::ActivateElevatedController() { |
| + DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
| - case SERVICE_PAUSE_PENDING: |
| - case SERVICE_STOP_PENDING: |
| - return STATE_STOPPING; |
| - break; |
| + // 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 = GetTopLevelWindow(window_handle_); |
| + bind_options.dwClassContext = CLSCTX_LOCAL_SERVER; |
| - case SERVICE_PAUSED: |
| - case SERVICE_STOPPED: |
| - return STATE_STOPPED; |
| - break; |
| + HRESULT hr = ::CoGetObject( |
| + kDaemonControllerElevationMoniker, |
| + &bind_options, |
| + IID_IDaemonControl, |
| + control_.ReceiveVoid()); |
| + if (FAILED(hr)) { |
| + return hr; |
| + } |
| - default: |
| - NOTREACHED(); |
| - return STATE_UNKNOWN; |
| + // Release |control_| upon expiration of the timeout. |
| + release_timer_.reset(new base::OneShotTimer<DaemonControllerWin>()); |
|
Sergey Ulanov
2012/05/01 17:26:05
Maybe use DelayTimer here and reset it ever time t
alexeypa (please no reviews)
2012/05/01 17:32:30
I intentionally implemented it this way. I.e. it i
|
| + release_timer_->Start(FROM_HERE, |
| + base::TimeDelta::FromSeconds(kUacTimeoutSec), |
| + this, |
| + &DaemonControllerWin::ReleaseElevatedController); |
| } |
| + |
| + return S_OK; |
| } |
| -// static |
| -DaemonController::AsyncResult DaemonControllerWin::HResultToAsyncResult( |
| - HRESULT hr) { |
| - // TODO(sergeyu): Report other errors to the webapp once it knows |
| - // how to handle them. |
| - return FAILED(hr) ? RESULT_FAILED : RESULT_OK; |
| +void DaemonControllerWin::ReleaseElevatedController() { |
| + DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
| + |
| + control_.Release(); |
| + release_timer_.reset(); |
| } |
| void DaemonControllerWin::OnInstallationComplete( |
| @@ -346,6 +317,7 @@ DWORD DaemonControllerWin::OpenService(ScopedScHandle* service_out) { |
| return ERROR_SUCCESS; |
| } |
| +// static |
| void DaemonControllerWin::ConfigToString(const base::DictionaryValue& config, |
| ScopedBstr* out) { |
| std::string config_str; |
| @@ -354,6 +326,42 @@ void DaemonControllerWin::ConfigToString(const base::DictionaryValue& config, |
| out->Swap(config_scoped_bstr); |
| } |
| +// static |
| +remoting::DaemonController::State DaemonControllerWin::ConvertToDaemonState( |
| + DWORD service_state) { |
| + switch (service_state) { |
| + case SERVICE_RUNNING: |
| + return STATE_STARTED; |
| + |
| + case SERVICE_CONTINUE_PENDING: |
| + case SERVICE_START_PENDING: |
| + return STATE_STARTING; |
| + break; |
| + |
| + case SERVICE_PAUSE_PENDING: |
| + case SERVICE_STOP_PENDING: |
| + return STATE_STOPPING; |
| + break; |
| + |
| + case SERVICE_PAUSED: |
| + case SERVICE_STOPPED: |
| + return STATE_STOPPED; |
| + break; |
| + |
| + default: |
| + NOTREACHED(); |
| + return STATE_UNKNOWN; |
| + } |
| +} |
| + |
| +// static |
| +DaemonController::AsyncResult DaemonControllerWin::HResultToAsyncResult( |
| + HRESULT hr) { |
| + // TODO(sergeyu): Report other errors to the webapp once it knows |
| + // how to handle them. |
| + return FAILED(hr) ? RESULT_FAILED : RESULT_OK; |
| +} |
| + |
| void DaemonControllerWin::DoGetConfig(const GetConfigCallback& callback) { |
| DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
| @@ -412,11 +420,8 @@ void DaemonControllerWin::DoInstallAsNeededAndStart( |
| const CompletionCallback& done_callback) { |
| DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
| - IDaemonControl* control = NULL; |
| - HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_, |
| - &control); |
| - |
| - // Just configure and start the Daemon Controller if it is installed already. |
| + // Configure and start the Daemon Controller if it is installed already. |
| + HRESULT hr = ActivateElevatedController(); |
| if (SUCCEEDED(hr)) { |
| DoSetConfigAndStart(config.Pass(), done_callback); |
| return; |
| @@ -447,9 +452,7 @@ void DaemonControllerWin::DoSetConfigAndStart( |
| const CompletionCallback& done_callback) { |
| DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
| - IDaemonControl* control = NULL; |
| - HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_, |
| - &control); |
| + HRESULT hr = ActivateElevatedController(); |
| if (FAILED(hr)) { |
| done_callback.Run(HResultToAsyncResult(hr)); |
| return; |
| @@ -463,14 +466,14 @@ void DaemonControllerWin::DoSetConfigAndStart( |
| return; |
| } |
| - hr = control->SetConfig(config_str); |
| + hr = control_->SetConfig(config_str); |
| if (FAILED(hr)) { |
| done_callback.Run(HResultToAsyncResult(hr)); |
| return; |
| } |
| // Start daemon. |
| - hr = control->StartDaemon(); |
| + hr = control_->StartDaemon(); |
| done_callback.Run(HResultToAsyncResult(hr)); |
| } |
| @@ -479,9 +482,7 @@ void DaemonControllerWin::DoUpdateConfig( |
| const CompletionCallback& done_callback) { |
| DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
| - IDaemonControl* control = NULL; |
| - HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_, |
| - &control); |
| + HRESULT hr = ActivateElevatedController(); |
| if (FAILED(hr)) { |
| done_callback.Run(HResultToAsyncResult(hr)); |
| return; |
| @@ -495,22 +496,20 @@ void DaemonControllerWin::DoUpdateConfig( |
| return; |
| } |
| - hr = control->UpdateConfig(config_str); |
| + hr = control_->UpdateConfig(config_str); |
| done_callback.Run(HResultToAsyncResult(hr)); |
| } |
| void DaemonControllerWin::DoStop(const CompletionCallback& done_callback) { |
| DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
| - IDaemonControl* control = NULL; |
| - HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_, |
| - &control); |
| + HRESULT hr = ActivateElevatedController(); |
| if (FAILED(hr)) { |
| done_callback.Run(HResultToAsyncResult(hr)); |
| return; |
| } |
| - hr = control->StopDaemon(); |
| + hr = control_->StopDaemon(); |
| done_callback.Run(HResultToAsyncResult(hr)); |
| } |