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

Unified Diff: remoting/host/plugin/daemon_controller_win.cc

Issue 10021003: Implemented on-demand installation of the Chromoting Host on Windows. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fixed errors. Created 8 years, 8 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 side-by-side diff with in-line comments
Download patch
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 7fca35d897bc0d71ddf06a45f4a26fe67720dac7..11c00e01aeb37c35104532ee5917f9928fe943ea 100644
--- a/remoting/host/plugin/daemon_controller_win.cc
+++ b/remoting/host/plugin/daemon_controller_win.cc
@@ -14,22 +14,29 @@
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
+#include "base/synchronization/lock.h"
#include "base/threading/thread.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
+#include "base/win/scoped_bstr.h"
+#include "base/win/scoped_comptr.h"
#include "remoting/base/scoped_sc_handle_win.h"
#include "remoting/host/branding.h"
+#include "remoting/host/plugin/daemon_installer_win.h"
// MIDL-generated declarations and definitions.
#include "remoting/host/elevated_controller.h"
+using base::win::ScopedBstr;
+using base::win::ScopedComPtr;
+
namespace remoting {
namespace {
// The COM elevation moniker for the elevated controller.
-const char kElevationMoniker[] = "Elevation:Administrator!new:"
- "{430a9403-8176-4733-afdc-0b325a8fda84}";
+const char kDaemonControllerElevationMoniker[] = "Elevation:Administrator!new:"
+ "ChromotingElevatedController.ElevatedController";
// Name of the Daemon Controller's worker thread.
const char kDaemonControllerThreadName[] = "Daemon Controller thread";
@@ -50,7 +57,7 @@ class ComThread : public base::Thread {
virtual void Init() OVERRIDE;
virtual void CleanUp() OVERRIDE;
- IDaemonControl* control_;
+ ScopedComPtr<IDaemonControl> control_;
DISALLOW_COPY_AND_ASSIGN(ComThread);
};
@@ -76,12 +83,18 @@ class DaemonControllerWin : public remoting::DaemonController {
// Converts HRESULT to the AsyncResult.
static AsyncResult HResultToAsyncResult(HRESULT hr);
+ // Procedes with the daemon configuration if the installation succeeded,
+ // otherwise reports the error.
+ void OnInstallationComplete(HRESULT result);
+
// Opens the Chromoting service returning its handle in |service_out|.
DWORD OpenService(ScopedScHandle* service_out);
// The functions that actually do the work. They should be called in
// the context of |worker_thread_|;
void DoGetConfig(const GetConfigCallback& callback);
+ void DoInstall(scoped_ptr<base::DictionaryValue> config,
+ const CompletionCallback& done_callback);
void DoSetConfigAndStart(scoped_ptr<base::DictionaryValue> config,
const CompletionCallback& done_callback);
void DoStop(const CompletionCallback& done_callback);
@@ -89,6 +102,13 @@ class DaemonControllerWin : public remoting::DaemonController {
// The worker thread used for servicing long running operations.
ComThread worker_thread_;
+ // The lock protecting the data members below.
+ base::Lock lock_;
+
+ scoped_ptr<base::DictionaryValue> config_;
+ CompletionCallback done_callback_;
Sergey Ulanov 2012/04/07 18:09:21 Since this is used only during installation maybe
alexeypa (please no reviews) 2012/04/09 20:24:11 It was removed from the class.
+ scoped_ptr<DaemonInstallerWin> installer_;
+
DISALLOW_COPY_AND_ASSIGN(DaemonControllerWin);
};
@@ -100,8 +120,7 @@ void ComThread::Init() {
}
void ComThread::CleanUp() {
- if (control_ != NULL)
- control_->Release();
+ control_.Release();
CoUninitialize();
}
@@ -109,25 +128,24 @@ HRESULT ComThread::ActivateElevatedController(
IDaemonControl** control_out) {
// Chache the instance of Elevated Controller to prevent a UAC prompt on every
// operation.
- if (control_ == NULL) {
+ if (control_.get() == NULL) {
BIND_OPTS3 bind_options;
memset(&bind_options, 0, sizeof(bind_options));
bind_options.cbStruct = sizeof(bind_options);
bind_options.hwnd = NULL;
bind_options.dwClassContext = CLSCTX_LOCAL_SERVER;
- HRESULT hr = ::CoGetObject(ASCIIToUTF16(kElevationMoniker).c_str(),
- &bind_options,
- IID_IDaemonControl,
- reinterpret_cast<void**>(&control_));
+ HRESULT hr = ::CoGetObject(
+ ASCIIToUTF16(kDaemonControllerElevationMoniker).c_str(),
+ &bind_options,
+ IID_IDaemonControl,
+ control_.ReceiveVoid());
if (FAILED(hr)) {
- LOG(ERROR) << "Failed to create the elevated controller (error: 0x"
- << std::hex << hr << std::dec << ").";
return hr;
}
}
- *control_out = control_;
+ *control_out = control_.get();
return S_OK;
}
@@ -168,7 +186,7 @@ remoting::DaemonController::State DaemonControllerWin::GetState() {
break;
}
case ERROR_SERVICE_DOES_NOT_EXIST:
- return STATE_NOT_IMPLEMENTED;
+ return STATE_NOT_INSTALLED;
default:
return STATE_UNKNOWN;
}
@@ -187,7 +205,7 @@ void DaemonControllerWin::SetConfigAndStart(
worker_thread_.message_loop_proxy()->PostTask(
FROM_HERE, base::Bind(
- &DaemonControllerWin::DoSetConfigAndStart, base::Unretained(this),
+ &DaemonControllerWin::DoInstall, base::Unretained(this),
base::Passed(&config), done_callback));
}
@@ -241,6 +259,26 @@ DaemonController::AsyncResult DaemonControllerWin::HResultToAsyncResult(
return FAILED(hr) ? RESULT_FAILED : RESULT_OK;
}
+void DaemonControllerWin::OnInstallationComplete(HRESULT result) {
+ scoped_ptr<base::DictionaryValue> config;
+ CompletionCallback done_callback;
+
+ {
+ base::AutoLock lock(lock_);
+ installer_.reset();
+ std::swap(done_callback, done_callback_);
+ config = config_.Pass();
+ }
+
+ if (SUCCEEDED(result)) {
+ DoSetConfigAndStart(config.Pass(), done_callback);
+ } else {
+ LOG(ERROR) << "Failed to install the Chromoting Host "
+ << "(error: 0x" << std::hex << result << std::dec << ").";
+ done_callback.Run(HResultToAsyncResult(result));
+ }
+}
+
DWORD DaemonControllerWin::OpenService(ScopedScHandle* service_out) {
// Open the service and query its current state.
ScopedScHandle scmanager(
@@ -278,16 +316,14 @@ void DaemonControllerWin::DoGetConfig(const GetConfigCallback& callback) {
}
// Get the host configuration.
- BSTR host_config = NULL;
- hr = control->GetConfig(&host_config);
+ ScopedBstr host_config;
+ hr = control->GetConfig(host_config.Receive());
if (FAILED(hr)) {
callback.Run(scoped_ptr<base::DictionaryValue>());
return;
}
- string16 file_content(static_cast<char16*>(host_config),
- ::SysStringLen(host_config));
- SysFreeString(host_config);
+ string16 file_content(static_cast<BSTR>(host_config), host_config.Length());
// Parse the string into a dictionary.
scoped_ptr<base::Value> config(
@@ -303,6 +339,41 @@ void DaemonControllerWin::DoGetConfig(const GetConfigCallback& callback) {
callback.Run(scoped_ptr<base::DictionaryValue>(dictionary));
}
+void DaemonControllerWin::DoInstall(scoped_ptr<base::DictionaryValue> config,
Sergey Ulanov 2012/04/07 18:09:21 Since this method installs the host only if it isn
alexeypa (please no reviews) 2012/04/09 20:24:11 Renamed to DoInstallAsNeededAndStart to preserve "
+ const CompletionCallback& done_callback) {
+ IDaemonControl* control = NULL;
+ HRESULT hr = worker_thread_.ActivateElevatedController(&control);
+
+ // Just configure and start the Daemon Controller if it is installed already.
+ if (SUCCEEDED(hr)) {
+ DoSetConfigAndStart(config.Pass(), done_callback);
+ return;
+ }
+
+ // Otherwise, install it if it's COM registration entry is missing.
+ if (hr == CO_E_CLASSSTRING) {
+ base::AutoLock lock(lock_);
+ DCHECK(!config_.get());
+ DCHECK(!installer_.get());
+
+ hr = DaemonInstallerWin::Create(&installer_);
+ if (SUCCEEDED(hr)) {
+ config_ = config.Pass();
Sergey Ulanov 2012/04/07 18:09:21 Do we really need to store these values as class m
alexeypa (please no reviews) 2012/04/09 20:24:11 Done. I kept installer_ as a class member (instea
+ done_callback_ = done_callback;
+ }
+ }
+
+ // Run the installer or report the error if any.
+ if (SUCCEEDED(hr)) {
+ installer_->Install(base::Bind(&DaemonControllerWin::OnInstallationComplete,
+ base::Unretained(this)));
Sergey Ulanov 2012/04/07 18:09:21 nit: not indented properly
alexeypa (please no reviews) 2012/04/09 20:24:11 Done.
+ } else {
+ LOG(ERROR) << "Failed to initiate the Chromoting Host installation "
+ << "(error: 0x" << std::hex << hr << std::dec << ").";
+ done_callback.Run(HResultToAsyncResult(hr));
+ }
+}
+
void DaemonControllerWin::DoSetConfigAndStart(
scoped_ptr<base::DictionaryValue> config,
const CompletionCallback& done_callback) {
@@ -317,14 +388,13 @@ void DaemonControllerWin::DoSetConfigAndStart(
std::string file_content;
base::JSONWriter::Write(config.get(), &file_content);
- BSTR host_config = ::SysAllocString(UTF8ToUTF16(file_content).c_str());
+ ScopedBstr host_config(UTF8ToUTF16(file_content).c_str());
if (host_config == NULL) {
done_callback.Run(HResultToAsyncResult(E_OUTOFMEMORY));
return;
}
hr = control->SetConfig(host_config);
- ::SysFreeString(host_config);
if (FAILED(hr)) {
done_callback.Run(HResultToAsyncResult(hr));
return;

Powered by Google App Engine
This is Rietveld 408576698