Index: remoting/host/setup/daemon_controller_delegate_win.cc |
diff --git a/remoting/host/setup/daemon_controller_win.cc b/remoting/host/setup/daemon_controller_delegate_win.cc |
similarity index 45% |
rename from remoting/host/setup/daemon_controller_win.cc |
rename to remoting/host/setup/daemon_controller_delegate_win.cc |
index e4b8896f8968e430a35156ef5869fbd2a9d209c3..5b14ff7460a3741729a6a7a336d3ef8fc4e1c1cb 100644 |
--- a/remoting/host/setup/daemon_controller_win.cc |
+++ b/remoting/host/setup/daemon_controller_delegate_win.cc |
@@ -2,20 +2,18 @@ |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-#include "remoting/host/setup/daemon_controller.h" |
+#include "remoting/host/setup/daemon_controller_delegate_win.h" |
#include "base/basictypes.h" |
#include "base/bind.h" |
#include "base/bind_helpers.h" |
#include "base/compiler_specific.h" |
-#include "base/file_util.h" |
-#include "base/files/file_path.h" |
#include "base/json/json_reader.h" |
#include "base/json/json_writer.h" |
#include "base/logging.h" |
#include "base/strings/string16.h" |
#include "base/strings/utf_string_conversions.h" |
-#include "base/threading/thread.h" |
+#include "base/thread_task_runner_handle.h" |
#include "base/time/time.h" |
#include "base/timer/timer.h" |
#include "base/values.h" |
@@ -45,9 +43,6 @@ const wchar_t kDaemonControllerElevationMoniker[] = |
L"Elevation:Administrator!new:" |
L"ChromotingElevatedController.ElevatedController"; |
-// Name of the Daemon Controller's worker thread. |
-const char kDaemonControllerThreadName[] = "Daemon Controller thread"; |
- |
// The maximum duration of keeping a reference to a privileged instance of |
// the Daemon Controller. This effectively reduces number of UAC prompts a user |
// sees. |
@@ -60,119 +55,92 @@ const int kPrivilegedTimeoutSec = 5 * 60; |
// that the old binary will go away sooner. |
const int kUnprivilegedTimeoutSec = 60; |
-class DaemonControllerWin : public remoting::DaemonController { |
- public: |
- DaemonControllerWin(); |
- virtual ~DaemonControllerWin(); |
- |
- virtual State GetState() OVERRIDE; |
- virtual void GetConfig(const GetConfigCallback& callback) OVERRIDE; |
- virtual void SetConfigAndStart( |
- scoped_ptr<base::DictionaryValue> config, |
- bool consent, |
- const CompletionCallback& done) OVERRIDE; |
- 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; |
- virtual void GetVersion(const GetVersionCallback& done_callback) OVERRIDE; |
- virtual void GetUsageStatsConsent( |
- const GetUsageStatsConsentCallback& done) OVERRIDE; |
- |
- private: |
- // Activates an unprivileged instance of the daemon controller and caches it. |
- HRESULT ActivateController(); |
- |
- // Activates an instance of the daemon controller and caches it. If COM |
- // Elevation is supported (Vista+) the activated instance is elevated, |
- // otherwise it is activated under credentials of the caller. |
- HRESULT ActivateElevatedController(); |
- |
- // Releases the cached instance of the controller. |
- void ReleaseController(); |
- |
- // Procedes with the daemon configuration if the installation succeeded, |
- // otherwise reports the error. |
- void OnInstallationComplete(scoped_ptr<base::DictionaryValue> config, |
- bool consent, |
- const CompletionCallback& done, |
- HRESULT result); |
- |
- // Opens the Chromoting service returning its handle in |service_out|. |
- DWORD OpenService(ScopedScHandle* service_out); |
- |
- // Converts a config dictionary to a scoped BSTR. |
- 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); |
- void DoInstallAsNeededAndStart(scoped_ptr<base::DictionaryValue> config, |
- bool consent, |
- const CompletionCallback& done_callback); |
- void DoSetConfigAndStart(scoped_ptr<base::DictionaryValue> config, |
- bool consent, |
- const CompletionCallback& done); |
- void DoUpdateConfig(scoped_ptr<base::DictionaryValue> config, |
- const CompletionCallback& done_callback); |
- void DoStop(const CompletionCallback& done_callback); |
- void DoSetWindow(void* window_handle); |
- void DoGetVersion(const GetVersionCallback& callback); |
- void DoGetUsageStatsConsent( |
- const GetUsageStatsConsentCallback& done); |
- |
- // |control_| and |control2_| hold references to an instance of the daemon |
- // controller to prevent a UAC prompt on every operation. |
- ScopedComPtr<IDaemonControl> control_; |
- ScopedComPtr<IDaemonControl2> control2_; |
- |
- // True if |control_| holds a reference to an elevated instance of the daemon |
- // controller. |
- bool control_is_elevated_; |
- |
- // 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_; |
- |
- // The worker thread used for servicing long running operations. |
- base::Thread worker_thread_; |
- |
- scoped_ptr<DaemonInstallerWin> installer_; |
- |
- DISALLOW_COPY_AND_ASSIGN(DaemonControllerWin); |
-}; |
- |
-DaemonControllerWin::DaemonControllerWin() |
- : control_is_elevated_(false), |
- window_handle_(NULL), |
- worker_thread_(kDaemonControllerThreadName) { |
- worker_thread_.init_com_with_mta(false); |
- if (!worker_thread_.Start()) { |
- LOG(FATAL) << "Failed to start the Daemon Controller worker thread."; |
+void ConfigToString(const base::DictionaryValue& config, ScopedBstr* out) { |
+ std::string config_str; |
+ base::JSONWriter::Write(&config, &config_str); |
+ ScopedBstr config_scoped_bstr(UTF8ToUTF16(config_str).c_str()); |
+ out->Swap(config_scoped_bstr); |
+} |
+ |
+DaemonController::State ConvertToDaemonState(DWORD service_state) { |
+ switch (service_state) { |
+ case SERVICE_RUNNING: |
+ return DaemonController::STATE_STARTED; |
+ |
+ case SERVICE_CONTINUE_PENDING: |
+ case SERVICE_START_PENDING: |
+ return DaemonController::STATE_STARTING; |
+ break; |
+ |
+ case SERVICE_PAUSE_PENDING: |
+ case SERVICE_STOP_PENDING: |
+ return DaemonController::STATE_STOPPING; |
+ break; |
+ |
+ case SERVICE_PAUSED: |
+ case SERVICE_STOPPED: |
+ return DaemonController::STATE_STOPPED; |
+ break; |
+ |
+ default: |
+ NOTREACHED(); |
+ return DaemonController::STATE_UNKNOWN; |
} |
} |
-DaemonControllerWin::~DaemonControllerWin() { |
- // Clean up resources allocated on the worker thread. |
- worker_thread_.message_loop_proxy()->PostTask( |
- FROM_HERE, |
- base::Bind(&DaemonControllerWin::ReleaseController, |
- base::Unretained(this))); |
- worker_thread_.Stop(); |
+DWORD OpenService(ScopedScHandle* service_out) { |
+ // Open the service and query its current state. |
+ ScopedScHandle scmanager( |
+ ::OpenSCManagerW(NULL, SERVICES_ACTIVE_DATABASE, |
+ SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE)); |
+ if (!scmanager.IsValid()) { |
+ DWORD error = GetLastError(); |
+ LOG_GETLASTERROR(ERROR) |
+ << "Failed to connect to the service control manager"; |
+ return error; |
+ } |
+ |
+ ScopedScHandle service( |
+ ::OpenServiceW(scmanager, kWindowsServiceName, SERVICE_QUERY_STATUS)); |
+ if (!service.IsValid()) { |
+ DWORD error = GetLastError(); |
+ if (error != ERROR_SERVICE_DOES_NOT_EXIST) { |
+ LOG_GETLASTERROR(ERROR) |
+ << "Failed to open to the '" << kWindowsServiceName << "' service"; |
+ } |
+ return error; |
+ } |
+ |
+ service_out->Set(service.Take()); |
+ return ERROR_SUCCESS; |
+} |
+ |
+DaemonController::AsyncResult HResultToAsyncResult( |
+ HRESULT hr) { |
+ if (SUCCEEDED(hr)) { |
+ return DaemonController::RESULT_OK; |
+ } else if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED)) { |
+ return DaemonController::RESULT_CANCELLED; |
+ } else { |
+ // TODO(sergeyu): Report other errors to the webapp once it knows |
+ // how to handle them. |
+ return DaemonController::RESULT_FAILED; |
+ } |
} |
-remoting::DaemonController::State DaemonControllerWin::GetState() { |
+} // namespace |
+ |
+DaemonControllerDelegateWin::DaemonControllerDelegateWin() |
+ : control_is_elevated_(false), |
+ window_handle_(NULL) { |
+} |
+ |
+DaemonControllerDelegateWin::~DaemonControllerDelegateWin() { |
+} |
+ |
+DaemonController::State DaemonControllerDelegateWin::GetState() { |
if (base::win::GetVersion() < base::win::VERSION_XP) { |
- return STATE_NOT_IMPLEMENTED; |
+ return DaemonController::STATE_NOT_IMPLEMENTED; |
} |
// TODO(alexeypa): Make the thread alertable, so we can switch to APC |
// notifications rather than polling. |
@@ -188,76 +156,167 @@ remoting::DaemonController::State DaemonControllerWin::GetState() { |
LOG_GETLASTERROR(ERROR) |
<< "Failed to query the state of the '" << kWindowsServiceName |
<< "' service"; |
- return STATE_UNKNOWN; |
+ return DaemonController::STATE_UNKNOWN; |
} |
break; |
} |
case ERROR_SERVICE_DOES_NOT_EXIST: |
- return STATE_NOT_INSTALLED; |
+ return DaemonController::STATE_NOT_INSTALLED; |
default: |
- return STATE_UNKNOWN; |
+ return DaemonController::STATE_UNKNOWN; |
} |
} |
-void DaemonControllerWin::GetConfig(const GetConfigCallback& callback) { |
- worker_thread_.message_loop_proxy()->PostTask( |
- FROM_HERE, |
- base::Bind(&DaemonControllerWin::DoGetConfig, |
- base::Unretained(this), callback)); |
+scoped_ptr<base::DictionaryValue> DaemonControllerDelegateWin::GetConfig() { |
+ // Configure and start the Daemon Controller if it is installed already. |
+ HRESULT hr = ActivateController(); |
+ if (FAILED(hr)) |
+ return scoped_ptr<base::DictionaryValue>(); |
+ |
+ // Get the host configuration. |
+ ScopedBstr host_config; |
+ hr = control_->GetConfig(host_config.Receive()); |
+ if (FAILED(hr)) |
+ return scoped_ptr<base::DictionaryValue>(); |
+ |
+ // Parse the string into a dictionary. |
+ string16 file_content(static_cast<BSTR>(host_config), host_config.Length()); |
+ scoped_ptr<base::Value> config( |
+ base::JSONReader::Read(UTF16ToUTF8(file_content), |
+ base::JSON_ALLOW_TRAILING_COMMAS)); |
+ |
+ if (!config || config->GetType() != base::Value::TYPE_DICTIONARY) |
+ return scoped_ptr<base::DictionaryValue>(); |
+ |
+ return scoped_ptr<base::DictionaryValue>( |
+ static_cast<base::DictionaryValue*>(config.release())); |
} |
-void DaemonControllerWin::SetConfigAndStart( |
+void DaemonControllerDelegateWin::SetConfigAndStart( |
scoped_ptr<base::DictionaryValue> config, |
bool consent, |
- const CompletionCallback& done) { |
- worker_thread_.message_loop_proxy()->PostTask( |
- FROM_HERE, base::Bind( |
- &DaemonControllerWin::DoInstallAsNeededAndStart, |
- base::Unretained(this), base::Passed(&config), consent, done)); |
+ const DaemonController::CompletionCallback& done) { |
+ // Configure and start the Daemon Controller if it is installed already. |
+ HRESULT hr = ActivateElevatedController(); |
+ if (SUCCEEDED(hr)) { |
+ OnInstallationComplete(config.Pass(), consent, done, S_OK); |
+ return; |
+ } |
+ |
+ // Otherwise, install it if its COM registration entry is missing. |
+ if (hr == CO_E_CLASSSTRING) { |
+ DCHECK(!installer_); |
+ |
+ installer_ = DaemonInstallerWin::Create( |
+ GetTopLevelWindow(window_handle_), |
+ base::Bind(&DaemonControllerDelegateWin::OnInstallationComplete, |
+ base::Unretained(this), |
+ base::Passed(&config), |
+ consent, |
+ done)); |
+ installer_->Install(); |
+ return; |
+ } |
+ |
+ LOG(ERROR) << "Failed to initiate the Chromoting Host installation " |
+ << "(error: 0x" << std::hex << hr << std::dec << ")."; |
+ done.Run(HResultToAsyncResult(hr)); |
} |
-void DaemonControllerWin::UpdateConfig( |
+void DaemonControllerDelegateWin::UpdateConfig( |
scoped_ptr<base::DictionaryValue> config, |
- const CompletionCallback& done_callback) { |
- worker_thread_.message_loop_proxy()->PostTask( |
- FROM_HERE, base::Bind( |
- &DaemonControllerWin::DoUpdateConfig, |
- base::Unretained(this), base::Passed(&config), done_callback)); |
-} |
+ const DaemonController::CompletionCallback& done) { |
+ HRESULT hr = ActivateElevatedController(); |
+ if (FAILED(hr)) { |
+ done.Run(HResultToAsyncResult(hr)); |
+ return; |
+ } |
-void DaemonControllerWin::Stop(const CompletionCallback& done_callback) { |
- worker_thread_.message_loop_proxy()->PostTask( |
- FROM_HERE, base::Bind( |
- &DaemonControllerWin::DoStop, base::Unretained(this), |
- done_callback)); |
+ // Update the configuration. |
+ ScopedBstr config_str(NULL); |
+ ConfigToString(*config, &config_str); |
+ if (config_str == NULL) { |
+ done.Run(HResultToAsyncResult(E_OUTOFMEMORY)); |
+ return; |
+ } |
+ |
+ // Make sure that the PIN confirmation dialog is focused properly. |
+ hr = control_->SetOwnerWindow( |
+ reinterpret_cast<LONG_PTR>(GetTopLevelWindow(window_handle_))); |
+ if (FAILED(hr)) { |
+ done.Run(HResultToAsyncResult(hr)); |
+ return; |
+ } |
+ |
+ hr = control_->UpdateConfig(config_str); |
+ done.Run(HResultToAsyncResult(hr)); |
} |
-void DaemonControllerWin::SetWindow(void* window_handle) { |
- worker_thread_.message_loop_proxy()->PostTask( |
- FROM_HERE, base::Bind( |
- &DaemonControllerWin::DoSetWindow, base::Unretained(this), |
- window_handle)); |
+void DaemonControllerDelegateWin::Stop( |
+ const DaemonController::CompletionCallback& done) { |
+ HRESULT hr = ActivateElevatedController(); |
+ if (SUCCEEDED(hr)) |
+ hr = control_->StopDaemon(); |
+ |
+ done.Run(HResultToAsyncResult(hr)); |
} |
-void DaemonControllerWin::GetVersion(const GetVersionCallback& callback) { |
- worker_thread_.message_loop_proxy()->PostTask( |
- FROM_HERE, |
- base::Bind(&DaemonControllerWin::DoGetVersion, |
- base::Unretained(this), callback)); |
+void DaemonControllerDelegateWin::SetWindow(void* window_handle) { |
+ window_handle_ = reinterpret_cast<HWND>(window_handle); |
} |
-void DaemonControllerWin::GetUsageStatsConsent( |
- const GetUsageStatsConsentCallback& done) { |
- worker_thread_.message_loop_proxy()->PostTask( |
- FROM_HERE, |
- base::Bind(&DaemonControllerWin::DoGetUsageStatsConsent, |
- base::Unretained(this), done)); |
+std::string DaemonControllerDelegateWin::GetVersion() { |
+ // Configure and start the Daemon Controller if it is installed already. |
+ HRESULT hr = ActivateController(); |
+ if (FAILED(hr)) |
+ return std::string(); |
+ |
+ // Get the version string. |
+ ScopedBstr version; |
+ hr = control_->GetVersion(version.Receive()); |
+ if (FAILED(hr)) |
+ return std::string(); |
+ |
+ return UTF16ToUTF8(string16(static_cast<BSTR>(version), version.Length())); |
} |
-HRESULT DaemonControllerWin::ActivateController() { |
- DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
+DaemonController::UsageStatsConsent |
+DaemonControllerDelegateWin::GetUsageStatsConsent() { |
+ DaemonController::UsageStatsConsent consent; |
+ consent.supported = true; |
+ consent.allowed = false; |
+ consent.set_by_policy = false; |
- if (control_.get() == NULL) { |
+ // Activate the Daemon Controller and see if it supports |IDaemonControl2|. |
+ HRESULT hr = ActivateController(); |
+ if (FAILED(hr)) { |
+ // The host is not installed yet. Assume that the user didn't consent to |
+ // collecting crash dumps. |
+ return consent; |
+ } |
+ |
+ if (control2_.get() == NULL) { |
+ // The host is installed and does not support crash dump reporting. |
+ return consent; |
+ } |
+ |
+ // Get the recorded user's consent. |
+ BOOL allowed; |
+ BOOL set_by_policy; |
+ hr = control2_->GetUsageStatsConsent(&allowed, &set_by_policy); |
+ if (FAILED(hr)) { |
+ // If the user's consent is not recorded yet, assume that the user didn't |
+ // consent to collecting crash dumps. |
+ return consent; |
+ } |
+ |
+ consent.allowed = !!allowed; |
+ consent.set_by_policy = !!set_by_policy; |
+ return consent; |
+} |
+ |
+HRESULT DaemonControllerDelegateWin::ActivateController() { |
+ if (!control_) { |
CLSID class_id; |
HRESULT hr = CLSIDFromProgID(kDaemonController, &class_id); |
if (FAILED(hr)) { |
@@ -274,30 +333,26 @@ HRESULT DaemonControllerWin::ActivateController() { |
control_.QueryInterface(IID_IDaemonControl2, control2_.ReceiveVoid()); |
// Release |control_| upon expiration of the timeout. |
- release_timer_.reset(new base::OneShotTimer<DaemonControllerWin>()); |
+ release_timer_.reset(new base::OneShotTimer<DaemonControllerDelegateWin>()); |
release_timer_->Start(FROM_HERE, |
base::TimeDelta::FromSeconds(kUnprivilegedTimeoutSec), |
this, |
- &DaemonControllerWin::ReleaseController); |
+ &DaemonControllerDelegateWin::ReleaseController); |
} |
return S_OK; |
} |
-HRESULT DaemonControllerWin::ActivateElevatedController() { |
- DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
- |
+HRESULT DaemonControllerDelegateWin::ActivateElevatedController() { |
// The COM elevation is supported on Vista and above. |
- if (base::win::GetVersion() < base::win::VERSION_VISTA) { |
+ if (base::win::GetVersion() < base::win::VERSION_VISTA) |
return ActivateController(); |
- } |
// Release an unprivileged instance of the daemon controller if any. |
- if (!control_is_elevated_) { |
+ if (!control_is_elevated_) |
ReleaseController(); |
- } |
- if (control_.get() == NULL) { |
+ if (!control_) { |
BIND_OPTS3 bind_options; |
memset(&bind_options, 0, sizeof(bind_options)); |
bind_options.cbStruct = sizeof(bind_options); |
@@ -320,207 +375,45 @@ HRESULT DaemonControllerWin::ActivateElevatedController() { |
control_is_elevated_ = true; |
// Release |control_| upon expiration of the timeout. |
- release_timer_.reset(new base::OneShotTimer<DaemonControllerWin>()); |
+ release_timer_.reset(new base::OneShotTimer<DaemonControllerDelegateWin>()); |
release_timer_->Start(FROM_HERE, |
base::TimeDelta::FromSeconds(kPrivilegedTimeoutSec), |
this, |
- &DaemonControllerWin::ReleaseController); |
+ &DaemonControllerDelegateWin::ReleaseController); |
} |
return S_OK; |
} |
-void DaemonControllerWin::ReleaseController() { |
- DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
- |
+void DaemonControllerDelegateWin::ReleaseController() { |
control_.Release(); |
control2_.Release(); |
release_timer_.reset(); |
control_is_elevated_ = false; |
} |
-void DaemonControllerWin::OnInstallationComplete( |
+void DaemonControllerDelegateWin::OnInstallationComplete( |
scoped_ptr<base::DictionaryValue> config, |
bool consent, |
- const CompletionCallback& done, |
- HRESULT result) { |
- DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
- |
- if (SUCCEEDED(result)) { |
- DoSetConfigAndStart(config.Pass(), consent, done); |
- } else { |
- LOG(ERROR) << "Failed to install the Chromoting Host " |
- << "(error: 0x" << std::hex << result << std::dec << ")."; |
- done.Run(HResultToAsyncResult(result)); |
- } |
- |
- DCHECK(installer_.get() != NULL); |
- installer_.reset(); |
-} |
- |
-DWORD DaemonControllerWin::OpenService(ScopedScHandle* service_out) { |
- // Open the service and query its current state. |
- ScopedScHandle scmanager( |
- ::OpenSCManagerW(NULL, SERVICES_ACTIVE_DATABASE, |
- SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE)); |
- if (!scmanager.IsValid()) { |
- DWORD error = GetLastError(); |
- LOG_GETLASTERROR(ERROR) |
- << "Failed to connect to the service control manager"; |
- return error; |
- } |
- |
- ScopedScHandle service( |
- ::OpenServiceW(scmanager, kWindowsServiceName, SERVICE_QUERY_STATUS)); |
- if (!service.IsValid()) { |
- DWORD error = GetLastError(); |
- if (error != ERROR_SERVICE_DOES_NOT_EXIST) { |
- LOG_GETLASTERROR(ERROR) |
- << "Failed to open to the '" << kWindowsServiceName << "' service"; |
- } |
- return error; |
- } |
- |
- service_out->Set(service.Take()); |
- return ERROR_SUCCESS; |
-} |
- |
-// static |
-void DaemonControllerWin::ConfigToString(const base::DictionaryValue& config, |
- ScopedBstr* out) { |
- std::string config_str; |
- base::JSONWriter::Write(&config, &config_str); |
- ScopedBstr config_scoped_bstr(UTF8ToUTF16(config_str).c_str()); |
- 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( |
+ const DaemonController::CompletionCallback& done, |
HRESULT hr) { |
- if (SUCCEEDED(hr)) { |
- return RESULT_OK; |
- } else if (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED)) { |
- return RESULT_CANCELLED; |
- } else { |
- // TODO(sergeyu): Report other errors to the webapp once it knows |
- // how to handle them. |
- return RESULT_FAILED; |
- } |
-} |
- |
-void DaemonControllerWin::DoGetConfig(const GetConfigCallback& callback) { |
- DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
- |
- scoped_ptr<base::DictionaryValue> dictionary_null; |
- |
- // Configure and start the Daemon Controller if it is installed already. |
- HRESULT hr = ActivateController(); |
- if (FAILED(hr)) { |
- callback.Run(dictionary_null.Pass()); |
- return; |
- } |
+ installer_.reset(); |
- // Get the host configuration. |
- ScopedBstr host_config; |
- hr = control_->GetConfig(host_config.Receive()); |
if (FAILED(hr)) { |
- callback.Run(dictionary_null.Pass()); |
- return; |
- } |
- |
- // Parse the string into a dictionary. |
- string16 file_content(static_cast<BSTR>(host_config), host_config.Length()); |
- scoped_ptr<base::Value> config( |
- base::JSONReader::Read(UTF16ToUTF8(file_content), |
- base::JSON_ALLOW_TRAILING_COMMAS)); |
- |
- base::DictionaryValue* dictionary; |
- if (config.get() == NULL || !config->GetAsDictionary(&dictionary)) { |
- callback.Run(dictionary_null.Pass()); |
- return; |
- } |
- // Release |config|, because dictionary points to the same object. |
- config.release(); |
- |
- callback.Run(scoped_ptr<base::DictionaryValue>(dictionary)); |
-} |
- |
-void DaemonControllerWin::DoInstallAsNeededAndStart( |
- scoped_ptr<base::DictionaryValue> config, |
- bool consent, |
- const CompletionCallback& done) { |
- DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
- |
- // Configure and start the Daemon Controller if it is installed already. |
- HRESULT hr = ActivateElevatedController(); |
- if (SUCCEEDED(hr)) { |
- DoSetConfigAndStart(config.Pass(), consent, done); |
- return; |
- } |
- |
- // Otherwise, install it if its COM registration entry is missing. |
- if (hr == CO_E_CLASSSTRING) { |
- scoped_ptr<DaemonInstallerWin> installer = DaemonInstallerWin::Create( |
- GetTopLevelWindow(window_handle_), |
- base::Bind(&DaemonControllerWin::OnInstallationComplete, |
- base::Unretained(this), |
- base::Passed(&config), |
- consent, |
- done)); |
- if (installer.get()) { |
- DCHECK(!installer_.get()); |
- installer_ = installer.Pass(); |
- installer_->Install(); |
- } |
- } else { |
- LOG(ERROR) << "Failed to initiate the Chromoting Host installation " |
+ LOG(ERROR) << "Failed to install the Chromoting Host " |
<< "(error: 0x" << std::hex << hr << std::dec << ")."; |
done.Run(HResultToAsyncResult(hr)); |
+ return; |
} |
-} |
- |
-void DaemonControllerWin::DoSetConfigAndStart( |
- scoped_ptr<base::DictionaryValue> config, |
- bool consent, |
- const CompletionCallback& done) { |
- DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
- HRESULT hr = ActivateElevatedController(); |
+ hr = ActivateElevatedController(); |
if (FAILED(hr)) { |
done.Run(HResultToAsyncResult(hr)); |
return; |
} |
// Record the user's consent. |
- if (control2_.get()) { |
+ if (control2_) { |
hr = control2_->SetUsageStatsConsent(consent); |
if (FAILED(hr)) { |
done.Run(HResultToAsyncResult(hr)); |
@@ -554,115 +447,10 @@ void DaemonControllerWin::DoSetConfigAndStart( |
done.Run(HResultToAsyncResult(hr)); |
} |
-void DaemonControllerWin::DoUpdateConfig( |
- scoped_ptr<base::DictionaryValue> config, |
- const CompletionCallback& done_callback) { |
- DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
- |
- HRESULT hr = ActivateElevatedController(); |
- if (FAILED(hr)) { |
- done_callback.Run(HResultToAsyncResult(hr)); |
- return; |
- } |
- |
- // Update the configuration. |
- ScopedBstr config_str(NULL); |
- ConfigToString(*config, &config_str); |
- if (config_str == NULL) { |
- done_callback.Run(HResultToAsyncResult(E_OUTOFMEMORY)); |
- return; |
- } |
- |
- // Make sure that the PIN confirmation dialog is focused properly. |
- hr = control_->SetOwnerWindow( |
- reinterpret_cast<LONG_PTR>(GetTopLevelWindow(window_handle_))); |
- if (FAILED(hr)) { |
- done_callback.Run(HResultToAsyncResult(hr)); |
- return; |
- } |
- |
- hr = control_->UpdateConfig(config_str); |
- done_callback.Run(HResultToAsyncResult(hr)); |
-} |
- |
-void DaemonControllerWin::DoStop(const CompletionCallback& done_callback) { |
- DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
- |
- HRESULT hr = ActivateElevatedController(); |
- if (FAILED(hr)) { |
- done_callback.Run(HResultToAsyncResult(hr)); |
- return; |
- } |
- |
- hr = control_->StopDaemon(); |
- done_callback.Run(HResultToAsyncResult(hr)); |
-} |
- |
-void DaemonControllerWin::DoSetWindow(void* window_handle) { |
- window_handle_ = reinterpret_cast<HWND>(window_handle); |
-} |
- |
-void DaemonControllerWin::DoGetVersion(const GetVersionCallback& callback) { |
- DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
- |
- std::string version_null; |
- |
- // Configure and start the Daemon Controller if it is installed already. |
- HRESULT hr = ActivateController(); |
- if (FAILED(hr)) { |
- callback.Run(version_null); |
- return; |
- } |
- |
- // Get the version string. |
- ScopedBstr version; |
- hr = control_->GetVersion(version.Receive()); |
- if (FAILED(hr)) { |
- callback.Run(version_null); |
- return; |
- } |
- |
- callback.Run(UTF16ToUTF8( |
- string16(static_cast<BSTR>(version), version.Length()))); |
-} |
- |
-void DaemonControllerWin::DoGetUsageStatsConsent( |
- const GetUsageStatsConsentCallback& done) { |
- DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
- |
- // Activate the Daemon Controller and see if it supports |IDaemonControl2|. |
- HRESULT hr = ActivateController(); |
- if (FAILED(hr)) { |
- // The host is not installed yet. Assume that the user didn't consent to |
- // collecting crash dumps. |
- done.Run(true, false, false); |
- return; |
- } |
- |
- if (control2_.get() == NULL) { |
- // The host is installed and does not support crash dump reporting. |
- done.Run(false, false, false); |
- return; |
- } |
- |
- // Get the recorded user's consent. |
- BOOL allowed; |
- BOOL set_by_policy; |
- hr = control2_->GetUsageStatsConsent(&allowed, &set_by_policy); |
- if (FAILED(hr)) { |
- // If the user's consent is not recorded yet, assume that the user didn't |
- // consent to collecting crash dumps. |
- done.Run(true, false, false); |
- return; |
- } |
- |
- done.Run(true, !!allowed, !!set_by_policy); |
-} |
- |
-} // namespace |
- |
-scoped_ptr<DaemonController> remoting::DaemonController::Create() { |
- return scoped_ptr<DaemonController>(new DaemonControllerWin()); |
+scoped_refptr<DaemonController> DaemonController::Create() { |
+ scoped_ptr<DaemonController::Delegate> delegate( |
+ new DaemonControllerDelegateWin()); |
+ return new DaemonController(delegate.Pass()); |
} |
} // namespace remoting |