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

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

Issue 10161034: Making sure that UAC promts fired by the Chromoting plugin get focus (instead of being shown in the… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: CR feedback 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
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 19 matching lines...) Expand all
30 // MIDL-generated declarations and definitions. 30 // MIDL-generated declarations and definitions.
31 #include "remoting/host/elevated_controller.h" 31 #include "remoting/host/elevated_controller.h"
32 32
33 using base::win::ScopedBstr; 33 using base::win::ScopedBstr;
34 using base::win::ScopedComPtr; 34 using base::win::ScopedComPtr;
35 35
36 namespace remoting { 36 namespace remoting {
37 37
38 namespace { 38 namespace {
39 39
40 // The COM elevation moniker for the elevated controller. 40 // The COM elevation moniker for the Elevated Controller.
41 const char16 kDaemonControllerElevationMoniker[] = 41 const char16 kDaemonControllerElevationMoniker[] =
42 TO_L_STRING("Elevation:Administrator!new:") 42 TO_L_STRING("Elevation:Administrator!new:")
43 TO_L_STRING("ChromotingElevatedController.ElevatedController"); 43 TO_L_STRING("ChromotingElevatedController.ElevatedController");
44 44
45 // Name of the Daemon Controller's worker thread. 45 // Name of the Daemon Controller's worker thread.
46 const char kDaemonControllerThreadName[] = "Daemon Controller thread"; 46 const char kDaemonControllerThreadName[] = "Daemon Controller thread";
47 47
48 // A base::Thread implementation that initializes COM on the new thread. 48 // A base::Thread implementation that initializes COM on the new thread.
49 class ComThread : public base::Thread { 49 class ComThread : public base::Thread {
50 public: 50 public:
51 explicit ComThread(const char* name); 51 explicit ComThread(const char* name);
52 52
53 // Activates an elevated instance of the controller and returns the pointer 53 // Activates an elevated instance of the controller and returns the pointer
54 // to the control interface in |control_out|. This class keeps the ownership 54 // to the control interface in |control_out|. This class keeps the ownership
55 // of the pointer so the caller should not call call AddRef() or Release(). 55 // of the pointer so the caller should not call call AddRef() or Release().
56 HRESULT ActivateElevatedController(IDaemonControl** control_out); 56 HRESULT ActivateElevatedController(HWND window_handle,
57 IDaemonControl** control_out);
57 58
58 bool Start(); 59 bool Start();
59 60
60 protected: 61 protected:
61 virtual void Init() OVERRIDE; 62 virtual void Init() OVERRIDE;
62 virtual void CleanUp() OVERRIDE; 63 virtual void CleanUp() OVERRIDE;
63 64
64 ScopedComPtr<IDaemonControl> control_; 65 ScopedComPtr<IDaemonControl> control_;
65 66
66 DISALLOW_COPY_AND_ASSIGN(ComThread); 67 DISALLOW_COPY_AND_ASSIGN(ComThread);
67 }; 68 };
68 69
69 class DaemonControllerWin : public remoting::DaemonController { 70 class DaemonControllerWin : public remoting::DaemonController {
70 public: 71 public:
71 DaemonControllerWin(); 72 DaemonControllerWin();
72 virtual ~DaemonControllerWin(); 73 virtual ~DaemonControllerWin();
73 74
74 virtual State GetState() OVERRIDE; 75 virtual State GetState() OVERRIDE;
75 virtual void GetConfig(const GetConfigCallback& callback) OVERRIDE; 76 virtual void GetConfig(const GetConfigCallback& callback) OVERRIDE;
76 virtual void SetConfigAndStart( 77 virtual void SetConfigAndStart(
77 scoped_ptr<base::DictionaryValue> config, 78 scoped_ptr<base::DictionaryValue> config,
78 const CompletionCallback& done_callback) OVERRIDE; 79 const CompletionCallback& done_callback) OVERRIDE;
79 virtual void UpdateConfig(scoped_ptr<base::DictionaryValue> config, 80 virtual void UpdateConfig(scoped_ptr<base::DictionaryValue> config,
80 const CompletionCallback& done_callback) OVERRIDE; 81 const CompletionCallback& done_callback) OVERRIDE;
81 virtual void Stop(const CompletionCallback& done_callback) OVERRIDE; 82 virtual void Stop(const CompletionCallback& done_callback) OVERRIDE;
83 virtual void SetWindow(void* window_handle) OVERRIDE;
82 84
83 private: 85 private:
84 // Converts a Windows service status code to a Daemon state. 86 // Converts a Windows service status code to a Daemon state.
85 static State ConvertToDaemonState(DWORD service_state); 87 static State ConvertToDaemonState(DWORD service_state);
86 88
87 // Converts HRESULT to the AsyncResult. 89 // Converts HRESULT to the AsyncResult.
88 static AsyncResult HResultToAsyncResult(HRESULT hr); 90 static AsyncResult HResultToAsyncResult(HRESULT hr);
89 91
90 // Procedes with the daemon configuration if the installation succeeded, 92 // Procedes with the daemon configuration if the installation succeeded,
91 // otherwise reports the error. 93 // otherwise reports the error.
92 void OnInstallationComplete(scoped_ptr<base::DictionaryValue> config, 94 void OnInstallationComplete(scoped_ptr<base::DictionaryValue> config,
93 const CompletionCallback& done_callback, 95 const CompletionCallback& done_callback,
94 HRESULT result); 96 HRESULT result);
95 97
96 // Opens the Chromoting service returning its handle in |service_out|. 98 // Opens the Chromoting service returning its handle in |service_out|.
97 DWORD OpenService(ScopedScHandle* service_out); 99 DWORD OpenService(ScopedScHandle* service_out);
98 100
99 // The functions that actually do the work. They should be called in 101 // The functions that actually do the work. They should be called in
100 // the context of |worker_thread_|; 102 // the context of |worker_thread_|;
101 void DoGetConfig(const GetConfigCallback& callback); 103 void DoGetConfig(const GetConfigCallback& callback);
102 void DoInstallAsNeededAndStart(scoped_ptr<base::DictionaryValue> config, 104 void DoInstallAsNeededAndStart(scoped_ptr<base::DictionaryValue> config,
103 const CompletionCallback& done_callback); 105 const CompletionCallback& done_callback);
104 void DoSetConfigAndStart(scoped_ptr<base::DictionaryValue> config, 106 void DoSetConfigAndStart(scoped_ptr<base::DictionaryValue> config,
105 const CompletionCallback& done_callback); 107 const CompletionCallback& done_callback);
106 void DoUpdateConfig(scoped_ptr<base::DictionaryValue> config, 108 void DoUpdateConfig(scoped_ptr<base::DictionaryValue> config,
107 const CompletionCallback& done_callback); 109 const CompletionCallback& done_callback);
108 void DoStop(const CompletionCallback& done_callback); 110 void DoStop(const CompletionCallback& done_callback);
111 void DoSetWindow(void* window_handle);
112
113 // Handle of the plugin window.
114 HWND window_handle_;
109 115
110 // The worker thread used for servicing long running operations. 116 // The worker thread used for servicing long running operations.
111 ComThread worker_thread_; 117 ComThread worker_thread_;
112 118
113 scoped_ptr<DaemonInstallerWin> installer_; 119 scoped_ptr<DaemonInstallerWin> installer_;
114 120
115 DISALLOW_COPY_AND_ASSIGN(DaemonControllerWin); 121 DISALLOW_COPY_AND_ASSIGN(DaemonControllerWin);
116 }; 122 };
117 123
118 ComThread::ComThread(const char* name) : base::Thread(name), control_(NULL) { 124 ComThread::ComThread(const char* name) : base::Thread(name), control_(NULL) {
119 } 125 }
120 126
121 void ComThread::Init() {
122 CoInitialize(NULL);
123 }
124
125 void ComThread::CleanUp() {
126 control_.Release();
127 CoUninitialize();
128 }
129
130 HRESULT ComThread::ActivateElevatedController( 127 HRESULT ComThread::ActivateElevatedController(
128 HWND window_handle,
131 IDaemonControl** control_out) { 129 IDaemonControl** control_out) {
132 // Chache the instance of Elevated Controller to prevent a UAC prompt on every 130 // Cache an instance of the Elevated Controller to prevent a UAC prompt on
133 // operation. 131 // every operation.
134 if (control_.get() == NULL) { 132 if (control_.get() == NULL) {
135 BIND_OPTS3 bind_options; 133 BIND_OPTS3 bind_options;
136 memset(&bind_options, 0, sizeof(bind_options)); 134 memset(&bind_options, 0, sizeof(bind_options));
137 bind_options.cbStruct = sizeof(bind_options); 135 bind_options.cbStruct = sizeof(bind_options);
138 bind_options.hwnd = NULL; 136 bind_options.hwnd = GetTopLevelWindow(window_handle);
139 bind_options.dwClassContext = CLSCTX_LOCAL_SERVER; 137 bind_options.dwClassContext = CLSCTX_LOCAL_SERVER;
140 138
141 HRESULT hr = ::CoGetObject( 139 HRESULT hr = ::CoGetObject(
142 kDaemonControllerElevationMoniker, 140 kDaemonControllerElevationMoniker,
143 &bind_options, 141 &bind_options,
144 IID_IDaemonControl, 142 IID_IDaemonControl,
145 control_.ReceiveVoid()); 143 control_.ReceiveVoid());
146 if (FAILED(hr)) { 144 if (FAILED(hr)) {
147 return hr; 145 return hr;
148 } 146 }
149 } 147 }
150 148
151 *control_out = control_.get(); 149 *control_out = control_.get();
152 return S_OK; 150 return S_OK;
153 } 151 }
154 152
155 bool ComThread::Start() { 153 bool ComThread::Start() {
156 // N.B. The single threaded COM apartment must be run on a UI message loop. 154 // N.B. The single threaded COM apartment must be run on a UI message loop.
157 base::Thread::Options thread_options(MessageLoop::TYPE_UI, 0); 155 base::Thread::Options thread_options(MessageLoop::TYPE_UI, 0);
158 return StartWithOptions(thread_options); 156 return StartWithOptions(thread_options);
159 } 157 }
160 158
159 void ComThread::Init() {
160 CoInitialize(NULL);
161 }
162
163 void ComThread::CleanUp() {
164 control_.Release();
165 CoUninitialize();
166 }
167
161 DaemonControllerWin::DaemonControllerWin() 168 DaemonControllerWin::DaemonControllerWin()
162 : worker_thread_(kDaemonControllerThreadName) { 169 : window_handle_(NULL),
170 worker_thread_(kDaemonControllerThreadName) {
163 if (!worker_thread_.Start()) { 171 if (!worker_thread_.Start()) {
164 LOG(FATAL) << "Failed to start the Daemon Controller worker thread."; 172 LOG(FATAL) << "Failed to start the Daemon Controller worker thread.";
165 } 173 }
166 } 174 }
167 175
168 DaemonControllerWin::~DaemonControllerWin() { 176 DaemonControllerWin::~DaemonControllerWin() {
169 worker_thread_.Stop(); 177 worker_thread_.Stop();
170 } 178 }
171 179
172 remoting::DaemonController::State DaemonControllerWin::GetState() { 180 remoting::DaemonController::State DaemonControllerWin::GetState() {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 base::Unretained(this), base::Passed(&config), done_callback)); 228 base::Unretained(this), base::Passed(&config), done_callback));
221 } 229 }
222 230
223 void DaemonControllerWin::Stop(const CompletionCallback& done_callback) { 231 void DaemonControllerWin::Stop(const CompletionCallback& done_callback) {
224 worker_thread_.message_loop_proxy()->PostTask( 232 worker_thread_.message_loop_proxy()->PostTask(
225 FROM_HERE, base::Bind( 233 FROM_HERE, base::Bind(
226 &DaemonControllerWin::DoStop, base::Unretained(this), 234 &DaemonControllerWin::DoStop, base::Unretained(this),
227 done_callback)); 235 done_callback));
228 } 236 }
229 237
238 void DaemonControllerWin::SetWindow(void* window_handle) {
239 worker_thread_.message_loop_proxy()->PostTask(
240 FROM_HERE, base::Bind(
241 &DaemonControllerWin::DoSetWindow, base::Unretained(this),
242 window_handle));
243 }
244
230 // static 245 // static
231 remoting::DaemonController::State DaemonControllerWin::ConvertToDaemonState( 246 remoting::DaemonController::State DaemonControllerWin::ConvertToDaemonState(
232 DWORD service_state) { 247 DWORD service_state) {
233 switch (service_state) { 248 switch (service_state) {
234 case SERVICE_RUNNING: 249 case SERVICE_RUNNING:
235 return STATE_STARTED; 250 return STATE_STARTED;
236 251
237 case SERVICE_CONTINUE_PENDING: 252 case SERVICE_CONTINUE_PENDING:
238 case SERVICE_START_PENDING: 253 case SERVICE_START_PENDING:
239 return STATE_STARTING; 254 return STATE_STARTING;
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
360 375
361 callback.Run(scoped_ptr<base::DictionaryValue>(dictionary)); 376 callback.Run(scoped_ptr<base::DictionaryValue>(dictionary));
362 } 377 }
363 378
364 void DaemonControllerWin::DoInstallAsNeededAndStart( 379 void DaemonControllerWin::DoInstallAsNeededAndStart(
365 scoped_ptr<base::DictionaryValue> config, 380 scoped_ptr<base::DictionaryValue> config,
366 const CompletionCallback& done_callback) { 381 const CompletionCallback& done_callback) {
367 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); 382 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
368 383
369 IDaemonControl* control = NULL; 384 IDaemonControl* control = NULL;
370 HRESULT hr = worker_thread_.ActivateElevatedController(&control); 385 HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_,
386 &control);
371 387
372 // Just configure and start the Daemon Controller if it is installed already. 388 // Just configure and start the Daemon Controller if it is installed already.
373 if (SUCCEEDED(hr)) { 389 if (SUCCEEDED(hr)) {
374 DoSetConfigAndStart(config.Pass(), done_callback); 390 DoSetConfigAndStart(config.Pass(), done_callback);
375 return; 391 return;
376 } 392 }
377 393
378 // Otherwise, install it if its COM registration entry is missing. 394 // Otherwise, install it if its COM registration entry is missing.
379 if (hr == CO_E_CLASSSTRING) { 395 if (hr == CO_E_CLASSSTRING) {
380 scoped_ptr<DaemonInstallerWin> installer = DaemonInstallerWin::Create( 396 scoped_ptr<DaemonInstallerWin> installer = DaemonInstallerWin::Create(
397 window_handle_,
381 base::Bind(&DaemonControllerWin::OnInstallationComplete, 398 base::Bind(&DaemonControllerWin::OnInstallationComplete,
382 base::Unretained(this), 399 base::Unretained(this),
383 base::Passed(&config), 400 base::Passed(&config),
384 done_callback)); 401 done_callback));
385 if (installer.get()) { 402 if (installer.get()) {
386 DCHECK(!installer_.get()); 403 DCHECK(!installer_.get());
387 installer_ = installer.Pass(); 404 installer_ = installer.Pass();
388 installer_->Install(); 405 installer_->Install();
389 } 406 }
390 } else { 407 } else {
391 LOG(ERROR) << "Failed to initiate the Chromoting Host installation " 408 LOG(ERROR) << "Failed to initiate the Chromoting Host installation "
392 << "(error: 0x" << std::hex << hr << std::dec << ")."; 409 << "(error: 0x" << std::hex << hr << std::dec << ").";
393 done_callback.Run(HResultToAsyncResult(hr)); 410 done_callback.Run(HResultToAsyncResult(hr));
394 } 411 }
395 } 412 }
396 413
397 void DaemonControllerWin::DoSetConfigAndStart( 414 void DaemonControllerWin::DoSetConfigAndStart(
398 scoped_ptr<base::DictionaryValue> config, 415 scoped_ptr<base::DictionaryValue> config,
399 const CompletionCallback& done_callback) { 416 const CompletionCallback& done_callback) {
400 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); 417 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
401 418
402 IDaemonControl* control = NULL; 419 IDaemonControl* control = NULL;
403 HRESULT hr = worker_thread_.ActivateElevatedController(&control); 420 HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_,
421 &control);
404 if (FAILED(hr)) { 422 if (FAILED(hr)) {
405 done_callback.Run(HResultToAsyncResult(hr)); 423 done_callback.Run(HResultToAsyncResult(hr));
406 return; 424 return;
407 } 425 }
408 426
409 // Store the configuration. 427 // Store the configuration.
410 std::string file_content; 428 std::string file_content;
411 base::JSONWriter::Write(config.get(), &file_content); 429 base::JSONWriter::Write(config.get(), &file_content);
412 430
413 ScopedBstr host_config(UTF8ToUTF16(file_content).c_str()); 431 ScopedBstr host_config(UTF8ToUTF16(file_content).c_str());
(...skipping 14 matching lines...) Expand all
428 } 446 }
429 447
430 void DaemonControllerWin::DoUpdateConfig( 448 void DaemonControllerWin::DoUpdateConfig(
431 scoped_ptr<base::DictionaryValue> config, 449 scoped_ptr<base::DictionaryValue> config,
432 const CompletionCallback& done_callback) { 450 const CompletionCallback& done_callback) {
433 // TODO(simonmorris): Much of this code was copied from DoSetConfigAndStart(). 451 // TODO(simonmorris): Much of this code was copied from DoSetConfigAndStart().
434 // Refactor. 452 // Refactor.
435 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); 453 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
436 454
437 IDaemonControl* control = NULL; 455 IDaemonControl* control = NULL;
438 HRESULT hr = worker_thread_.ActivateElevatedController(&control); 456 HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_,
457 &control);
439 if (FAILED(hr)) { 458 if (FAILED(hr)) {
440 done_callback.Run(HResultToAsyncResult(hr)); 459 done_callback.Run(HResultToAsyncResult(hr));
441 return; 460 return;
442 } 461 }
443 462
444 // Store the configuration. 463 // Store the configuration.
445 std::string file_content; 464 std::string file_content;
446 base::JSONWriter::Write(config.get(), &file_content); 465 base::JSONWriter::Write(config.get(), &file_content);
447 466
448 ScopedBstr host_config(UTF8ToUTF16(file_content).c_str()); 467 ScopedBstr host_config(UTF8ToUTF16(file_content).c_str());
449 if (host_config == NULL) { 468 if (host_config == NULL) {
450 done_callback.Run(HResultToAsyncResult(E_OUTOFMEMORY)); 469 done_callback.Run(HResultToAsyncResult(E_OUTOFMEMORY));
451 return; 470 return;
452 } 471 }
453 472
454 hr = control->UpdateConfig(host_config); 473 hr = control->UpdateConfig(host_config);
455 done_callback.Run(HResultToAsyncResult(hr)); 474 done_callback.Run(HResultToAsyncResult(hr));
456 } 475 }
457 476
458 void DaemonControllerWin::DoStop(const CompletionCallback& done_callback) { 477 void DaemonControllerWin::DoStop(const CompletionCallback& done_callback) {
459 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); 478 DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread());
460 479
461 IDaemonControl* control = NULL; 480 IDaemonControl* control = NULL;
462 HRESULT hr = worker_thread_.ActivateElevatedController(&control); 481 HRESULT hr = worker_thread_.ActivateElevatedController(window_handle_,
482 &control);
463 if (FAILED(hr)) { 483 if (FAILED(hr)) {
464 done_callback.Run(HResultToAsyncResult(hr)); 484 done_callback.Run(HResultToAsyncResult(hr));
465 return; 485 return;
466 } 486 }
467 487
468 hr = control->StopDaemon(); 488 hr = control->StopDaemon();
469 done_callback.Run(HResultToAsyncResult(hr)); 489 done_callback.Run(HResultToAsyncResult(hr));
470 } 490 }
471 491
492 void DaemonControllerWin::DoSetWindow(void* window_handle) {
493 window_handle_ = reinterpret_cast<HWND>(window_handle);
494 }
495
472 } // namespace 496 } // namespace
473 497
474 scoped_ptr<DaemonController> remoting::DaemonController::Create() { 498 scoped_ptr<DaemonController> remoting::DaemonController::Create() {
475 return scoped_ptr<DaemonController>(new DaemonControllerWin()); 499 return scoped_ptr<DaemonController>(new DaemonControllerWin());
476 } 500 }
477 501
478 } // namespace remoting 502 } // namespace remoting
OLDNEW
« no previous file with comments | « remoting/host/plugin/daemon_controller_mac.cc ('k') | remoting/host/plugin/daemon_installer_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698