OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "remoting/host/plugin/daemon_controller.h" | 5 #include "remoting/host/plugin/daemon_controller.h" |
6 | 6 |
7 #include <objbase.h> | 7 #include <objbase.h> |
8 | 8 |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
12 #include "base/compiler_specific.h" | 12 #include "base/compiler_specific.h" |
13 #include "base/file_path.h" | 13 #include "base/file_path.h" |
14 #include "base/file_util.h" | 14 #include "base/file_util.h" |
15 #include "base/json/json_reader.h" | 15 #include "base/json/json_reader.h" |
16 #include "base/json/json_writer.h" | 16 #include "base/json/json_writer.h" |
17 #include "base/logging.h" | 17 #include "base/logging.h" |
18 #include "base/string16.h" | 18 #include "base/string16.h" |
19 #include "base/stringize_macros.h" | 19 #include "base/stringize_macros.h" |
20 #include "base/threading/thread.h" | 20 #include "base/threading/thread.h" |
21 #include "base/time.h" | 21 #include "base/time.h" |
22 #include "base/timer.h" | 22 #include "base/timer.h" |
23 #include "base/utf_string_conversions.h" | 23 #include "base/utf_string_conversions.h" |
24 #include "base/values.h" | 24 #include "base/values.h" |
25 #include "base/win/scoped_bstr.h" | 25 #include "base/win/scoped_bstr.h" |
26 #include "base/win/scoped_comptr.h" | 26 #include "base/win/scoped_comptr.h" |
27 #include "base/win/windows_version.h" | 27 #include "base/win/windows_version.h" |
28 #include "remoting/base/scoped_sc_handle_win.h" | 28 #include "remoting/base/scoped_sc_handle_win.h" |
29 #include "remoting/host/branding.h" | 29 #include "remoting/host/branding.h" |
30 #include "remoting/host/breakpad.h" | |
30 #include "remoting/host/plugin/daemon_installer_win.h" | 31 #include "remoting/host/plugin/daemon_installer_win.h" |
31 | 32 |
32 // MIDL-generated declarations and definitions. | 33 // MIDL-generated declarations and definitions. |
33 #include "remoting/host/elevated_controller.h" | 34 #include "remoting/host/elevated_controller.h" |
34 | 35 |
35 using base::win::ScopedBstr; | 36 using base::win::ScopedBstr; |
36 using base::win::ScopedComPtr; | 37 using base::win::ScopedComPtr; |
37 | 38 |
38 namespace remoting { | 39 namespace remoting { |
39 | 40 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
76 virtual State GetState() OVERRIDE; | 77 virtual State GetState() OVERRIDE; |
77 virtual void GetConfig(const GetConfigCallback& callback) OVERRIDE; | 78 virtual void GetConfig(const GetConfigCallback& callback) OVERRIDE; |
78 virtual void SetConfigAndStart( | 79 virtual void SetConfigAndStart( |
79 scoped_ptr<base::DictionaryValue> config, | 80 scoped_ptr<base::DictionaryValue> config, |
80 const CompletionCallback& done_callback) OVERRIDE; | 81 const CompletionCallback& done_callback) OVERRIDE; |
81 virtual void UpdateConfig(scoped_ptr<base::DictionaryValue> config, | 82 virtual void UpdateConfig(scoped_ptr<base::DictionaryValue> config, |
82 const CompletionCallback& done_callback) OVERRIDE; | 83 const CompletionCallback& done_callback) OVERRIDE; |
83 virtual void Stop(const CompletionCallback& done_callback) OVERRIDE; | 84 virtual void Stop(const CompletionCallback& done_callback) OVERRIDE; |
84 virtual void SetWindow(void* window_handle) OVERRIDE; | 85 virtual void SetWindow(void* window_handle) OVERRIDE; |
85 virtual void GetVersion(const GetVersionCallback& done_callback) OVERRIDE; | 86 virtual void GetVersion(const GetVersionCallback& done_callback) OVERRIDE; |
87 virtual void GetUsageStatsConsent( | |
88 const GetUsageStatsConsentCallback& done_callback) OVERRIDE; | |
89 virtual void SetUsageStatsConsent(bool consent) OVERRIDE; | |
86 | 90 |
87 private: | 91 private: |
88 // Activates an unprivileged instance of the daemon controller and caches it. | 92 // Activates an unprivileged instance of the daemon controller and caches it. |
89 HRESULT ActivateController(); | 93 HRESULT ActivateController(); |
90 | 94 |
91 // Activates an elevated instance of the daemon controller and caches it. | 95 // Activates an elevated instance of the daemon controller and caches it. |
92 HRESULT ActivateElevatedController(); | 96 HRESULT ActivateElevatedController(); |
93 | 97 |
94 // Releases the cached instance of the controller. | 98 // Releases the cached instance of the controller. |
95 void ReleaseController(); | 99 void ReleaseController(); |
(...skipping 22 matching lines...) Expand all Loading... | |
118 void DoGetConfig(const GetConfigCallback& callback); | 122 void DoGetConfig(const GetConfigCallback& callback); |
119 void DoInstallAsNeededAndStart(scoped_ptr<base::DictionaryValue> config, | 123 void DoInstallAsNeededAndStart(scoped_ptr<base::DictionaryValue> config, |
120 const CompletionCallback& done_callback); | 124 const CompletionCallback& done_callback); |
121 void DoSetConfigAndStart(scoped_ptr<base::DictionaryValue> config, | 125 void DoSetConfigAndStart(scoped_ptr<base::DictionaryValue> config, |
122 const CompletionCallback& done_callback); | 126 const CompletionCallback& done_callback); |
123 void DoUpdateConfig(scoped_ptr<base::DictionaryValue> config, | 127 void DoUpdateConfig(scoped_ptr<base::DictionaryValue> config, |
124 const CompletionCallback& done_callback); | 128 const CompletionCallback& done_callback); |
125 void DoStop(const CompletionCallback& done_callback); | 129 void DoStop(const CompletionCallback& done_callback); |
126 void DoSetWindow(void* window_handle); | 130 void DoSetWindow(void* window_handle); |
127 void DoGetVersion(const GetVersionCallback& callback); | 131 void DoGetVersion(const GetVersionCallback& callback); |
132 void DoGetUsageStatsConsent( | |
133 const GetUsageStatsConsentCallback& callback); | |
134 void DoSetUsageStatsConsent(bool consent); | |
128 | 135 |
129 // |control_| holds a reference to an instance of the daemon controller | 136 // |control_| and |control2_| hold references to an instance of the daemon |
130 // to prevent a UAC prompt on every operation. | 137 // controller to prevent a UAC prompt on every operation. |
131 ScopedComPtr<IDaemonControl> control_; | 138 ScopedComPtr<IDaemonControl> control_; |
139 ScopedComPtr<IDaemonControl2> control2_; | |
132 | 140 |
133 // True if |control_| holds a reference to an elevated instance of the daemon | 141 // True if |control_| holds a reference to an elevated instance of the daemon |
134 // controller. | 142 // controller. |
135 bool control_is_elevated_; | 143 bool control_is_elevated_; |
136 | 144 |
137 // This timer is used to release |control_| after a timeout. | 145 // This timer is used to release |control_| after a timeout. |
138 scoped_ptr<base::OneShotTimer<DaemonControllerWin> > release_timer_; | 146 scoped_ptr<base::OneShotTimer<DaemonControllerWin> > release_timer_; |
139 | 147 |
140 // Handle of the plugin window. | 148 // Handle of the plugin window. |
141 HWND window_handle_; | 149 HWND window_handle_; |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
251 window_handle)); | 259 window_handle)); |
252 } | 260 } |
253 | 261 |
254 void DaemonControllerWin::GetVersion(const GetVersionCallback& callback) { | 262 void DaemonControllerWin::GetVersion(const GetVersionCallback& callback) { |
255 worker_thread_.message_loop_proxy()->PostTask( | 263 worker_thread_.message_loop_proxy()->PostTask( |
256 FROM_HERE, | 264 FROM_HERE, |
257 base::Bind(&DaemonControllerWin::DoGetVersion, | 265 base::Bind(&DaemonControllerWin::DoGetVersion, |
258 base::Unretained(this), callback)); | 266 base::Unretained(this), callback)); |
259 } | 267 } |
260 | 268 |
269 void DaemonControllerWin::GetUsageStatsConsent( | |
270 const GetUsageStatsConsentCallback& callback) { | |
271 worker_thread_.message_loop_proxy()->PostTask( | |
272 FROM_HERE, | |
273 base::Bind(&DaemonControllerWin::DoGetUsageStatsConsent, | |
274 base::Unretained(this), callback)); | |
275 } | |
276 | |
277 void DaemonControllerWin::SetUsageStatsConsent(bool consent) { | |
278 worker_thread_.message_loop_proxy()->PostTask( | |
279 FROM_HERE, | |
280 base::Bind(&DaemonControllerWin::DoSetUsageStatsConsent, | |
281 base::Unretained(this), consent)); | |
282 } | |
283 | |
261 HRESULT DaemonControllerWin::ActivateController() { | 284 HRESULT DaemonControllerWin::ActivateController() { |
262 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); | 285 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
263 | 286 |
264 if (control_.get() == NULL) { | 287 if (control_.get() == NULL) { |
265 CLSID class_id; | 288 CLSID class_id; |
266 HRESULT hr = CLSIDFromProgID(kDaemonController, &class_id); | 289 HRESULT hr = CLSIDFromProgID(kDaemonController, &class_id); |
267 if (FAILED(hr)) { | 290 if (FAILED(hr)) { |
268 return hr; | 291 return hr; |
269 } | 292 } |
270 | 293 |
271 hr = CoCreateInstance(class_id, NULL, CLSCTX_LOCAL_SERVER, | 294 hr = CoCreateInstance(class_id, NULL, CLSCTX_LOCAL_SERVER, |
272 IID_IDaemonControl, control_.ReceiveVoid()); | 295 IID_IDaemonControl, control_.ReceiveVoid()); |
273 if (FAILED(hr)) { | 296 if (FAILED(hr)) { |
274 return hr; | 297 return hr; |
275 } | 298 } |
299 | |
300 // Ignore the error. IID_IDaemonControl2 is optional. | |
301 control_.QueryInterface(IID_IDaemonControl2, control2_.ReceiveVoid()); | |
276 } | 302 } |
277 | 303 |
278 return S_OK; | 304 return S_OK; |
279 } | 305 } |
280 | 306 |
281 HRESULT DaemonControllerWin::ActivateElevatedController() { | 307 HRESULT DaemonControllerWin::ActivateElevatedController() { |
282 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); | 308 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
283 | 309 |
284 // Release an unprivileged instance of the daemon controller if any. | 310 // Release an unprivileged instance of the daemon controller if any. |
285 if (!control_is_elevated_) { | 311 if (!control_is_elevated_) { |
286 ReleaseController(); | 312 ReleaseController(); |
287 } | 313 } |
288 | 314 |
289 if (control_.get() == NULL) { | 315 if (control_.get() == NULL) { |
290 BIND_OPTS3 bind_options; | 316 BIND_OPTS3 bind_options; |
291 memset(&bind_options, 0, sizeof(bind_options)); | 317 memset(&bind_options, 0, sizeof(bind_options)); |
292 bind_options.cbStruct = sizeof(bind_options); | 318 bind_options.cbStruct = sizeof(bind_options); |
293 bind_options.hwnd = GetTopLevelWindow(window_handle_); | 319 bind_options.hwnd = GetTopLevelWindow(window_handle_); |
294 bind_options.dwClassContext = CLSCTX_LOCAL_SERVER; | 320 bind_options.dwClassContext = CLSCTX_LOCAL_SERVER; |
295 | 321 |
296 HRESULT hr = ::CoGetObject( | 322 HRESULT hr = ::CoGetObject( |
297 kDaemonControllerElevationMoniker, | 323 kDaemonControllerElevationMoniker, |
298 &bind_options, | 324 &bind_options, |
299 IID_IDaemonControl, | 325 IID_IDaemonControl, |
300 control_.ReceiveVoid()); | 326 control_.ReceiveVoid()); |
301 if (FAILED(hr)) { | 327 if (FAILED(hr)) { |
302 return hr; | 328 return hr; |
303 } | 329 } |
304 | 330 |
331 // Ignore the error. IID_IDaemonControl2 is optional. | |
332 control_.QueryInterface(IID_IDaemonControl2, control2_.ReceiveVoid()); | |
Jamie
2012/06/14 23:43:56
Does this result in an elevated IDaemonControl2 in
alexeypa (please no reviews)
2012/06/19 23:27:29
Yes, but the UAC prompt has been shown to the user
Jamie
2012/06/21 18:47:52
My point is that if the code is designed to be run
alexeypa (please no reviews)
2012/06/21 23:30:25
The code was designed to be running as either non-
| |
333 | |
305 // Note that we hold a reference to an elevated instance now. | 334 // Note that we hold a reference to an elevated instance now. |
306 control_is_elevated_ = true; | 335 control_is_elevated_ = true; |
307 | 336 |
308 // Release |control_| upon expiration of the timeout. | 337 // Release |control_| upon expiration of the timeout. |
309 release_timer_.reset(new base::OneShotTimer<DaemonControllerWin>()); | 338 release_timer_.reset(new base::OneShotTimer<DaemonControllerWin>()); |
310 release_timer_->Start(FROM_HERE, | 339 release_timer_->Start(FROM_HERE, |
311 base::TimeDelta::FromSeconds(kUacTimeoutSec), | 340 base::TimeDelta::FromSeconds(kUacTimeoutSec), |
312 this, | 341 this, |
313 &DaemonControllerWin::ReleaseController); | 342 &DaemonControllerWin::ReleaseController); |
314 } | 343 } |
315 | 344 |
316 return S_OK; | 345 return S_OK; |
317 } | 346 } |
318 | 347 |
319 void DaemonControllerWin::ReleaseController() { | 348 void DaemonControllerWin::ReleaseController() { |
320 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); | 349 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
321 | 350 |
322 control_.Release(); | 351 control_.Release(); |
352 control2_.Release(); | |
323 release_timer_.reset(); | 353 release_timer_.reset(); |
324 control_is_elevated_ = false; | 354 control_is_elevated_ = false; |
325 } | 355 } |
326 | 356 |
327 void DaemonControllerWin::OnInstallationComplete( | 357 void DaemonControllerWin::OnInstallationComplete( |
328 scoped_ptr<base::DictionaryValue> config, | 358 scoped_ptr<base::DictionaryValue> config, |
329 const CompletionCallback& done_callback, | 359 const CompletionCallback& done_callback, |
330 HRESULT result) { | 360 HRESULT result) { |
331 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); | 361 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); |
332 | 362 |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
585 hr = control_->GetVersion(version.Receive()); | 615 hr = control_->GetVersion(version.Receive()); |
586 if (FAILED(hr)) { | 616 if (FAILED(hr)) { |
587 callback.Run(version_null); | 617 callback.Run(version_null); |
588 return; | 618 return; |
589 } | 619 } |
590 | 620 |
591 callback.Run(UTF16ToUTF8( | 621 callback.Run(UTF16ToUTF8( |
592 string16(static_cast<BSTR>(version), version.Length()))); | 622 string16(static_cast<BSTR>(version), version.Length()))); |
593 } | 623 } |
594 | 624 |
625 void DaemonControllerWin::DoGetUsageStatsConsent( | |
626 const GetUsageStatsConsentCallback& callback) { | |
627 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); | |
628 | |
629 // Activate the Daemon Controller and see if it supports |IDaemonControl2|. | |
630 HRESULT hr = ActivateController(); | |
631 if (FAILED(hr) || control2_.get() == NULL) { | |
632 callback.Run(false, false); | |
Jamie
2012/06/14 23:43:56
There should be a mechanism for reporting "not imp
alexeypa (please no reviews)
2012/06/19 23:27:29
Done.
| |
633 return; | |
634 } | |
635 | |
636 // Get the recorded user's consent. | |
637 BOOL set_by_policy; | |
638 BOOL allowed; | |
639 hr = control2_->GetUsageStatsConsent(&set_by_policy, &allowed); | |
640 if (FAILED(hr)) { | |
641 callback.Run(false, false); | |
642 return; | |
643 } | |
644 | |
645 callback.Run(!!set_by_policy, !!allowed); | |
646 } | |
647 | |
648 void DaemonControllerWin::DoSetUsageStatsConsent(bool consent) { | |
649 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); | |
650 | |
651 // Activate the Daemon Controller and see if it supports |IDaemonControl2|. | |
652 HRESULT hr = ActivateController(); | |
653 if (FAILED(hr) || control2_.get() == NULL) { | |
654 return; | |
Jamie
2012/06/14 23:43:56
It would be better to report failure to the caller
alexeypa (please no reviews)
2012/06/19 23:27:29
Done.
| |
655 } | |
656 | |
657 // Record the user's consent. | |
658 hr = control2_->SetUsageStatsConsent(consent); | |
659 if (FAILED(hr)) { | |
660 return; | |
661 } | |
662 } | |
663 | |
595 } // namespace | 664 } // namespace |
596 | 665 |
597 scoped_ptr<DaemonController> remoting::DaemonController::Create() { | 666 scoped_ptr<DaemonController> remoting::DaemonController::Create() { |
598 return scoped_ptr<DaemonController>(new DaemonControllerWin()); | 667 return scoped_ptr<DaemonController>(new DaemonControllerWin()); |
599 } | 668 } |
600 | 669 |
601 } // namespace remoting | 670 } // namespace remoting |
OLD | NEW |