Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(596)

Side by Side Diff: remoting/host/plugin/daemon_controller_win.cc

Issue 10272029: Make sure the timer is stopped and destroyed on the thread it was created on. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
48 const char kDaemonControllerThreadName[] = "Daemon Controller thread"; 48 const char kDaemonControllerThreadName[] = "Daemon Controller thread";
49 49
50 // The maximum interval between showing UAC prompts. 50 // The maximum interval between showing UAC prompts.
51 const int kUacTimeoutSec = 15 * 60; 51 const int kUacTimeoutSec = 15 * 60;
52 52
53 // A base::Thread implementation that initializes COM on the new thread. 53 // A base::Thread implementation that initializes COM on the new thread.
54 class ComThread : public base::Thread { 54 class ComThread : public base::Thread {
55 public: 55 public:
56 explicit ComThread(const char* name); 56 explicit ComThread(const char* name);
57 57
58 // Activates an elevated instance of the controller and returns the pointer
59 // to the control interface in |control_out|. This class keeps the ownership
60 // of the pointer so the caller should not call call AddRef() or Release().
61 HRESULT ActivateElevatedController(HWND window_handle,
62 IDaemonControl** control_out);
63
64 bool Start(); 58 bool Start();
65 59
66 protected: 60 protected:
67 virtual void Init() OVERRIDE; 61 virtual void Init() OVERRIDE;
68 virtual void CleanUp() OVERRIDE; 62 virtual void CleanUp() OVERRIDE;
69 63
70 void ReleaseElevatedController();
71
72 ScopedComPtr<IDaemonControl> control_;
73
74 // This timer is used to release |control_| after a timeout.
75 base::OneShotTimer<ComThread> release_timer_;
76
77 DISALLOW_COPY_AND_ASSIGN(ComThread); 64 DISALLOW_COPY_AND_ASSIGN(ComThread);
78 }; 65 };
79 66
80 class DaemonControllerWin : public remoting::DaemonController { 67 class DaemonControllerWin : public remoting::DaemonController {
81 public: 68 public:
82 DaemonControllerWin(); 69 DaemonControllerWin();
83 virtual ~DaemonControllerWin(); 70 virtual ~DaemonControllerWin();
84 71
85 virtual State GetState() OVERRIDE; 72 virtual State GetState() OVERRIDE;
86 virtual void GetConfig(const GetConfigCallback& callback) OVERRIDE; 73 virtual void GetConfig(const GetConfigCallback& callback) OVERRIDE;
87 virtual void SetConfigAndStart( 74 virtual void SetConfigAndStart(
88 scoped_ptr<base::DictionaryValue> config, 75 scoped_ptr<base::DictionaryValue> config,
89 const CompletionCallback& done_callback) OVERRIDE; 76 const CompletionCallback& done_callback) OVERRIDE;
90 virtual void UpdateConfig(scoped_ptr<base::DictionaryValue> config, 77 virtual void UpdateConfig(scoped_ptr<base::DictionaryValue> config,
91 const CompletionCallback& done_callback) OVERRIDE; 78 const CompletionCallback& done_callback) OVERRIDE;
92 virtual void Stop(const CompletionCallback& done_callback) OVERRIDE; 79 virtual void Stop(const CompletionCallback& done_callback) OVERRIDE;
93 virtual void SetWindow(void* window_handle) OVERRIDE; 80 virtual void SetWindow(void* window_handle) OVERRIDE;
94 81
95 private: 82 private:
96 // Converts a Windows service status code to a Daemon state. 83 // 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.
97 static State ConvertToDaemonState(DWORD service_state); 84 // in |control_|.
85 HRESULT ActivateElevatedController();
98 86
99 // Converts HRESULT to the AsyncResult. 87 // 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.
100 static AsyncResult HResultToAsyncResult(HRESULT hr); 88 void ReleaseElevatedController();
101 89
102 // Procedes with the daemon configuration if the installation succeeded, 90 // Procedes with the daemon configuration if the installation succeeded,
103 // otherwise reports the error. 91 // otherwise reports the error.
104 void OnInstallationComplete(scoped_ptr<base::DictionaryValue> config, 92 void OnInstallationComplete(scoped_ptr<base::DictionaryValue> config,
105 const CompletionCallback& done_callback, 93 const CompletionCallback& done_callback,
106 HRESULT result); 94 HRESULT result);
107 95
108 // Opens the Chromoting service returning its handle in |service_out|. 96 // Opens the Chromoting service returning its handle in |service_out|.
109 DWORD OpenService(ScopedScHandle* service_out); 97 DWORD OpenService(ScopedScHandle* service_out);
110 98
111 // Converts a config dictionary to a scoped BSTR. 99 // Converts a config dictionary to a scoped BSTR.
112 static void ConfigToString(const base::DictionaryValue& config, 100 static void ConfigToString(const base::DictionaryValue& config,
113 ScopedBstr* out); 101 ScopedBstr* out);
114 102
103 // Converts a Windows service status code to a Daemon state.
104 static State ConvertToDaemonState(DWORD service_state);
105
106 // Converts HRESULT to the AsyncResult.
107 static AsyncResult HResultToAsyncResult(HRESULT hr);
108
115 // The functions that actually do the work. They should be called in 109 // The functions that actually do the work. They should be called in
116 // the context of |worker_thread_|; 110 // the context of |worker_thread_|;
117 void DoGetConfig(const GetConfigCallback& callback); 111 void DoGetConfig(const GetConfigCallback& callback);
118 void DoInstallAsNeededAndStart(scoped_ptr<base::DictionaryValue> config, 112 void DoInstallAsNeededAndStart(scoped_ptr<base::DictionaryValue> config,
119 const CompletionCallback& done_callback); 113 const CompletionCallback& done_callback);
120 void DoSetConfigAndStart(scoped_ptr<base::DictionaryValue> config, 114 void DoSetConfigAndStart(scoped_ptr<base::DictionaryValue> config,
121 const CompletionCallback& done_callback); 115 const CompletionCallback& done_callback);
122 void DoUpdateConfig(scoped_ptr<base::DictionaryValue> config, 116 void DoUpdateConfig(scoped_ptr<base::DictionaryValue> config,
123 const CompletionCallback& done_callback); 117 const CompletionCallback& done_callback);
124 void DoStop(const CompletionCallback& done_callback); 118 void DoStop(const CompletionCallback& done_callback);
125 void DoSetWindow(void* window_handle); 119 void DoSetWindow(void* window_handle);
126 120
121 ScopedComPtr<IDaemonControl> control_;
122
123 // This timer is used to release |control_| after a timeout.
124 scoped_ptr<base::OneShotTimer<DaemonControllerWin> > release_timer_;
125
127 // Handle of the plugin window. 126 // Handle of the plugin window.
128 HWND window_handle_; 127 HWND window_handle_;
129 128
130 // The worker thread used for servicing long running operations. 129 // The worker thread used for servicing long running operations.
131 ComThread worker_thread_; 130 ComThread worker_thread_;
132 131
133 scoped_ptr<DaemonInstallerWin> installer_; 132 scoped_ptr<DaemonInstallerWin> installer_;
134 133
135 DISALLOW_COPY_AND_ASSIGN(DaemonControllerWin); 134 DISALLOW_COPY_AND_ASSIGN(DaemonControllerWin);
136 }; 135 };
137 136
138 ComThread::ComThread(const char* name) : base::Thread(name), control_(NULL) { 137 ComThread::ComThread(const char* name) : base::Thread(name) {
139 }
140
141 HRESULT ComThread::ActivateElevatedController(
142 HWND window_handle,
143 IDaemonControl** control_out) {
144 // Cache an instance of the Elevated Controller to prevent a UAC prompt on
145 // every operation.
146 if (control_.get() == NULL) {
147 BIND_OPTS3 bind_options;
148 memset(&bind_options, 0, sizeof(bind_options));
149 bind_options.cbStruct = sizeof(bind_options);
150 bind_options.hwnd = GetTopLevelWindow(window_handle);
151 bind_options.dwClassContext = CLSCTX_LOCAL_SERVER;
152
153 HRESULT hr = ::CoGetObject(
154 kDaemonControllerElevationMoniker,
155 &bind_options,
156 IID_IDaemonControl,
157 control_.ReceiveVoid());
158 if (FAILED(hr)) {
159 return hr;
160 }
161
162 // Release |control_| upon expiration of the timeout.
163 release_timer_.Start(FROM_HERE,
164 base::TimeDelta::FromSeconds(kUacTimeoutSec),
165 this, &ComThread::ReleaseElevatedController);
166 }
167
168 *control_out = control_.get();
169 return S_OK;
170 } 138 }
171 139
172 bool ComThread::Start() { 140 bool ComThread::Start() {
173 // N.B. The single threaded COM apartment must be run on a UI message loop. 141 // N.B. The single threaded COM apartment must be run on a UI message loop.
174 base::Thread::Options thread_options(MessageLoop::TYPE_UI, 0); 142 base::Thread::Options thread_options(MessageLoop::TYPE_UI, 0);
175 return StartWithOptions(thread_options); 143 return StartWithOptions(thread_options);
176 } 144 }
177 145
178 void ComThread::Init() { 146 void ComThread::Init() {
179 CoInitialize(NULL); 147 CoInitialize(NULL);
180 } 148 }
181 149
182 void ComThread::CleanUp() { 150 void ComThread::CleanUp() {
183 ReleaseElevatedController();
184 CoUninitialize(); 151 CoUninitialize();
185 } 152 }
186 153
187 void ComThread::ReleaseElevatedController() {
188 control_.Release();
189 }
190
191 DaemonControllerWin::DaemonControllerWin() 154 DaemonControllerWin::DaemonControllerWin()
192 : window_handle_(NULL), 155 : window_handle_(NULL),
193 worker_thread_(kDaemonControllerThreadName) { 156 worker_thread_(kDaemonControllerThreadName) {
194 if (!worker_thread_.Start()) { 157 if (!worker_thread_.Start()) {
195 LOG(FATAL) << "Failed to start the Daemon Controller worker thread."; 158 LOG(FATAL) << "Failed to start the Daemon Controller worker thread.";
196 } 159 }
197 } 160 }
198 161
199 DaemonControllerWin::~DaemonControllerWin() { 162 DaemonControllerWin::~DaemonControllerWin() {
163 // Clean up resources allocated on the worker thread.
164 worker_thread_.message_loop_proxy()->PostTask(
165 FROM_HERE,
166 base::Bind(&DaemonControllerWin::ReleaseElevatedController,
167 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
200 worker_thread_.Stop(); 168 worker_thread_.Stop();
201 } 169 }
202 170
203 remoting::DaemonController::State DaemonControllerWin::GetState() { 171 remoting::DaemonController::State DaemonControllerWin::GetState() {
204 // TODO(alexeypa): Make the thread alertable, so we can switch to APC 172 // TODO(alexeypa): Make the thread alertable, so we can switch to APC
205 // notifications rather than polling. 173 // notifications rather than polling.
206 ScopedScHandle service; 174 ScopedScHandle service;
207 DWORD error = OpenService(&service); 175 DWORD error = OpenService(&service);
208 176
209 switch (error) { 177 switch (error) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 done_callback)); 226 done_callback));
259 } 227 }
260 228
261 void DaemonControllerWin::SetWindow(void* window_handle) { 229 void DaemonControllerWin::SetWindow(void* window_handle) {
262 worker_thread_.message_loop_proxy()->PostTask( 230 worker_thread_.message_loop_proxy()->PostTask(
263 FROM_HERE, base::Bind( 231 FROM_HERE, base::Bind(
264 &DaemonControllerWin::DoSetWindow, base::Unretained(this), 232 &DaemonControllerWin::DoSetWindow, base::Unretained(this),
265 window_handle)); 233 window_handle));
266 } 234 }
267 235
268 // static 236 HRESULT DaemonControllerWin::ActivateElevatedController() {
269 remoting::DaemonController::State DaemonControllerWin::ConvertToDaemonState( 237 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
270 DWORD service_state) {
271 switch (service_state) {
272 case SERVICE_RUNNING:
273 return STATE_STARTED;
274 238
275 case SERVICE_CONTINUE_PENDING: 239 // Cache an instance of the Elevated Controller to prevent a UAC prompt on
276 case SERVICE_START_PENDING: 240 // every operation.
277 return STATE_STARTING; 241 if (control_.get() == NULL) {
278 break; 242 BIND_OPTS3 bind_options;
243 memset(&bind_options, 0, sizeof(bind_options));
244 bind_options.cbStruct = sizeof(bind_options);
245 bind_options.hwnd = GetTopLevelWindow(window_handle_);
246 bind_options.dwClassContext = CLSCTX_LOCAL_SERVER;
279 247
280 case SERVICE_PAUSE_PENDING: 248 HRESULT hr = ::CoGetObject(
281 case SERVICE_STOP_PENDING: 249 kDaemonControllerElevationMoniker,
282 return STATE_STOPPING; 250 &bind_options,
283 break; 251 IID_IDaemonControl,
252 control_.ReceiveVoid());
253 if (FAILED(hr)) {
254 return hr;
255 }
284 256
285 case SERVICE_PAUSED: 257 // Release |control_| upon expiration of the timeout.
286 case SERVICE_STOPPED: 258 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
287 return STATE_STOPPED; 259 release_timer_->Start(FROM_HERE,
288 break; 260 base::TimeDelta::FromSeconds(kUacTimeoutSec),
261 this,
262 &DaemonControllerWin::ReleaseElevatedController);
263 }
289 264
290 default: 265 return S_OK;
291 NOTREACHED();
292 return STATE_UNKNOWN;
293 }
294 } 266 }
295 267
296 // static 268 void DaemonControllerWin::ReleaseElevatedController() {
297 DaemonController::AsyncResult DaemonControllerWin::HResultToAsyncResult( 269 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
298 HRESULT hr) { 270
299 // TODO(sergeyu): Report other errors to the webapp once it knows 271 control_.Release();
300 // how to handle them. 272 release_timer_.reset();
301 return FAILED(hr) ? RESULT_FAILED : RESULT_OK;
302 } 273 }
303 274
304 void DaemonControllerWin::OnInstallationComplete( 275 void DaemonControllerWin::OnInstallationComplete(
305 scoped_ptr<base::DictionaryValue> config, 276 scoped_ptr<base::DictionaryValue> config,
306 const CompletionCallback& done_callback, 277 const CompletionCallback& done_callback,
307 HRESULT result) { 278 HRESULT result) {
308 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); 279 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
309 280
310 if (SUCCEEDED(result)) { 281 if (SUCCEEDED(result)) {
311 DoSetConfigAndStart(config.Pass(), done_callback); 282 DoSetConfigAndStart(config.Pass(), done_callback);
(...skipping 27 matching lines...) Expand all
339 LOG_GETLASTERROR(ERROR) 310 LOG_GETLASTERROR(ERROR)
340 << "Failed to open to the '" << kWindowsServiceName << "' service"; 311 << "Failed to open to the '" << kWindowsServiceName << "' service";
341 } 312 }
342 return error; 313 return error;
343 } 314 }
344 315
345 service_out->Set(service.Take()); 316 service_out->Set(service.Take());
346 return ERROR_SUCCESS; 317 return ERROR_SUCCESS;
347 } 318 }
348 319
320 // static
349 void DaemonControllerWin::ConfigToString(const base::DictionaryValue& config, 321 void DaemonControllerWin::ConfigToString(const base::DictionaryValue& config,
350 ScopedBstr* out) { 322 ScopedBstr* out) {
351 std::string config_str; 323 std::string config_str;
352 base::JSONWriter::Write(&config, &config_str); 324 base::JSONWriter::Write(&config, &config_str);
353 ScopedBstr config_scoped_bstr(UTF8ToUTF16(config_str).c_str()); 325 ScopedBstr config_scoped_bstr(UTF8ToUTF16(config_str).c_str());
354 out->Swap(config_scoped_bstr); 326 out->Swap(config_scoped_bstr);
355 } 327 }
356 328
329 // static
330 remoting::DaemonController::State DaemonControllerWin::ConvertToDaemonState(
331 DWORD service_state) {
332 switch (service_state) {
333 case SERVICE_RUNNING:
334 return STATE_STARTED;
335
336 case SERVICE_CONTINUE_PENDING:
337 case SERVICE_START_PENDING:
338 return STATE_STARTING;
339 break;
340
341 case SERVICE_PAUSE_PENDING:
342 case SERVICE_STOP_PENDING:
343 return STATE_STOPPING;
344 break;
345
346 case SERVICE_PAUSED:
347 case SERVICE_STOPPED:
348 return STATE_STOPPED;
349 break;
350
351 default:
352 NOTREACHED();
353 return STATE_UNKNOWN;
354 }
355 }
356
357 // static
358 DaemonController::AsyncResult DaemonControllerWin::HResultToAsyncResult(
359 HRESULT hr) {
360 // TODO(sergeyu): Report other errors to the webapp once it knows
361 // how to handle them.
362 return FAILED(hr) ? RESULT_FAILED : RESULT_OK;
363 }
364
357 void DaemonControllerWin::DoGetConfig(const GetConfigCallback& callback) { 365 void DaemonControllerWin::DoGetConfig(const GetConfigCallback& callback) {
358 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); 366 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
359 367
360 scoped_ptr<base::DictionaryValue> dictionary_null(NULL); 368 scoped_ptr<base::DictionaryValue> dictionary_null(NULL);
361 // Get the name of the configuration file. 369 // Get the name of the configuration file.
362 FilePath dir = remoting::GetConfigDir(); 370 FilePath dir = remoting::GetConfigDir();
363 FilePath filename = dir.Append(kUnprivilegedConfigFileName); 371 FilePath filename = dir.Append(kUnprivilegedConfigFileName);
364 372
365 // Read raw data from the configuration file. 373 // Read raw data from the configuration file.
366 base::win::ScopedHandle file( 374 base::win::ScopedHandle file(
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 value.release(); 413 value.release();
406 414
407 callback.Run(scoped_ptr<base::DictionaryValue>(dictionary)); 415 callback.Run(scoped_ptr<base::DictionaryValue>(dictionary));
408 } 416 }
409 417
410 void DaemonControllerWin::DoInstallAsNeededAndStart( 418 void DaemonControllerWin::DoInstallAsNeededAndStart(
411 scoped_ptr<base::DictionaryValue> config, 419 scoped_ptr<base::DictionaryValue> config,
412 const CompletionCallback& done_callback) { 420 const CompletionCallback& done_callback) {
413 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); 421 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
414 422
415 IDaemonControl* control = NULL; 423 // Configure and start the Daemon Controller if it is installed already.
416 HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_, 424 HRESULT hr = ActivateElevatedController();
417 &control);
418
419 // Just configure and start the Daemon Controller if it is installed already.
420 if (SUCCEEDED(hr)) { 425 if (SUCCEEDED(hr)) {
421 DoSetConfigAndStart(config.Pass(), done_callback); 426 DoSetConfigAndStart(config.Pass(), done_callback);
422 return; 427 return;
423 } 428 }
424 429
425 // Otherwise, install it if its COM registration entry is missing. 430 // Otherwise, install it if its COM registration entry is missing.
426 if (hr == CO_E_CLASSSTRING) { 431 if (hr == CO_E_CLASSSTRING) {
427 scoped_ptr<DaemonInstallerWin> installer = DaemonInstallerWin::Create( 432 scoped_ptr<DaemonInstallerWin> installer = DaemonInstallerWin::Create(
428 window_handle_, 433 window_handle_,
429 base::Bind(&DaemonControllerWin::OnInstallationComplete, 434 base::Bind(&DaemonControllerWin::OnInstallationComplete,
(...skipping 10 matching lines...) Expand all
440 << "(error: 0x" << std::hex << hr << std::dec << ")."; 445 << "(error: 0x" << std::hex << hr << std::dec << ").";
441 done_callback.Run(HResultToAsyncResult(hr)); 446 done_callback.Run(HResultToAsyncResult(hr));
442 } 447 }
443 } 448 }
444 449
445 void DaemonControllerWin::DoSetConfigAndStart( 450 void DaemonControllerWin::DoSetConfigAndStart(
446 scoped_ptr<base::DictionaryValue> config, 451 scoped_ptr<base::DictionaryValue> config,
447 const CompletionCallback& done_callback) { 452 const CompletionCallback& done_callback) {
448 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); 453 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
449 454
450 IDaemonControl* control = NULL; 455 HRESULT hr = ActivateElevatedController();
451 HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_,
452 &control);
453 if (FAILED(hr)) { 456 if (FAILED(hr)) {
454 done_callback.Run(HResultToAsyncResult(hr)); 457 done_callback.Run(HResultToAsyncResult(hr));
455 return; 458 return;
456 } 459 }
457 460
458 // Set the configuration. 461 // Set the configuration.
459 ScopedBstr config_str(NULL); 462 ScopedBstr config_str(NULL);
460 ConfigToString(*config, &config_str); 463 ConfigToString(*config, &config_str);
461 if (config_str == NULL) { 464 if (config_str == NULL) {
462 done_callback.Run(HResultToAsyncResult(E_OUTOFMEMORY)); 465 done_callback.Run(HResultToAsyncResult(E_OUTOFMEMORY));
463 return; 466 return;
464 } 467 }
465 468
466 hr = control->SetConfig(config_str); 469 hr = control_->SetConfig(config_str);
467 if (FAILED(hr)) { 470 if (FAILED(hr)) {
468 done_callback.Run(HResultToAsyncResult(hr)); 471 done_callback.Run(HResultToAsyncResult(hr));
469 return; 472 return;
470 } 473 }
471 474
472 // Start daemon. 475 // Start daemon.
473 hr = control->StartDaemon(); 476 hr = control_->StartDaemon();
474 done_callback.Run(HResultToAsyncResult(hr)); 477 done_callback.Run(HResultToAsyncResult(hr));
475 } 478 }
476 479
477 void DaemonControllerWin::DoUpdateConfig( 480 void DaemonControllerWin::DoUpdateConfig(
478 scoped_ptr<base::DictionaryValue> config, 481 scoped_ptr<base::DictionaryValue> config,
479 const CompletionCallback& done_callback) { 482 const CompletionCallback& done_callback) {
480 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); 483 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
481 484
482 IDaemonControl* control = NULL; 485 HRESULT hr = ActivateElevatedController();
483 HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_,
484 &control);
485 if (FAILED(hr)) { 486 if (FAILED(hr)) {
486 done_callback.Run(HResultToAsyncResult(hr)); 487 done_callback.Run(HResultToAsyncResult(hr));
487 return; 488 return;
488 } 489 }
489 490
490 // Update the configuration. 491 // Update the configuration.
491 ScopedBstr config_str(NULL); 492 ScopedBstr config_str(NULL);
492 ConfigToString(*config, &config_str); 493 ConfigToString(*config, &config_str);
493 if (config_str == NULL) { 494 if (config_str == NULL) {
494 done_callback.Run(HResultToAsyncResult(E_OUTOFMEMORY)); 495 done_callback.Run(HResultToAsyncResult(E_OUTOFMEMORY));
495 return; 496 return;
496 } 497 }
497 498
498 hr = control->UpdateConfig(config_str); 499 hr = control_->UpdateConfig(config_str);
499 done_callback.Run(HResultToAsyncResult(hr)); 500 done_callback.Run(HResultToAsyncResult(hr));
500 } 501 }
501 502
502 void DaemonControllerWin::DoStop(const CompletionCallback& done_callback) { 503 void DaemonControllerWin::DoStop(const CompletionCallback& done_callback) {
503 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); 504 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
504 505
505 IDaemonControl* control = NULL; 506 HRESULT hr = ActivateElevatedController();
506 HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_,
507 &control);
508 if (FAILED(hr)) { 507 if (FAILED(hr)) {
509 done_callback.Run(HResultToAsyncResult(hr)); 508 done_callback.Run(HResultToAsyncResult(hr));
510 return; 509 return;
511 } 510 }
512 511
513 hr = control->StopDaemon(); 512 hr = control_->StopDaemon();
514 done_callback.Run(HResultToAsyncResult(hr)); 513 done_callback.Run(HResultToAsyncResult(hr));
515 } 514 }
516 515
517 void DaemonControllerWin::DoSetWindow(void* window_handle) { 516 void DaemonControllerWin::DoSetWindow(void* window_handle) {
518 window_handle_ = reinterpret_cast<HWND>(window_handle); 517 window_handle_ = reinterpret_cast<HWND>(window_handle);
519 } 518 }
520 519
521 } // namespace 520 } // namespace
522 521
523 scoped_ptr<DaemonController> remoting::DaemonController::Create() { 522 scoped_ptr<DaemonController> remoting::DaemonController::Create() {
524 return scoped_ptr<DaemonController>(new DaemonControllerWin()); 523 return scoped_ptr<DaemonController>(new DaemonControllerWin());
525 } 524 }
526 525
527 } // namespace remoting 526 } // namespace remoting
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698