diff options
author | alexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-05 00:50:36 +0000 |
---|---|---|
committer | alexeypa@chromium.org <alexeypa@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-05-05 00:50:36 +0000 |
commit | 7b9b819b1212e4ec9ba9c1d38f09793921c9de10 (patch) | |
tree | 9d63b77a83af46aeb88ed751582a6668e631b535 /remoting/host/plugin | |
parent | 5f17a46c9a7f85a6ae7c0552930718d0a4ee8ac3 (diff) | |
download | chromium_src-7b9b819b1212e4ec9ba9c1d38f09793921c9de10.zip chromium_src-7b9b819b1212e4ec9ba9c1d38f09793921c9de10.tar.gz chromium_src-7b9b819b1212e4ec9ba9c1d38f09793921c9de10.tar.bz2 |
The unprivileged part of Chromoting host configuration is read via the daemon controller interface now (instead of hardcoding the file name into the webapp plugin).
BUG=124937
TEST=manual
Review URL: http://codereview.chromium.org/10377016
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@135501 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/host/plugin')
-rw-r--r-- | remoting/host/plugin/daemon_controller_win.cc | 110 |
1 files changed, 67 insertions, 43 deletions
diff --git a/remoting/host/plugin/daemon_controller_win.cc b/remoting/host/plugin/daemon_controller_win.cc index 278d39f..c7b484d 100644 --- a/remoting/host/plugin/daemon_controller_win.cc +++ b/remoting/host/plugin/daemon_controller_win.cc @@ -26,7 +26,6 @@ #include "base/win/scoped_comptr.h" #include "remoting/base/scoped_sc_handle_win.h" #include "remoting/host/branding.h" -#include "remoting/host/daemon_controller_common_win.h" #include "remoting/host/plugin/daemon_installer_win.h" // MIDL-generated declarations and definitions. @@ -39,6 +38,10 @@ namespace remoting { namespace { +// ProgID of the daemon controller. +const char16 kDaemonController[] = + TO_L_STRING("ChromotingElevatedController.ElevatedController"); + // The COM elevation moniker for the Elevated Controller. const char16 kDaemonControllerElevationMoniker[] = TO_L_STRING("Elevation:Administrator!new:") @@ -80,11 +83,14 @@ class DaemonControllerWin : public remoting::DaemonController { virtual void SetWindow(void* window_handle) OVERRIDE; private: - // Activates an elevated instance of the controller and caches it. + // Activates an unprivileged instance of the daemon controller and caches it. + HRESULT ActivateController(); + + // Activates an elevated instance of the daemon controller and caches it. HRESULT ActivateElevatedController(); - // Releases the cached instance of the elevated controller. - void ReleaseElevatedController(); + // Releases the cached instance of the controller. + void ReleaseController(); // Procedes with the daemon configuration if the installation succeeded, // otherwise reports the error. @@ -117,9 +123,15 @@ class DaemonControllerWin : public remoting::DaemonController { void DoStop(const CompletionCallback& done_callback); void DoSetWindow(void* window_handle); + // |control_| and |control_ui_| hold references to an instance of the daemon + // controller to prevent a UAC prompt on every operation. ScopedComPtr<IDaemonControl> control_; ScopedComPtr<IDaemonControlUi> control_ui_; + // True if |control_| holds a reference to an elevated instance of the daemon + // controller. + bool control_is_elevated_; + // This timer is used to release |control_| after a timeout. scoped_ptr<base::OneShotTimer<DaemonControllerWin> > release_timer_; @@ -152,7 +164,8 @@ void ComThread::CleanUp() { } DaemonControllerWin::DaemonControllerWin() - : window_handle_(NULL), + : control_is_elevated_(false), + window_handle_(NULL), worker_thread_(kDaemonControllerThreadName) { if (!worker_thread_.Start()) { LOG(FATAL) << "Failed to start the Daemon Controller worker thread."; @@ -163,7 +176,7 @@ DaemonControllerWin::~DaemonControllerWin() { // Clean up resources allocated on the worker thread. worker_thread_.message_loop_proxy()->PostTask( FROM_HERE, - base::Bind(&DaemonControllerWin::ReleaseElevatedController, + base::Bind(&DaemonControllerWin::ReleaseController, base::Unretained(this))); worker_thread_.Stop(); } @@ -233,11 +246,34 @@ void DaemonControllerWin::SetWindow(void* window_handle) { window_handle)); } +HRESULT DaemonControllerWin::ActivateController() { + DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); + + if (control_.get() == NULL) { + CLSID class_id; + HRESULT hr = CLSIDFromProgID(kDaemonController, &class_id); + if (FAILED(hr)) { + return hr; + } + + hr = CoCreateInstance(class_id, NULL, CLSCTX_LOCAL_SERVER, + IID_IDaemonControl, control_.ReceiveVoid()); + if (FAILED(hr)) { + return hr; + } + } + + return S_OK; +} + HRESULT DaemonControllerWin::ActivateElevatedController() { DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); - // Cache an instance of the Elevated Controller to prevent a UAC prompt on - // every operation. + // Release an unprivileged instance of the daemon controller if any. + if (!control_is_elevated_) { + ReleaseController(); + } + if (control_.get() == NULL) { BIND_OPTS3 bind_options; memset(&bind_options, 0, sizeof(bind_options)); @@ -254,12 +290,15 @@ HRESULT DaemonControllerWin::ActivateElevatedController() { return hr; } + // Note that we hold a reference to an elevated instance now. + control_is_elevated_ = true; + // Release |control_| upon expiration of the timeout. release_timer_.reset(new base::OneShotTimer<DaemonControllerWin>()); release_timer_->Start(FROM_HERE, base::TimeDelta::FromSeconds(kUacTimeoutSec), this, - &DaemonControllerWin::ReleaseElevatedController); + &DaemonControllerWin::ReleaseController); // Ignore the error. IID_IDaemonControlUi is optional. control_.QueryInterface(IID_IDaemonControlUi, control_ui_.ReceiveVoid()); @@ -268,12 +307,13 @@ HRESULT DaemonControllerWin::ActivateElevatedController() { return S_OK; } -void DaemonControllerWin::ReleaseElevatedController() { +void DaemonControllerWin::ReleaseController() { DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); control_.Release(); control_ui_.Release(); release_timer_.reset(); + control_is_elevated_ = false; } void DaemonControllerWin::OnInstallationComplete( @@ -370,51 +410,35 @@ void DaemonControllerWin::DoGetConfig(const GetConfigCallback& callback) { DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); scoped_ptr<base::DictionaryValue> dictionary_null(NULL); - // Get the name of the configuration file. - FilePath dir = remoting::GetConfigDir(); - FilePath filename = dir.Append(kUnprivilegedConfigFileName); - - // Read raw data from the configuration file. - base::win::ScopedHandle file( - CreateFileW(filename.value().c_str(), - GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - FILE_FLAG_SEQUENTIAL_SCAN, - NULL)); - - if (!file.IsValid()) { - DWORD error = GetLastError(); - LOG_GETLASTERROR(ERROR) - << "Failed to open '" << filename.value() << "'"; + + // Configure and start the Daemon Controller if it is installed already. + HRESULT hr = ActivateController(); + if (FAILED(hr)) { callback.Run(dictionary_null.Pass()); return; } - scoped_array<char> buffer(new char[kMaxConfigFileSize]); - DWORD size = kMaxConfigFileSize; - if (!::ReadFile(file, &buffer[0], size, &size, NULL)) { - DWORD error = GetLastError(); - LOG_GETLASTERROR(ERROR) - << "Failed to read '" << filename.value() << "'"; + // Get the host configuration. + ScopedBstr host_config; + hr = control_->GetConfig(host_config.Receive()); + if (FAILED(hr)) { callback.Run(dictionary_null.Pass()); return; } - // Parse the JSON configuration, expecting it to contain a dictionary. - std::string file_content(buffer.get(), size); - scoped_ptr<base::Value> value( - base::JSONReader::Read(file_content, base::JSON_ALLOW_TRAILING_COMMAS)); + // Parse the string into a dictionary. + string16 file_content(static_cast<BSTR>(host_config), host_config.Length()); + scoped_ptr<base::Value> config( + base::JSONReader::Read(UTF16ToUTF8(file_content), + base::JSON_ALLOW_TRAILING_COMMAS)); - base::DictionaryValue* dictionary = NULL; - if (value.get() == NULL || !value->GetAsDictionary(&dictionary)) { - LOG(ERROR) << "Failed to read '" << filename.value() << "'"; + base::DictionaryValue* dictionary; + if (config.get() == NULL || !config->GetAsDictionary(&dictionary)) { callback.Run(dictionary_null.Pass()); return; } - // Release value, because dictionary points to the same object. - value.release(); + // Release |config|, because dictionary points to the same object. + config.release(); callback.Run(scoped_ptr<base::DictionaryValue>(dictionary)); } |