diff options
author | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-29 14:10:00 +0000 |
---|---|---|
committer | sergeyu@chromium.org <sergeyu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-29 14:10:00 +0000 |
commit | 31f71b329a4ffe735a7af3ceb27dcd559d943a05 (patch) | |
tree | 2a641db384fcb98c08d2e17990766d8047455131 /remoting/host/plugin | |
parent | 19a0ee47090984c3f3bb3f04d5e58656a2075b7b (diff) | |
download | chromium_src-31f71b329a4ffe735a7af3ceb27dcd559d943a05.zip chromium_src-31f71b329a4ffe735a7af3ceb27dcd559d943a05.tar.gz chromium_src-31f71b329a4ffe735a7af3ceb27dcd559d943a05.tar.bz2 |
Move DaemonController to remoting/host/setup
DaemonController will be used outside of the plugin, so it doesn't make
sense to keep it in the plugin directory.
Review URL: https://chromiumcodereview.appspot.com/10985086
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@159402 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'remoting/host/plugin')
-rw-r--r-- | remoting/host/plugin/daemon_controller.h | 151 | ||||
-rw-r--r-- | remoting/host/plugin/daemon_controller_linux.cc | 343 | ||||
-rw-r--r-- | remoting/host/plugin/daemon_controller_mac.cc | 368 | ||||
-rw-r--r-- | remoting/host/plugin/daemon_controller_win.cc | 698 | ||||
-rw-r--r-- | remoting/host/plugin/daemon_installer_win.h | 1 | ||||
-rw-r--r-- | remoting/host/plugin/host_script_object.cc | 1 | ||||
-rw-r--r-- | remoting/host/plugin/host_script_object.h | 2 |
7 files changed, 1 insertions, 1563 deletions
diff --git a/remoting/host/plugin/daemon_controller.h b/remoting/host/plugin/daemon_controller.h deleted file mode 100644 index bf67345..0000000 --- a/remoting/host/plugin/daemon_controller.h +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef REMOTING_HOST_DAEMON_CONTROLLER_H_ -#define REMOTING_HOST_DAEMON_CONTROLLER_H_ - -#include <string> - -#include "base/callback_forward.h" -#include "base/memory/scoped_ptr.h" - -namespace base { -class DictionaryValue; -} // namespace base - -namespace remoting { - -class DaemonController { - public: - // Note that these enumeration values are duplicated in daemon_plugin.js and - // must be kept in sync. - enum State { - // Placeholder state for platforms on which the daemon process is not - // implemented. The web-app will not show the corresponding UI. This value - // will eventually be deprecated or removed. - STATE_NOT_IMPLEMENTED = -1, - // The daemon is not installed. This is functionally equivalent to - // STATE_STOPPED, but the start method is expected to be significantly - // slower, and might involve user interaction. It might be appropriate to - // indicate this in the UI. - STATE_NOT_INSTALLED = 0, - // The daemon is being installed. - STATE_INSTALLING = 1, - // The daemon is installed but not running. Call Start to start it. - STATE_STOPPED = 2, - // The daemon process is starting. - STATE_STARTING = 3, - // The daemon process is running. Call Start again to change the PIN or - // Stop to stop it. - STATE_STARTED = 4, - // The daemon process is stopping. - STATE_STOPPING = 5, - // The state cannot be determined. This could indicate that the plugin - // has not been provided with sufficient information, for example, the - // user for which to query state on a multi-user system. - STATE_UNKNOWN = 6 - }; - - // Enum used for completion callback. - enum AsyncResult { - RESULT_OK = 0, - - // The operation has FAILED. - RESULT_FAILED = 1, - - // User has cancelled the action (e.g. rejected UAC prompt). - // TODO(sergeyu): Current implementations don't return this value. - RESULT_CANCELLED = 2, - - // Failed to access host directory. - RESULT_FAILED_DIRECTORY = 3 - - // TODO(sergeyu): Add more error codes when we know how to handle - // them in the webapp. - }; - - // Callback type for GetConfig(). If the host is configured then a dictionary - // is returned containing host_id and xmpp_login, with security-sensitive - // fields filtered out. An empty dictionary is returned if the host is not - // configured, and NULL if the configuration is corrupt or cannot be read. - typedef base::Callback<void (scoped_ptr<base::DictionaryValue> config)> - GetConfigCallback; - - // Callback used for asynchronous operations, e.g. when - // starting/stopping the service. - typedef base::Callback<void (AsyncResult result)> CompletionCallback; - - // Callback type for GetVersion(). - typedef base::Callback<void (const std::string&)> GetVersionCallback; - - // Callback type for GetUsageStatsConsent(). |supported| indicates whether - // crash dump reporting is supported by the host. |allowed| indicates if - // crash dump reporting is allowed by the user. |set_by_policy| carries - // information whether the crash dump reporting is controlled by policy. - typedef base::Callback<void ( - bool supported, - bool allowed, - bool set_by_policy)> GetUsageStatsConsentCallback; - - virtual ~DaemonController() {} - - // Return the "installed/running" state of the daemon process. - // - // TODO(sergeyu): This method is called synchronously from the - // webapp. In most cases it requires IO operations, so it may block - // the user interface. Replace it with asynchronous notifications, - // e.g. with StartStateNotifications()/StopStateNotifications() methods. - virtual State GetState() = 0; - - // Queries current host configuration. The |callback| is called - // after the configuration is read, and any values that might be security - // sensitive have been filtered out. - virtual void GetConfig(const GetConfigCallback& callback) = 0; - - // Start the daemon process. This may require that the daemon be - // downloaded and installed. |done_callback| is called when the - // operation is finished or fails. - // - // TODO(sergeyu): This method writes config and starts the host - - // these two steps are merged for simplicity. Consider splitting it - // into SetConfig() and Start() once we have basic host setup flow - // working. - virtual void SetConfigAndStart(scoped_ptr<base::DictionaryValue> config, - bool consent, - const CompletionCallback& done) = 0; - - // Updates current host configuration with the values specified in - // |config|. Changes must take effect before the call completes. - // Any value in the existing configuration that isn't specified in |config| - // is preserved. |config| must not contain host_id or xmpp_login values, - // because implementations of this method cannot change them. - virtual void UpdateConfig(scoped_ptr<base::DictionaryValue> config, - const CompletionCallback& done_callback) = 0; - - // Stop the daemon process. It is permitted to call Stop while the daemon - // process is being installed, in which case the installation should be - // aborted if possible; if not then it is sufficient to ensure that the - // daemon process is not started automatically upon successful installation. - // As with Start, Stop may return before the operation is complete--poll - // GetState until the state is STATE_STOPPED. - virtual void Stop(const CompletionCallback& done_callback) = 0; - - // Caches the native handle of the plugin window so it can be used to focus - // elevation prompts properly. - virtual void SetWindow(void* window_handle) = 0; - - // Get the version of the daemon as a dotted decimal string of the form - // major.minor.build.patch, if it is installed, or "" otherwise. - virtual void GetVersion(const GetVersionCallback& done_callback) = 0; - - // Get the user's consent to crash reporting. - virtual void GetUsageStatsConsent( - const GetUsageStatsConsentCallback& done) = 0; - - static scoped_ptr<DaemonController> Create(); -}; - -} // namespace remoting - -#endif // REMOTING_HOST_DAEMON_CONTROLLER_H_ diff --git a/remoting/host/plugin/daemon_controller_linux.cc b/remoting/host/plugin/daemon_controller_linux.cc deleted file mode 100644 index ab2e087..0000000 --- a/remoting/host/plugin/daemon_controller_linux.cc +++ /dev/null @@ -1,343 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "remoting/host/plugin/daemon_controller.h" - -#include <unistd.h> - -#include "base/basictypes.h" -#include "base/bind.h" -#include "base/command_line.h" -#include "base/compiler_specific.h" -#include "base/environment.h" -#include "base/file_path.h" -#include "base/file_util.h" -#include "base/json/json_writer.h" -#include "base/logging.h" -#include "base/md5.h" -#include "base/process_util.h" -#include "base/string_number_conversions.h" -#include "base/string_split.h" -#include "base/string_util.h" -#include "base/threading/thread.h" -#include "base/values.h" -#include "net/base/net_util.h" -#include "remoting/host/host_config.h" -#include "remoting/host/json_host_config.h" -#include "remoting/host/usage_stats_consent.h" - -namespace remoting { - -namespace { - -const char kDaemonScript[] = - "/opt/google/chrome-remote-desktop/chrome-remote-desktop"; - -// Timeout for running daemon script. -const int64 kDaemonTimeoutMs = 5000; - -// Timeout for commands that require password prompt- 1 minute; -const int64 kSudoTimeoutMs = 60000; - -std::string GetMd5(const std::string& value) { - base::MD5Context ctx; - base::MD5Init(&ctx); - base::MD5Update(&ctx, value); - base::MD5Digest digest; - base::MD5Final(&digest, &ctx); - return StringToLowerASCII(base::HexEncode(digest.a, sizeof(digest.a))); -} - -class DaemonControllerLinux : public remoting::DaemonController { - public: - DaemonControllerLinux(); - - virtual State GetState() OVERRIDE; - virtual void GetConfig(const GetConfigCallback& callback) OVERRIDE; - virtual void SetConfigAndStart( - scoped_ptr<base::DictionaryValue> config, - bool consent, - const CompletionCallback& done) OVERRIDE; - virtual void UpdateConfig(scoped_ptr<base::DictionaryValue> config, - const CompletionCallback& done_callback) OVERRIDE; - virtual void Stop(const CompletionCallback& done_callback) OVERRIDE; - virtual void SetWindow(void* window_handle) OVERRIDE; - virtual void GetVersion(const GetVersionCallback& done_callback) OVERRIDE; - virtual void GetUsageStatsConsent( - const GetUsageStatsConsentCallback& done) OVERRIDE; - - private: - FilePath GetConfigPath(); - - void DoGetConfig(const GetConfigCallback& callback); - void DoSetConfigAndStart(scoped_ptr<base::DictionaryValue> config, - const CompletionCallback& done); - void DoUpdateConfig(scoped_ptr<base::DictionaryValue> config, - const CompletionCallback& done_callback); - void DoStop(const CompletionCallback& done_callback); - void DoGetVersion(const GetVersionCallback& done_callback); - - base::Thread file_io_thread_; - - DISALLOW_COPY_AND_ASSIGN(DaemonControllerLinux); -}; - -DaemonControllerLinux::DaemonControllerLinux() - : file_io_thread_("DaemonControllerFileIO") { - file_io_thread_.Start(); -} - -static bool GetScriptPath(FilePath* result) { - FilePath candidate_exe(kDaemonScript); - if (access(candidate_exe.value().c_str(), X_OK) == 0) { - *result = candidate_exe; - return true; - } - return false; -} - -static bool RunHostScriptWithTimeout( - const std::vector<std::string>& args, - base::TimeDelta timeout, - int* exit_code) { - // As long as we're relying on running an external binary from the - // PATH, don't do it as root. - if (getuid() == 0) { - return false; - } - FilePath script_path; - if (!GetScriptPath(&script_path)) { - return false; - } - CommandLine command_line(script_path); - for (unsigned int i = 0; i < args.size(); ++i) { - command_line.AppendArg(args[i]); - } - base::ProcessHandle process_handle; - bool result = base::LaunchProcess(command_line, - base::LaunchOptions(), - &process_handle); - if (result) { - if (exit_code) { - result = base::WaitForExitCodeWithTimeout( - process_handle, exit_code, timeout); - } - base::CloseProcessHandle(process_handle); - } - return result; -} - -static bool RunHostScript(const std::vector<std::string>& args, - int* exit_code) { - return RunHostScriptWithTimeout( - args, base::TimeDelta::FromMilliseconds(kDaemonTimeoutMs), exit_code); -} - -remoting::DaemonController::State DaemonControllerLinux::GetState() { - std::vector<std::string> args; - args.push_back("--check-running"); - int exit_code = 0; - if (!RunHostScript(args, &exit_code)) { - // TODO(jamiewalch): When we have a good story for installing, return - // NOT_INSTALLED rather than NOT_IMPLEMENTED (the former suppresses - // the relevant UI in the web-app). - return remoting::DaemonController::STATE_NOT_IMPLEMENTED; - } - - if (exit_code == 0) { - return remoting::DaemonController::STATE_STARTED; - } else { - return remoting::DaemonController::STATE_STOPPED; - } -} - -void DaemonControllerLinux::GetConfig(const GetConfigCallback& callback) { - // base::Unretained() is safe because we control lifetime of the thread. - file_io_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( - &DaemonControllerLinux::DoGetConfig, base::Unretained(this), callback)); -} - -void DaemonControllerLinux::GetUsageStatsConsent( - const GetUsageStatsConsentCallback& done) { - // Crash dump collection is not implemented on Linux yet. - // http://crbug.com/130678. - done.Run(false, false, false); -} - -void DaemonControllerLinux::SetConfigAndStart( - scoped_ptr<base::DictionaryValue> config, - bool /* consent */, - const CompletionCallback& done) { - // base::Unretained() is safe because we control lifetime of the thread. - file_io_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( - &DaemonControllerLinux::DoSetConfigAndStart, base::Unretained(this), - base::Passed(&config), done)); -} - -void DaemonControllerLinux::UpdateConfig( - scoped_ptr<base::DictionaryValue> config, - const CompletionCallback& done_callback) { - file_io_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( - &DaemonControllerLinux::DoUpdateConfig, base::Unretained(this), - base::Passed(&config), done_callback)); -} - -void DaemonControllerLinux::Stop(const CompletionCallback& done_callback) { - file_io_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( - &DaemonControllerLinux::DoStop, base::Unretained(this), - done_callback)); -} - -void DaemonControllerLinux::SetWindow(void* window_handle) { - // noop -} - -void DaemonControllerLinux::GetVersion( - const GetVersionCallback& done_callback) { - file_io_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( - &DaemonControllerLinux::DoGetVersion, base::Unretained(this), - done_callback)); -} - -FilePath DaemonControllerLinux::GetConfigPath() { - std::string filename = "host#" + GetMd5(net::GetHostName()) + ".json"; - return file_util::GetHomeDir(). - Append(".config/chrome-remote-desktop").Append(filename); -} - -void DaemonControllerLinux::DoGetConfig(const GetConfigCallback& callback) { - scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue()); - - if (GetState() != remoting::DaemonController::STATE_NOT_IMPLEMENTED) { - JsonHostConfig config(GetConfigPath()); - if (config.Read()) { - std::string value; - if (config.GetString(kHostIdConfigPath, &value)) { - result->SetString(kHostIdConfigPath, value); - } - if (config.GetString(kXmppLoginConfigPath, &value)) { - result->SetString(kXmppLoginConfigPath, value); - } - } else { - result.reset(); // Return NULL in case of error. - } - } - - callback.Run(result.Pass()); -} - -void DaemonControllerLinux::DoSetConfigAndStart( - scoped_ptr<base::DictionaryValue> config, - const CompletionCallback& done_callback) { - - // Add the user to chrome-remote-desktop group first. - std::vector<std::string> args; - args.push_back("--add-user"); - int exit_code; - if (!RunHostScriptWithTimeout( - args, base::TimeDelta::FromMilliseconds(kSudoTimeoutMs), - &exit_code) || - exit_code != 0) { - LOG(ERROR) << "Failed to add user to chrome-remote-desktop group."; - done_callback.Run(RESULT_FAILED); - return; - } - - // Write config. - JsonHostConfig config_file(GetConfigPath()); - if (!config_file.CopyFrom(config.get()) || - !config_file.Save()) { - LOG(ERROR) << "Failed to update config file."; - done_callback.Run(RESULT_FAILED); - return; - } - - // Finally start the host. - args.clear(); - args.push_back("--start"); - AsyncResult result; - if (RunHostScript(args, &exit_code)) { - result = (exit_code == 0) ? RESULT_OK : RESULT_FAILED; - } else { - result = RESULT_FAILED; - } - done_callback.Run(result); -} - -void DaemonControllerLinux::DoUpdateConfig( - scoped_ptr<base::DictionaryValue> config, - const CompletionCallback& done_callback) { - JsonHostConfig config_file(GetConfigPath()); - if (!config_file.Read() || - !config_file.CopyFrom(config.get()) || - !config_file.Save()) { - LOG(ERROR) << "Failed to update config file."; - done_callback.Run(RESULT_FAILED); - return; - } - - std::vector<std::string> args; - args.push_back("--reload"); - AsyncResult result; - int exit_code; - if (RunHostScript(args, &exit_code)) { - result = (exit_code == 0) ? RESULT_OK : RESULT_FAILED; - } else { - result = RESULT_FAILED; - } - - done_callback.Run(result); -} - -void DaemonControllerLinux::DoStop(const CompletionCallback& done_callback) { - std::vector<std::string> args; - args.push_back("--stop"); - int exit_code = 0; - AsyncResult result; - if (RunHostScript(args, &exit_code)) { - result = (exit_code == 0) ? RESULT_OK : RESULT_FAILED; - } else { - result = RESULT_FAILED; - } - done_callback.Run(result); -} - -void DaemonControllerLinux::DoGetVersion( - const GetVersionCallback& done_callback) { - FilePath script_path; - if (!GetScriptPath(&script_path)) { - done_callback.Run(""); - return; - } - CommandLine command_line(script_path); - command_line.AppendArg("--host-version"); - - std::string version; - int exit_code = 0; - int result = - base::GetAppOutputWithExitCode(command_line, &version, &exit_code); - if (!result || exit_code != 0) { - LOG(ERROR) << "Failed to run \"" << command_line.GetCommandLineString() - << "\". Exit code: " << exit_code; - done_callback.Run(""); - return; - } - - TrimWhitespaceASCII(version, TRIM_ALL, &version); - if (!ContainsOnlyChars(version, "0123456789.")) { - LOG(ERROR) << "Received invalid host version number: " << version; - done_callback.Run(""); - return; - } - - done_callback.Run(version); -} - -} // namespace - -scoped_ptr<DaemonController> remoting::DaemonController::Create() { - return scoped_ptr<DaemonController>(new DaemonControllerLinux()); -} - -} // namespace remoting diff --git a/remoting/host/plugin/daemon_controller_mac.cc b/remoting/host/plugin/daemon_controller_mac.cc deleted file mode 100644 index 54c59b3..0000000 --- a/remoting/host/plugin/daemon_controller_mac.cc +++ /dev/null @@ -1,368 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "remoting/host/plugin/daemon_controller.h" - -#include <launch.h> -#include <stdio.h> -#include <sys/types.h> - -#include "base/basictypes.h" -#include "base/bind.h" -#include "base/compiler_specific.h" -#include "base/file_path.h" -#include "base/file_util.h" -#include "base/json/json_writer.h" -#include "base/logging.h" -#include "base/mac/foundation_util.h" -#include "base/mac/launchd.h" -#include "base/mac/mac_logging.h" -#include "base/mac/mac_util.h" -#include "base/mac/scoped_launch_data.h" -#include "base/threading/thread.h" -#include "base/time.h" -#include "base/values.h" -#include "remoting/host/constants_mac.h" -#include "remoting/host/json_host_config.h" -#include "remoting/host/usage_stats_consent.h" - -namespace remoting { - -namespace { - -// The NSSystemDirectories.h header has a conflicting definition of -// NSSearchPathDirectory with the one in base/mac/foundation_util.h. -// Foundation.h would work, but it can only be included from Objective-C files. -// Therefore, we define the needed constants here. -const int NSLibraryDirectory = 5; - -class DaemonControllerMac : public remoting::DaemonController { - public: - DaemonControllerMac(); - virtual ~DaemonControllerMac(); - - virtual State GetState() OVERRIDE; - virtual void GetConfig(const GetConfigCallback& callback) OVERRIDE; - virtual void SetConfigAndStart( - scoped_ptr<base::DictionaryValue> config, - bool consent, - const CompletionCallback& done) OVERRIDE; - virtual void UpdateConfig(scoped_ptr<base::DictionaryValue> config, - const CompletionCallback& done_callback) OVERRIDE; - virtual void Stop(const CompletionCallback& done_callback) OVERRIDE; - virtual void SetWindow(void* window_handle) OVERRIDE; - virtual void GetVersion(const GetVersionCallback& done_callback) OVERRIDE; - virtual void GetUsageStatsConsent( - const GetUsageStatsConsentCallback& callback) OVERRIDE; - - private: - void DoGetConfig(const GetConfigCallback& callback); - void DoGetVersion(const GetVersionCallback& callback); - void DoSetConfigAndStart(scoped_ptr<base::DictionaryValue> config, - const CompletionCallback& done); - void DoUpdateConfig(scoped_ptr<base::DictionaryValue> config, - const CompletionCallback& done_callback); - void DoStop(const CompletionCallback& done_callback); - - void ShowPreferencePane(const std::string& config_data, - const CompletionCallback& done_callback); - void RegisterForPreferencePaneNotifications( - const CompletionCallback &done_callback); - void DeregisterForPreferencePaneNotifications(); - void PreferencePaneCallbackDelegate(CFStringRef name); - static bool DoShowPreferencePane(const std::string& config_data); - static void PreferencePaneCallback(CFNotificationCenterRef center, - void* observer, - CFStringRef name, - const void* object, - CFDictionaryRef user_info); - - base::Thread auth_thread_; - CompletionCallback current_callback_; - - DISALLOW_COPY_AND_ASSIGN(DaemonControllerMac); -}; - -DaemonControllerMac::DaemonControllerMac() - : auth_thread_("Auth thread") { - auth_thread_.Start(); -} - -DaemonControllerMac::~DaemonControllerMac() { - auth_thread_.Stop(); - DeregisterForPreferencePaneNotifications(); -} - -void DaemonControllerMac::DeregisterForPreferencePaneNotifications() { - CFNotificationCenterRemoveObserver( - CFNotificationCenterGetDistributedCenter(), - this, - CFSTR(UPDATE_SUCCEEDED_NOTIFICATION_NAME), - NULL); - CFNotificationCenterRemoveObserver( - CFNotificationCenterGetDistributedCenter(), - this, - CFSTR(UPDATE_FAILED_NOTIFICATION_NAME), - NULL); -} - -DaemonController::State DaemonControllerMac::GetState() { - pid_t job_pid = base::mac::PIDForJob(kServiceName); - if (job_pid < 0) { - return DaemonController::STATE_NOT_INSTALLED; - } else if (job_pid == 0) { - // Service is stopped, or a start attempt failed. - return DaemonController::STATE_STOPPED; - } else { - return DaemonController::STATE_STARTED; - } -} - -void DaemonControllerMac::GetConfig(const GetConfigCallback& callback) { - // base::Unretained() is safe, since this object owns the thread and therefore - // outlives it. - auth_thread_.message_loop_proxy()->PostTask( - FROM_HERE, - base::Bind(&DaemonControllerMac::DoGetConfig, base::Unretained(this), - callback)); -} - -void DaemonControllerMac::SetConfigAndStart( - scoped_ptr<base::DictionaryValue> config, - bool /* consent */, - const CompletionCallback& done) { - auth_thread_.message_loop_proxy()->PostTask( - FROM_HERE, base::Bind( - &DaemonControllerMac::DoSetConfigAndStart, base::Unretained(this), - base::Passed(&config), done)); -} - -void DaemonControllerMac::UpdateConfig( - scoped_ptr<base::DictionaryValue> config, - const CompletionCallback& done_callback) { - auth_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( - &DaemonControllerMac::DoUpdateConfig, base::Unretained(this), - base::Passed(&config), done_callback)); -} - -void DaemonControllerMac::Stop(const CompletionCallback& done_callback) { - auth_thread_.message_loop_proxy()->PostTask( - FROM_HERE, base::Bind( - &DaemonControllerMac::DoStop, base::Unretained(this), done_callback)); -} - -void DaemonControllerMac::SetWindow(void* window_handle) { - // noop -} - -void DaemonControllerMac::GetVersion(const GetVersionCallback& callback) { - auth_thread_.message_loop_proxy()->PostTask( - FROM_HERE, - base::Bind(&DaemonControllerMac::DoGetVersion, base::Unretained(this), - callback)); -} - -void DaemonControllerMac::GetUsageStatsConsent( - const GetUsageStatsConsentCallback& callback) { - // Crash dump collection is not implemented on Mac yet. - // http://crbug.com/130678. - callback.Run(false, false, false); -} - -void DaemonControllerMac::DoGetConfig(const GetConfigCallback& callback) { - FilePath config_path(kHostConfigFilePath); - JsonHostConfig host_config(config_path); - scoped_ptr<base::DictionaryValue> config; - - if (host_config.Read()) { - config.reset(new base::DictionaryValue()); - std::string value; - if (host_config.GetString(kHostIdConfigPath, &value)) - config.get()->SetString(kHostIdConfigPath, value); - if (host_config.GetString(kXmppLoginConfigPath, &value)) - config.get()->SetString(kXmppLoginConfigPath, value); - } - - callback.Run(config.Pass()); -} - -void DaemonControllerMac::DoGetVersion(const GetVersionCallback& callback) { - std::string version = ""; - std::string command_line = remoting::kHostHelperScriptPath; - command_line += " --host-version"; - FILE* script_output = popen(command_line.c_str(), "r"); - if (script_output) { - char buffer[100]; - char* result = fgets(buffer, sizeof(buffer), script_output); - pclose(script_output); - if (result) { - // The string is guaranteed to be null-terminated, but probably contains - // a newline character, which we don't want. - for (int i = 0; result[i]; ++i) { - if (result[i] < ' ') { - result[i] = 0; - break; - } - } - version = result; - } - } - callback.Run(version); -} - -void DaemonControllerMac::DoSetConfigAndStart( - scoped_ptr<base::DictionaryValue> config, - const CompletionCallback& done) { - std::string config_data; - base::JSONWriter::Write(config.get(), &config_data); - ShowPreferencePane(config_data, done); -} - -void DaemonControllerMac::DoUpdateConfig( - scoped_ptr<base::DictionaryValue> config, - const CompletionCallback& done_callback) { - FilePath config_file_path(kHostConfigFilePath); - JsonHostConfig config_file(config_file_path); - if (!config_file.Read()) { - done_callback.Run(RESULT_FAILED); - return; - } - if (!config_file.CopyFrom(config.get())) { - LOG(ERROR) << "Failed to update configuration."; - done_callback.Run(RESULT_FAILED); - return; - } - - std::string config_data = config_file.GetSerializedData(); - ShowPreferencePane(config_data, done_callback); -} - -void DaemonControllerMac::ShowPreferencePane( - const std::string& config_data, const CompletionCallback& done_callback) { - if (DoShowPreferencePane(config_data)) { - RegisterForPreferencePaneNotifications(done_callback); - } else { - done_callback.Run(RESULT_FAILED); - } -} - -bool DaemonControllerMac::DoShowPreferencePane(const std::string& config_data) { - if (!config_data.empty()) { - FilePath config_path; - if (!file_util::GetTempDir(&config_path)) { - LOG(ERROR) << "Failed to get filename for saving configuration data."; - return false; - } - config_path = config_path.Append(kHostConfigFileName); - - int written = file_util::WriteFile(config_path, config_data.data(), - config_data.size()); - if (written != static_cast<int>(config_data.size())) { - LOG(ERROR) << "Failed to save configuration data to: " - << config_path.value(); - return false; - } - } - - FilePath pane_path; - // TODO(lambroslambrou): Use NSPreferencePanesDirectory once we start - // building against SDK 10.6. - if (!base::mac::GetLocalDirectory(NSLibraryDirectory, &pane_path)) { - LOG(ERROR) << "Failed to get directory for local preference panes."; - return false; - } - pane_path = pane_path.Append("PreferencePanes").Append(kPrefPaneFileName); - - FSRef pane_path_ref; - if (!base::mac::FSRefFromPath(pane_path.value(), &pane_path_ref)) { - LOG(ERROR) << "Failed to create FSRef"; - return false; - } - OSStatus status = LSOpenFSRef(&pane_path_ref, NULL); - if (status != noErr) { - OSSTATUS_LOG(ERROR, status) << "LSOpenFSRef failed for path: " - << pane_path.value(); - return false; - } - - CFNotificationCenterRef center = - CFNotificationCenterGetDistributedCenter(); - base::mac::ScopedCFTypeRef<CFStringRef> service_name( - CFStringCreateWithCString(kCFAllocatorDefault, remoting::kServiceName, - kCFStringEncodingUTF8)); - CFNotificationCenterPostNotification(center, service_name, NULL, NULL, - TRUE); - return true; -} - -void DaemonControllerMac::DoStop(const CompletionCallback& done_callback) { - ShowPreferencePane("", done_callback); -} - -// CFNotificationCenterAddObserver ties the thread on which distributed -// notifications are received to the one on which it is first called. -// This is safe because HostNPScriptObject::InvokeAsyncResultCallback -// bounces the invocation to the correct thread, so it doesn't matter -// which thread CompletionCallbacks are called on. -void DaemonControllerMac::RegisterForPreferencePaneNotifications( - const CompletionCallback& done_callback) { - // We can only have one callback registered at a time. This is enforced by the - // UX flow of the web-app. - DCHECK(current_callback_.is_null()); - current_callback_ = done_callback; - - CFNotificationCenterAddObserver( - CFNotificationCenterGetDistributedCenter(), - this, - &DaemonControllerMac::PreferencePaneCallback, - CFSTR(UPDATE_SUCCEEDED_NOTIFICATION_NAME), - NULL, - CFNotificationSuspensionBehaviorDeliverImmediately); - CFNotificationCenterAddObserver( - CFNotificationCenterGetDistributedCenter(), - this, - &DaemonControllerMac::PreferencePaneCallback, - CFSTR(UPDATE_FAILED_NOTIFICATION_NAME), - NULL, - CFNotificationSuspensionBehaviorDeliverImmediately); -} - -void DaemonControllerMac::PreferencePaneCallbackDelegate(CFStringRef name) { - AsyncResult result = RESULT_FAILED; - if (CFStringCompare(name, CFSTR(UPDATE_SUCCEEDED_NOTIFICATION_NAME), 0) == - kCFCompareEqualTo) { - result = RESULT_OK; - } else if (CFStringCompare(name, CFSTR(UPDATE_FAILED_NOTIFICATION_NAME), 0) == - kCFCompareEqualTo) { - result = RESULT_FAILED; - } else { - LOG(WARNING) << "Ignoring unexpected notification: " << name; - return; - } - DCHECK(!current_callback_.is_null()); - current_callback_.Run(result); - current_callback_.Reset(); - DeregisterForPreferencePaneNotifications(); -} - -void DaemonControllerMac::PreferencePaneCallback(CFNotificationCenterRef center, - void* observer, - CFStringRef name, - const void* object, - CFDictionaryRef user_info) { - DaemonControllerMac* self = reinterpret_cast<DaemonControllerMac*>(observer); - if (self) { - self->PreferencePaneCallbackDelegate(name); - } else { - LOG(WARNING) << "Ignoring notification with NULL observer: " << name; - } -} - -} // namespace - -scoped_ptr<DaemonController> remoting::DaemonController::Create() { - return scoped_ptr<DaemonController>(new DaemonControllerMac()); -} - -} // namespace remoting diff --git a/remoting/host/plugin/daemon_controller_win.cc b/remoting/host/plugin/daemon_controller_win.cc deleted file mode 100644 index 2985652..0000000 --- a/remoting/host/plugin/daemon_controller_win.cc +++ /dev/null @@ -1,698 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "remoting/host/plugin/daemon_controller.h" - -#include <objbase.h> - -#include "base/basictypes.h" -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "base/compiler_specific.h" -#include "base/file_path.h" -#include "base/file_util.h" -#include "base/json/json_reader.h" -#include "base/json/json_writer.h" -#include "base/logging.h" -#include "base/string16.h" -#include "base/threading/thread.h" -#include "base/time.h" -#include "base/timer.h" -#include "base/utf_string_conversions.h" -#include "base/values.h" -#include "base/win/scoped_bstr.h" -#include "base/win/scoped_comptr.h" -#include "base/win/windows_version.h" -#include "remoting/base/scoped_sc_handle_win.h" -#include "remoting/host/branding.h" -#include "remoting/host/plugin/daemon_installer_win.h" -#include "remoting/host/usage_stats_consent.h" - -// MIDL-generated declarations and definitions. -#include "remoting/host/elevated_controller.h" - -using base::win::ScopedBstr; -using base::win::ScopedComPtr; - -namespace remoting { - -namespace { - -// ProgID of the daemon controller. -const wchar_t kDaemonController[] = - L"ChromotingElevatedController.ElevatedController"; - -// The COM elevation moniker for the Elevated Controller. -const wchar_t kDaemonControllerElevationMoniker[] = - L"Elevation:Administrator!new:" - L"ChromotingElevatedController.ElevatedController"; - -// Name of the Daemon Controller's worker thread. -const char kDaemonControllerThreadName[] = "Daemon Controller thread"; - -// The maximum duration of keeping a reference to a privileged instance of -// the Daemon Controller. This effectively reduces number of UAC prompts a user -// sees. -const int kPrivilegedTimeoutSec = 5 * 60; - -// The maximum duration of keeping a reference to an unprivileged instance of -// the Daemon Controller. This interval should not be too long. If upgrade -// happens while there is a live reference to a Daemon Controller instance -// the old binary still can be used. So dropping the references often makes sure -// that the old binary will go away sooner. -const int kUnprivilegedTimeoutSec = 60; - -// A base::Thread implementation that initializes COM on the new thread. -class ComThread : public base::Thread { - public: - explicit ComThread(const char* name); - - bool Start(); - - protected: - virtual void Init() OVERRIDE; - virtual void CleanUp() OVERRIDE; - - DISALLOW_COPY_AND_ASSIGN(ComThread); -}; - -class DaemonControllerWin : public remoting::DaemonController { - public: - DaemonControllerWin(); - virtual ~DaemonControllerWin(); - - virtual State GetState() OVERRIDE; - virtual void GetConfig(const GetConfigCallback& callback) OVERRIDE; - virtual void SetConfigAndStart( - scoped_ptr<base::DictionaryValue> config, - bool consent, - const CompletionCallback& done) OVERRIDE; - virtual void UpdateConfig(scoped_ptr<base::DictionaryValue> config, - const CompletionCallback& done_callback) OVERRIDE; - virtual void Stop(const CompletionCallback& done_callback) OVERRIDE; - virtual void SetWindow(void* window_handle) OVERRIDE; - virtual void GetVersion(const GetVersionCallback& done_callback) OVERRIDE; - virtual void GetUsageStatsConsent( - const GetUsageStatsConsentCallback& done) OVERRIDE; - - private: - // Activates an unprivileged instance of the daemon controller and caches it. - HRESULT ActivateController(); - - // Activates an instance of the daemon controller and caches it. If COM - // Elevation is supported (Vista+) the activated instance is elevated, - // otherwise it is activated under credentials of the caller. - HRESULT ActivateElevatedController(); - - // Releases the cached instance of the controller. - void ReleaseController(); - - // Procedes with the daemon configuration if the installation succeeded, - // otherwise reports the error. - void OnInstallationComplete(scoped_ptr<base::DictionaryValue> config, - bool consent, - const CompletionCallback& done, - HRESULT result); - - // Opens the Chromoting service returning its handle in |service_out|. - DWORD OpenService(ScopedScHandle* service_out); - - // Converts a config dictionary to a scoped BSTR. - static void ConfigToString(const base::DictionaryValue& config, - ScopedBstr* out); - - // Converts a Windows service status code to a Daemon state. - static State ConvertToDaemonState(DWORD service_state); - - // Converts HRESULT to the AsyncResult. - static AsyncResult HResultToAsyncResult(HRESULT hr); - - // The functions that actually do the work. They should be called in - // the context of |worker_thread_|; - void DoGetConfig(const GetConfigCallback& callback); - void DoInstallAsNeededAndStart(scoped_ptr<base::DictionaryValue> config, - bool consent, - const CompletionCallback& done_callback); - void DoSetConfigAndStart(scoped_ptr<base::DictionaryValue> config, - bool consent, - const CompletionCallback& done); - void DoUpdateConfig(scoped_ptr<base::DictionaryValue> config, - const CompletionCallback& done_callback); - void DoStop(const CompletionCallback& done_callback); - void DoSetWindow(void* window_handle); - void DoGetVersion(const GetVersionCallback& callback); - void DoGetUsageStatsConsent( - const GetUsageStatsConsentCallback& done); - - // |control_| and |control2_| hold references to an instance of the daemon - // controller to prevent a UAC prompt on every operation. - ScopedComPtr<IDaemonControl> control_; - ScopedComPtr<IDaemonControl2> control2_; - - // 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_; - - // Handle of the plugin window. - HWND window_handle_; - - // The worker thread used for servicing long running operations. - ComThread worker_thread_; - - scoped_ptr<DaemonInstallerWin> installer_; - - DISALLOW_COPY_AND_ASSIGN(DaemonControllerWin); -}; - -ComThread::ComThread(const char* name) : base::Thread(name) { -} - -bool ComThread::Start() { - // N.B. The single threaded COM apartment must be run on a UI message loop. - base::Thread::Options thread_options(MessageLoop::TYPE_UI, 0); - return StartWithOptions(thread_options); -} - -void ComThread::Init() { - CoInitialize(NULL); -} - -void ComThread::CleanUp() { - CoUninitialize(); -} - -DaemonControllerWin::DaemonControllerWin() - : control_is_elevated_(false), - window_handle_(NULL), - worker_thread_(kDaemonControllerThreadName) { - if (!worker_thread_.Start()) { - LOG(FATAL) << "Failed to start the Daemon Controller worker thread."; - } -} - -DaemonControllerWin::~DaemonControllerWin() { - // Clean up resources allocated on the worker thread. - worker_thread_.message_loop_proxy()->PostTask( - FROM_HERE, - base::Bind(&DaemonControllerWin::ReleaseController, - base::Unretained(this))); - worker_thread_.Stop(); -} - -remoting::DaemonController::State DaemonControllerWin::GetState() { - if (base::win::GetVersion() < base::win::VERSION_XP) { - return STATE_NOT_IMPLEMENTED; - } - // TODO(alexeypa): Make the thread alertable, so we can switch to APC - // notifications rather than polling. - ScopedScHandle service; - DWORD error = OpenService(&service); - - switch (error) { - case ERROR_SUCCESS: { - SERVICE_STATUS status; - if (::QueryServiceStatus(service, &status)) { - return ConvertToDaemonState(status.dwCurrentState); - } else { - LOG_GETLASTERROR(ERROR) - << "Failed to query the state of the '" << kWindowsServiceName - << "' service"; - return STATE_UNKNOWN; - } - break; - } - case ERROR_SERVICE_DOES_NOT_EXIST: - return STATE_NOT_INSTALLED; - default: - return STATE_UNKNOWN; - } -} - -void DaemonControllerWin::GetConfig(const GetConfigCallback& callback) { - worker_thread_.message_loop_proxy()->PostTask( - FROM_HERE, - base::Bind(&DaemonControllerWin::DoGetConfig, - base::Unretained(this), callback)); -} - -void DaemonControllerWin::SetConfigAndStart( - scoped_ptr<base::DictionaryValue> config, - bool consent, - const CompletionCallback& done) { - worker_thread_.message_loop_proxy()->PostTask( - FROM_HERE, base::Bind( - &DaemonControllerWin::DoInstallAsNeededAndStart, - base::Unretained(this), base::Passed(&config), consent, done)); -} - -void DaemonControllerWin::UpdateConfig( - scoped_ptr<base::DictionaryValue> config, - const CompletionCallback& done_callback) { - worker_thread_.message_loop_proxy()->PostTask( - FROM_HERE, base::Bind( - &DaemonControllerWin::DoUpdateConfig, - base::Unretained(this), base::Passed(&config), done_callback)); -} - -void DaemonControllerWin::Stop(const CompletionCallback& done_callback) { - worker_thread_.message_loop_proxy()->PostTask( - FROM_HERE, base::Bind( - &DaemonControllerWin::DoStop, base::Unretained(this), - done_callback)); -} - -void DaemonControllerWin::SetWindow(void* window_handle) { - worker_thread_.message_loop_proxy()->PostTask( - FROM_HERE, base::Bind( - &DaemonControllerWin::DoSetWindow, base::Unretained(this), - window_handle)); -} - -void DaemonControllerWin::GetVersion(const GetVersionCallback& callback) { - worker_thread_.message_loop_proxy()->PostTask( - FROM_HERE, - base::Bind(&DaemonControllerWin::DoGetVersion, - base::Unretained(this), callback)); -} - -void DaemonControllerWin::GetUsageStatsConsent( - const GetUsageStatsConsentCallback& done) { - worker_thread_.message_loop_proxy()->PostTask( - FROM_HERE, - base::Bind(&DaemonControllerWin::DoGetUsageStatsConsent, - base::Unretained(this), done)); -} - -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; - } - - // Ignore the error. IID_IDaemonControl2 is optional. - control_.QueryInterface(IID_IDaemonControl2, control2_.ReceiveVoid()); - - // Release |control_| upon expiration of the timeout. - release_timer_.reset(new base::OneShotTimer<DaemonControllerWin>()); - release_timer_->Start(FROM_HERE, - base::TimeDelta::FromSeconds(kUnprivilegedTimeoutSec), - this, - &DaemonControllerWin::ReleaseController); - } - - return S_OK; -} - -HRESULT DaemonControllerWin::ActivateElevatedController() { - DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); - - // The COM elevation is supported on Vista and above. - if (base::win::GetVersion() < base::win::VERSION_VISTA) { - return ActivateController(); - } - - // 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)); - bind_options.cbStruct = sizeof(bind_options); - bind_options.hwnd = GetTopLevelWindow(window_handle_); - bind_options.dwClassContext = CLSCTX_LOCAL_SERVER; - - HRESULT hr = ::CoGetObject( - kDaemonControllerElevationMoniker, - &bind_options, - IID_IDaemonControl, - control_.ReceiveVoid()); - if (FAILED(hr)) { - return hr; - } - - // Ignore the error. IID_IDaemonControl2 is optional. - control_.QueryInterface(IID_IDaemonControl2, control2_.ReceiveVoid()); - - // 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(kPrivilegedTimeoutSec), - this, - &DaemonControllerWin::ReleaseController); - } - - return S_OK; -} - -void DaemonControllerWin::ReleaseController() { - DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); - - control_.Release(); - control2_.Release(); - release_timer_.reset(); - control_is_elevated_ = false; -} - -void DaemonControllerWin::OnInstallationComplete( - scoped_ptr<base::DictionaryValue> config, - bool consent, - const CompletionCallback& done, - HRESULT result) { - DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); - - if (SUCCEEDED(result)) { - DoSetConfigAndStart(config.Pass(), consent, done); - } else { - LOG(ERROR) << "Failed to install the Chromoting Host " - << "(error: 0x" << std::hex << result << std::dec << ")."; - done.Run(HResultToAsyncResult(result)); - } - - DCHECK(installer_.get() != NULL); - installer_.reset(); -} - -DWORD DaemonControllerWin::OpenService(ScopedScHandle* service_out) { - // Open the service and query its current state. - ScopedScHandle scmanager( - ::OpenSCManagerW(NULL, SERVICES_ACTIVE_DATABASE, - SC_MANAGER_CONNECT | SC_MANAGER_ENUMERATE_SERVICE)); - if (!scmanager.IsValid()) { - DWORD error = GetLastError(); - LOG_GETLASTERROR(ERROR) - << "Failed to connect to the service control manager"; - return error; - } - - ScopedScHandle service( - ::OpenServiceW(scmanager, kWindowsServiceName, SERVICE_QUERY_STATUS)); - if (!service.IsValid()) { - DWORD error = GetLastError(); - if (error != ERROR_SERVICE_DOES_NOT_EXIST) { - LOG_GETLASTERROR(ERROR) - << "Failed to open to the '" << kWindowsServiceName << "' service"; - } - return error; - } - - service_out->Set(service.Take()); - return ERROR_SUCCESS; -} - -// static -void DaemonControllerWin::ConfigToString(const base::DictionaryValue& config, - ScopedBstr* out) { - std::string config_str; - base::JSONWriter::Write(&config, &config_str); - ScopedBstr config_scoped_bstr(UTF8ToUTF16(config_str).c_str()); - out->Swap(config_scoped_bstr); -} - -// static -remoting::DaemonController::State DaemonControllerWin::ConvertToDaemonState( - DWORD service_state) { - switch (service_state) { - case SERVICE_RUNNING: - return STATE_STARTED; - - case SERVICE_CONTINUE_PENDING: - case SERVICE_START_PENDING: - return STATE_STARTING; - break; - - case SERVICE_PAUSE_PENDING: - case SERVICE_STOP_PENDING: - return STATE_STOPPING; - break; - - case SERVICE_PAUSED: - case SERVICE_STOPPED: - return STATE_STOPPED; - break; - - default: - NOTREACHED(); - return STATE_UNKNOWN; - } -} - -// static -DaemonController::AsyncResult DaemonControllerWin::HResultToAsyncResult( - HRESULT hr) { - // TODO(sergeyu): Report other errors to the webapp once it knows - // how to handle them. - return FAILED(hr) ? RESULT_FAILED : RESULT_OK; -} - -void DaemonControllerWin::DoGetConfig(const GetConfigCallback& callback) { - DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); - - scoped_ptr<base::DictionaryValue> dictionary_null(NULL); - - // Configure and start the Daemon Controller if it is installed already. - HRESULT hr = ActivateController(); - if (FAILED(hr)) { - callback.Run(dictionary_null.Pass()); - return; - } - - // Get the host configuration. - ScopedBstr host_config; - hr = control_->GetConfig(host_config.Receive()); - if (FAILED(hr)) { - callback.Run(dictionary_null.Pass()); - return; - } - - // 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; - if (config.get() == NULL || !config->GetAsDictionary(&dictionary)) { - callback.Run(dictionary_null.Pass()); - return; - } - // Release |config|, because dictionary points to the same object. - config.release(); - - callback.Run(scoped_ptr<base::DictionaryValue>(dictionary)); -} - -void DaemonControllerWin::DoInstallAsNeededAndStart( - scoped_ptr<base::DictionaryValue> config, - bool consent, - const CompletionCallback& done) { - DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); - - // Configure and start the Daemon Controller if it is installed already. - HRESULT hr = ActivateElevatedController(); - if (SUCCEEDED(hr)) { - DoSetConfigAndStart(config.Pass(), consent, done); - return; - } - - // Otherwise, install it if its COM registration entry is missing. - if (hr == CO_E_CLASSSTRING) { - scoped_ptr<DaemonInstallerWin> installer = DaemonInstallerWin::Create( - GetTopLevelWindow(window_handle_), - base::Bind(&DaemonControllerWin::OnInstallationComplete, - base::Unretained(this), - base::Passed(&config), - consent, - done)); - if (installer.get()) { - DCHECK(!installer_.get()); - installer_ = installer.Pass(); - installer_->Install(); - } - } else { - LOG(ERROR) << "Failed to initiate the Chromoting Host installation " - << "(error: 0x" << std::hex << hr << std::dec << ")."; - done.Run(HResultToAsyncResult(hr)); - } -} - -void DaemonControllerWin::DoSetConfigAndStart( - scoped_ptr<base::DictionaryValue> config, - bool consent, - const CompletionCallback& done) { - DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); - - HRESULT hr = ActivateElevatedController(); - if (FAILED(hr)) { - done.Run(HResultToAsyncResult(hr)); - return; - } - - // Record the user's consent. - if (control2_.get()) { - hr = control2_->SetUsageStatsConsent(consent); - if (FAILED(hr)) { - done.Run(HResultToAsyncResult(hr)); - return; - } - } - - // Set the configuration. - ScopedBstr config_str(NULL); - ConfigToString(*config, &config_str); - if (config_str == NULL) { - done.Run(HResultToAsyncResult(E_OUTOFMEMORY)); - return; - } - - hr = control_->SetOwnerWindow( - reinterpret_cast<LONG_PTR>(GetTopLevelWindow(window_handle_))); - if (FAILED(hr)) { - done.Run(HResultToAsyncResult(hr)); - return; - } - - hr = control_->SetConfig(config_str); - if (FAILED(hr)) { - done.Run(HResultToAsyncResult(hr)); - return; - } - - // Start daemon. - hr = control_->StartDaemon(); - done.Run(HResultToAsyncResult(hr)); -} - -void DaemonControllerWin::DoUpdateConfig( - scoped_ptr<base::DictionaryValue> config, - const CompletionCallback& done_callback) { - DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); - - HRESULT hr = ActivateElevatedController(); - if (FAILED(hr)) { - done_callback.Run(HResultToAsyncResult(hr)); - return; - } - - // Update the configuration. - ScopedBstr config_str(NULL); - ConfigToString(*config, &config_str); - if (config_str == NULL) { - done_callback.Run(HResultToAsyncResult(E_OUTOFMEMORY)); - return; - } - - // Make sure that the PIN confirmation dialog is focused properly. - hr = control_->SetOwnerWindow( - reinterpret_cast<LONG_PTR>(GetTopLevelWindow(window_handle_))); - if (FAILED(hr)) { - done_callback.Run(HResultToAsyncResult(hr)); - return; - } - - hr = control_->UpdateConfig(config_str); - done_callback.Run(HResultToAsyncResult(hr)); -} - -void DaemonControllerWin::DoStop(const CompletionCallback& done_callback) { - DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); - - HRESULT hr = ActivateElevatedController(); - if (FAILED(hr)) { - done_callback.Run(HResultToAsyncResult(hr)); - return; - } - - hr = control_->StopDaemon(); - done_callback.Run(HResultToAsyncResult(hr)); -} - -void DaemonControllerWin::DoSetWindow(void* window_handle) { - window_handle_ = reinterpret_cast<HWND>(window_handle); -} - -void DaemonControllerWin::DoGetVersion(const GetVersionCallback& callback) { - DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); - - std::string version_null; - - // Configure and start the Daemon Controller if it is installed already. - HRESULT hr = ActivateController(); - if (FAILED(hr)) { - callback.Run(version_null); - return; - } - - // Get the version string. - ScopedBstr version; - hr = control_->GetVersion(version.Receive()); - if (FAILED(hr)) { - callback.Run(version_null); - return; - } - - callback.Run(UTF16ToUTF8( - string16(static_cast<BSTR>(version), version.Length()))); -} - -void DaemonControllerWin::DoGetUsageStatsConsent( - const GetUsageStatsConsentCallback& done) { - DCHECK(worker_thread_.message_loop_proxy()->BelongsToCurrentThread()); - - // Activate the Daemon Controller and see if it supports |IDaemonControl2|. - HRESULT hr = ActivateController(); - if (FAILED(hr)) { - // The host is not installed yet. Assume that the user's consent is not - // recorded yet and set the default value to true. This value will not come - // into effect until the user installs the host and agrees to crash - // dump reporting. - done.Run(true, true, false); - return; - } - - if (control2_.get() == NULL) { - // The host is installed and does not support crash dump reporting. - done.Run(false, false, false); - return; - } - - // Get the recorded user's consent. - BOOL allowed; - BOOL set_by_policy; - hr = control2_->GetUsageStatsConsent(&allowed, &set_by_policy); - if (FAILED(hr)) { - // If the user's consent is not recorded yet, set the default value to true. - // This value will not come into effect until the user agrees to crash - // dump reporting. - done.Run(true, true, false); - return; - } - - done.Run(true, !!allowed, !!set_by_policy); -} - -} // namespace - -scoped_ptr<DaemonController> remoting::DaemonController::Create() { - return scoped_ptr<DaemonController>(new DaemonControllerWin()); -} - -} // namespace remoting diff --git a/remoting/host/plugin/daemon_installer_win.h b/remoting/host/plugin/daemon_installer_win.h index bff134c..3709982 100644 --- a/remoting/host/plugin/daemon_installer_win.h +++ b/remoting/host/plugin/daemon_installer_win.h @@ -10,7 +10,6 @@ #include "base/basictypes.h" #include "base/callback.h" #include "base/memory/scoped_ptr.h" -#include "remoting/host/plugin/daemon_controller.h" namespace remoting { diff --git a/remoting/host/plugin/host_script_object.cc b/remoting/host/plugin/host_script_object.cc index 15b5cee..6af792f 100644 --- a/remoting/host/plugin/host_script_object.cc +++ b/remoting/host/plugin/host_script_object.cc @@ -27,7 +27,6 @@ #include "remoting/host/it2me_host_user_interface.h" #include "remoting/host/network_settings.h" #include "remoting/host/pin_hash.h" -#include "remoting/host/plugin/daemon_controller.h" #include "remoting/host/plugin/host_log_handler.h" #include "remoting/host/policy_hack/policy_watcher.h" #include "remoting/host/register_support_host_request.h" diff --git a/remoting/host/plugin/host_script_object.h b/remoting/host/plugin/host_script_object.h index db452cf..c9bd1ec5 100644 --- a/remoting/host/plugin/host_script_object.h +++ b/remoting/host/plugin/host_script_object.h @@ -23,8 +23,8 @@ #include "remoting/host/host_key_pair.h" #include "remoting/host/host_status_observer.h" #include "remoting/host/log_to_server.h" -#include "remoting/host/plugin/daemon_controller.h" #include "remoting/host/plugin/host_plugin_utils.h" +#include "remoting/host/setup/daemon_controller.h" #include "remoting/host/ui_strings.h" #include "third_party/npapi/bindings/npapi.h" #include "third_party/npapi/bindings/npfunctions.h" |