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 86e7d66644cea80c422e83a96039488a595791af..0cb41a9aeddc1a9325d5a24b3babfade6c3f4a17 100644 |
--- a/remoting/host/plugin/daemon_controller_win.cc |
+++ b/remoting/host/plugin/daemon_controller_win.cc |
@@ -27,6 +27,7 @@ |
#include "remoting/base/scoped_sc_handle_win.h" |
#include "remoting/host/branding.h" |
#include "remoting/host/plugin/daemon_installer_win.h" |
+#include "remoting/host/usage_stats_consent.h" |
// MIDL-generated declarations and definitions. |
#include "remoting/host/elevated_controller.h" |
@@ -76,12 +77,15 @@ class DaemonControllerWin : public remoting::DaemonController { |
virtual void GetConfig(const GetConfigCallback& callback) OVERRIDE; |
virtual void SetConfigAndStart( |
scoped_ptr<base::DictionaryValue> config, |
- const CompletionCallback& done_callback) OVERRIDE; |
+ 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. |
@@ -96,7 +100,8 @@ class DaemonControllerWin : public remoting::DaemonController { |
// Procedes with the daemon configuration if the installation succeeded, |
// otherwise reports the error. |
void OnInstallationComplete(scoped_ptr<base::DictionaryValue> config, |
- const CompletionCallback& done_callback, |
+ bool consent, |
+ const CompletionCallback& done, |
HRESULT result); |
// Opens the Chromoting service returning its handle in |service_out|. |
@@ -116,18 +121,23 @@ class DaemonControllerWin : public remoting::DaemonController { |
// 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, |
- const CompletionCallback& done_callback); |
+ 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_| holds a reference to an instance of the daemon controller |
- // to prevent a UAC prompt on every operation. |
+ // |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. |
@@ -220,11 +230,12 @@ void DaemonControllerWin::GetConfig(const GetConfigCallback& callback) { |
void DaemonControllerWin::SetConfigAndStart( |
scoped_ptr<base::DictionaryValue> config, |
- const CompletionCallback& done_callback) { |
+ bool consent, |
+ const CompletionCallback& done) { |
worker_thread_.message_loop_proxy()->PostTask( |
FROM_HERE, base::Bind( |
&DaemonControllerWin::DoInstallAsNeededAndStart, |
- base::Unretained(this), base::Passed(&config), done_callback)); |
+ base::Unretained(this), base::Passed(&config), consent, done)); |
} |
void DaemonControllerWin::UpdateConfig( |
@@ -257,6 +268,14 @@ void DaemonControllerWin::GetVersion(const GetVersionCallback& callback) { |
base::Unretained(this), callback)); |
} |
+void DaemonControllerWin::GetUsageStatsConsent( |
+ const GetUsageStatsConsentCallback& done) { |
+ worker_thread_.message_loop_proxy()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&DaemonControllerWin::DoGetUsageStatsConsent, |
+ base::Unretained(this), done)); |
+} |
+ |
HRESULT DaemonControllerWin::ActivateController() { |
DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
@@ -272,6 +291,9 @@ HRESULT DaemonControllerWin::ActivateController() { |
if (FAILED(hr)) { |
return hr; |
} |
+ |
+ // Ignore the error. IID_IDaemonControl2 is optional. |
+ control_.QueryInterface(IID_IDaemonControl2, control2_.ReceiveVoid()); |
} |
return S_OK; |
@@ -301,6 +323,9 @@ HRESULT DaemonControllerWin::ActivateElevatedController() { |
return hr; |
} |
+ // Ignore the error. IID_IDaemonControl2 is optional. |
+ control_.QueryInterface(IID_IDaemonControl2, control2_.ReceiveVoid()); |
+ |
// Note that we hold a reference to an elevated instance now. |
control_is_elevated_ = true; |
@@ -319,22 +344,24 @@ void DaemonControllerWin::ReleaseController() { |
DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
control_.Release(); |
+ control2_.Release(); |
release_timer_.reset(); |
control_is_elevated_ = false; |
} |
void DaemonControllerWin::OnInstallationComplete( |
scoped_ptr<base::DictionaryValue> config, |
- const CompletionCallback& done_callback, |
+ bool consent, |
+ const CompletionCallback& done, |
HRESULT result) { |
DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
if (SUCCEEDED(result)) { |
- DoSetConfigAndStart(config.Pass(), done_callback); |
+ DoSetConfigAndStart(config.Pass(), consent, done); |
} else { |
LOG(ERROR) << "Failed to install the Chromoting Host " |
<< "(error: 0x" << std::hex << result << std::dec << ")."; |
- done_callback.Run(HResultToAsyncResult(result)); |
+ done.Run(HResultToAsyncResult(result)); |
} |
DCHECK(installer_.get() != NULL); |
@@ -452,13 +479,14 @@ void DaemonControllerWin::DoGetConfig(const GetConfigCallback& callback) { |
void DaemonControllerWin::DoInstallAsNeededAndStart( |
scoped_ptr<base::DictionaryValue> config, |
- const CompletionCallback& done_callback) { |
+ 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(), done_callback); |
+ DoSetConfigAndStart(config.Pass(), consent, done); |
return; |
} |
@@ -469,7 +497,8 @@ void DaemonControllerWin::DoInstallAsNeededAndStart( |
base::Bind(&DaemonControllerWin::OnInstallationComplete, |
base::Unretained(this), |
base::Passed(&config), |
- done_callback)); |
+ consent, |
+ done)); |
if (installer.get()) { |
DCHECK(!installer_.get()); |
installer_ = installer.Pass(); |
@@ -478,45 +507,55 @@ void DaemonControllerWin::DoInstallAsNeededAndStart( |
} else { |
LOG(ERROR) << "Failed to initiate the Chromoting Host installation " |
<< "(error: 0x" << std::hex << hr << std::dec << ")."; |
- done_callback.Run(HResultToAsyncResult(hr)); |
+ done.Run(HResultToAsyncResult(hr)); |
} |
} |
void DaemonControllerWin::DoSetConfigAndStart( |
scoped_ptr<base::DictionaryValue> config, |
- const CompletionCallback& done_callback) { |
+ bool consent, |
+ const CompletionCallback& done) { |
DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
HRESULT hr = ActivateElevatedController(); |
if (FAILED(hr)) { |
- done_callback.Run(HResultToAsyncResult(hr)); |
+ done.Run(HResultToAsyncResult(hr)); |
return; |
} |
+ // Record the user's consent. |
+ if (control2_.get()) { |
+ hr = control2_->SetUsageStatsConsent(consent); |
+ if (FAILED(hr)) { |
+ done.Run(HResultToAsyncResult(hr)); |
+ return; |
+ } |
+ } |
+ |
// Set the configuration. |
ScopedBstr config_str(NULL); |
ConfigToString(*config, &config_str); |
if (config_str == NULL) { |
- done_callback.Run(HResultToAsyncResult(E_OUTOFMEMORY)); |
+ done.Run(HResultToAsyncResult(E_OUTOFMEMORY)); |
return; |
} |
hr = control_->SetOwnerWindow( |
reinterpret_cast<LONG_PTR>(GetTopLevelWindow(window_handle_))); |
if (FAILED(hr)) { |
- done_callback.Run(HResultToAsyncResult(hr)); |
+ done.Run(HResultToAsyncResult(hr)); |
return; |
} |
hr = control_->SetConfig(config_str); |
if (FAILED(hr)) { |
- done_callback.Run(HResultToAsyncResult(hr)); |
+ done.Run(HResultToAsyncResult(hr)); |
return; |
} |
// Start daemon. |
hr = control_->StartDaemon(); |
- done_callback.Run(HResultToAsyncResult(hr)); |
+ done.Run(HResultToAsyncResult(hr)); |
} |
void DaemonControllerWin::DoUpdateConfig( |
@@ -591,6 +630,32 @@ void DaemonControllerWin::DoGetVersion(const GetVersionCallback& callback) { |
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) || control2_.get() == NULL) { |
+ 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, set the default value to true. |
+ // This value will not come into effect until the user agrees to crash |
+ // dump reporting while starting the host. |
+ done.Run(true, true, false); |
+ return; |
+ } |
+ |
+ done.Run(true, !!allowed, !!set_by_policy); |
+} |
+ |
} // namespace |
scoped_ptr<DaemonController> remoting::DaemonController::Create() { |