Chromium Code Reviews| OLD | NEW |
|---|---|
| 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/setup/daemon_controller.h" | 5 #include "remoting/host/setup/daemon_controller_delegate_linux.h" |
| 6 | 6 |
| 7 #include <unistd.h> | 7 #include <unistd.h> |
| 8 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
| 12 #include "base/compiler_specific.h" | 12 #include "base/compiler_specific.h" |
| 13 #include "base/environment.h" | 13 #include "base/environment.h" |
| 14 #include "base/file_util.h" | 14 #include "base/file_util.h" |
| 15 #include "base/files/file_path.h" | 15 #include "base/files/file_path.h" |
| 16 #include "base/json/json_writer.h" | 16 #include "base/json/json_writer.h" |
| 17 #include "base/logging.h" | 17 #include "base/logging.h" |
| 18 #include "base/md5.h" | 18 #include "base/md5.h" |
| 19 #include "base/process/kill.h" | 19 #include "base/process/kill.h" |
| 20 #include "base/process/launch.h" | 20 #include "base/process/launch.h" |
| 21 #include "base/process/process_handle.h" | 21 #include "base/process/process_handle.h" |
| 22 #include "base/strings/string_number_conversions.h" | 22 #include "base/strings/string_number_conversions.h" |
| 23 #include "base/strings/string_split.h" | 23 #include "base/strings/string_split.h" |
| 24 #include "base/strings/string_util.h" | 24 #include "base/strings/string_util.h" |
| 25 #include "base/threading/thread.h" | 25 #include "base/thread_task_runner_handle.h" |
| 26 #include "base/values.h" | 26 #include "base/values.h" |
| 27 #include "net/base/net_util.h" | 27 #include "net/base/net_util.h" |
| 28 #include "remoting/host/host_config.h" | 28 #include "remoting/host/host_config.h" |
| 29 #include "remoting/host/json_host_config.h" | 29 #include "remoting/host/json_host_config.h" |
| 30 #include "remoting/host/usage_stats_consent.h" | 30 #include "remoting/host/usage_stats_consent.h" |
| 31 | 31 |
| 32 namespace remoting { | 32 namespace remoting { |
| 33 | 33 |
| 34 namespace { | 34 namespace { |
| 35 | 35 |
| 36 const char kDaemonScript[] = | 36 const char kDaemonScript[] = |
| 37 "/opt/google/chrome-remote-desktop/chrome-remote-desktop"; | 37 "/opt/google/chrome-remote-desktop/chrome-remote-desktop"; |
| 38 | 38 |
| 39 // Timeout for running daemon script. The script itself sets a timeout when | 39 // Timeout for running daemon script. The script itself sets a timeout when |
| 40 // waiting for the host to come online, so the setting here should be at least | 40 // waiting for the host to come online, so the setting here should be at least |
| 41 // as long. | 41 // as long. |
| 42 const int64 kDaemonTimeoutMs = 60000; | 42 const int64 kDaemonTimeoutMs = 60000; |
| 43 | 43 |
| 44 // Timeout for commands that require password prompt - 5 minutes. | 44 // Timeout for commands that require password prompt - 5 minutes. |
| 45 const int64 kSudoTimeoutSeconds = 5 * 60; | 45 const int64 kSudoTimeoutSeconds = 5 * 60; |
| 46 | 46 |
| 47 void Dummy() {} | |
|
Sergey Ulanov
2013/09/09 18:12:31
not used anywhere
alexeypa (please no reviews)
2013/09/09 19:30:57
Done.
| |
| 48 | |
| 47 std::string GetMd5(const std::string& value) { | 49 std::string GetMd5(const std::string& value) { |
| 48 base::MD5Context ctx; | 50 base::MD5Context ctx; |
| 49 base::MD5Init(&ctx); | 51 base::MD5Init(&ctx); |
| 50 base::MD5Update(&ctx, value); | 52 base::MD5Update(&ctx, value); |
| 51 base::MD5Digest digest; | 53 base::MD5Digest digest; |
| 52 base::MD5Final(&digest, &ctx); | 54 base::MD5Final(&digest, &ctx); |
| 53 return StringToLowerASCII(base::HexEncode(digest.a, sizeof(digest.a))); | 55 return StringToLowerASCII(base::HexEncode(digest.a, sizeof(digest.a))); |
| 54 } | 56 } |
| 55 | 57 |
| 56 class DaemonControllerLinux : public remoting::DaemonController { | 58 base::FilePath GetConfigPath() { |
| 57 public: | 59 std::string filename = "host#" + GetMd5(net::GetHostName()) + ".json"; |
| 58 DaemonControllerLinux(); | 60 return file_util::GetHomeDir(). |
| 59 | 61 Append(".config/chrome-remote-desktop").Append(filename); |
| 60 virtual State GetState() OVERRIDE; | |
| 61 virtual void GetConfig(const GetConfigCallback& callback) OVERRIDE; | |
| 62 virtual void SetConfigAndStart( | |
| 63 scoped_ptr<base::DictionaryValue> config, | |
| 64 bool consent, | |
| 65 const CompletionCallback& done) OVERRIDE; | |
| 66 virtual void UpdateConfig(scoped_ptr<base::DictionaryValue> config, | |
| 67 const CompletionCallback& done_callback) OVERRIDE; | |
| 68 virtual void Stop(const CompletionCallback& done_callback) OVERRIDE; | |
| 69 virtual void SetWindow(void* window_handle) OVERRIDE; | |
| 70 virtual void GetVersion(const GetVersionCallback& done_callback) OVERRIDE; | |
| 71 virtual void GetUsageStatsConsent( | |
| 72 const GetUsageStatsConsentCallback& done) OVERRIDE; | |
| 73 | |
| 74 private: | |
| 75 base::FilePath GetConfigPath(); | |
| 76 | |
| 77 void DoGetConfig(const GetConfigCallback& callback); | |
| 78 void DoSetConfigAndStart(scoped_ptr<base::DictionaryValue> config, | |
| 79 const CompletionCallback& done); | |
| 80 void DoUpdateConfig(scoped_ptr<base::DictionaryValue> config, | |
| 81 const CompletionCallback& done_callback); | |
| 82 void DoStop(const CompletionCallback& done_callback); | |
| 83 void DoGetVersion(const GetVersionCallback& done_callback); | |
| 84 | |
| 85 base::Thread file_io_thread_; | |
| 86 | |
| 87 DISALLOW_COPY_AND_ASSIGN(DaemonControllerLinux); | |
| 88 }; | |
| 89 | |
| 90 DaemonControllerLinux::DaemonControllerLinux() | |
| 91 : file_io_thread_("DaemonControllerFileIO") { | |
| 92 file_io_thread_.Start(); | |
| 93 } | 62 } |
| 94 | 63 |
| 95 static bool GetScriptPath(base::FilePath* result) { | 64 bool GetScriptPath(base::FilePath* result) { |
| 96 base::FilePath candidate_exe(kDaemonScript); | 65 base::FilePath candidate_exe(kDaemonScript); |
| 97 if (access(candidate_exe.value().c_str(), X_OK) == 0) { | 66 if (access(candidate_exe.value().c_str(), X_OK) == 0) { |
| 98 *result = candidate_exe; | 67 *result = candidate_exe; |
| 99 return true; | 68 return true; |
| 100 } | 69 } |
| 101 return false; | 70 return false; |
| 102 } | 71 } |
| 103 | 72 |
| 104 static bool RunHostScriptWithTimeout( | 73 bool RunHostScriptWithTimeout( |
| 105 const std::vector<std::string>& args, | 74 const std::vector<std::string>& args, |
| 106 base::TimeDelta timeout, | 75 base::TimeDelta timeout, |
| 107 int* exit_code) { | 76 int* exit_code) { |
| 108 DCHECK(exit_code); | 77 DCHECK(exit_code); |
| 109 | 78 |
| 110 // As long as we're relying on running an external binary from the | 79 // As long as we're relying on running an external binary from the |
| 111 // PATH, don't do it as root. | 80 // PATH, don't do it as root. |
| 112 if (getuid() == 0) { | 81 if (getuid() == 0) { |
| 113 LOG(ERROR) << "Refusing to run script as root."; | 82 LOG(ERROR) << "Refusing to run script as root."; |
| 114 return false; | 83 return false; |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 140 if (!base::WaitForExitCodeWithTimeout(process_handle, exit_code, timeout)) { | 109 if (!base::WaitForExitCodeWithTimeout(process_handle, exit_code, timeout)) { |
| 141 base::KillProcess(process_handle, 0, false); | 110 base::KillProcess(process_handle, 0, false); |
| 142 LOG(ERROR) << "Timeout exceeded for command: " | 111 LOG(ERROR) << "Timeout exceeded for command: " |
| 143 << command_line.GetCommandLineString(); | 112 << command_line.GetCommandLineString(); |
| 144 return false; | 113 return false; |
| 145 } | 114 } |
| 146 | 115 |
| 147 return true; | 116 return true; |
| 148 } | 117 } |
| 149 | 118 |
| 150 static bool RunHostScript(const std::vector<std::string>& args, | 119 bool RunHostScript(const std::vector<std::string>& args, |
| 151 int* exit_code) { | 120 int* exit_code) { |
| 152 return RunHostScriptWithTimeout( | 121 return RunHostScriptWithTimeout( |
| 153 args, base::TimeDelta::FromMilliseconds(kDaemonTimeoutMs), exit_code); | 122 args, base::TimeDelta::FromMilliseconds(kDaemonTimeoutMs), exit_code); |
| 154 } | 123 } |
| 155 | 124 |
| 156 remoting::DaemonController::State DaemonControllerLinux::GetState() { | 125 } // namespace |
| 126 | |
| 127 DaemonControllerDelegateLinux::DaemonControllerDelegateLinux() { | |
| 128 } | |
| 129 | |
| 130 DaemonControllerDelegateLinux::~DaemonControllerDelegateLinux() { | |
| 131 } | |
| 132 | |
| 133 DaemonController::State DaemonControllerDelegateLinux::GetState() { | |
| 157 std::vector<std::string> args; | 134 std::vector<std::string> args; |
| 158 args.push_back("--check-running"); | 135 args.push_back("--check-running"); |
| 159 int exit_code = 0; | 136 int exit_code = 0; |
| 160 if (!RunHostScript(args, &exit_code)) { | 137 if (!RunHostScript(args, &exit_code)) { |
| 161 // TODO(jamiewalch): When we have a good story for installing, return | 138 // TODO(jamiewalch): When we have a good story for installing, return |
| 162 // NOT_INSTALLED rather than NOT_IMPLEMENTED (the former suppresses | 139 // NOT_INSTALLED rather than NOT_IMPLEMENTED (the former suppresses |
| 163 // the relevant UI in the web-app). | 140 // the relevant UI in the web-app). |
| 164 return remoting::DaemonController::STATE_NOT_IMPLEMENTED; | 141 return DaemonController::STATE_NOT_IMPLEMENTED; |
| 165 } | 142 } |
| 166 | 143 |
| 167 if (exit_code == 0) { | 144 if (exit_code == 0) { |
| 168 return remoting::DaemonController::STATE_STARTED; | 145 return DaemonController::STATE_STARTED; |
| 169 } else { | 146 } else { |
| 170 return remoting::DaemonController::STATE_STOPPED; | 147 return DaemonController::STATE_STOPPED; |
| 171 } | 148 } |
| 172 } | 149 } |
| 173 | 150 |
| 174 void DaemonControllerLinux::GetConfig(const GetConfigCallback& callback) { | 151 scoped_ptr<base::DictionaryValue> DaemonControllerDelegateLinux::GetConfig() { |
| 175 // base::Unretained() is safe because we control lifetime of the thread. | |
| 176 file_io_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | |
| 177 &DaemonControllerLinux::DoGetConfig, base::Unretained(this), callback)); | |
| 178 } | |
| 179 | |
| 180 void DaemonControllerLinux::GetUsageStatsConsent( | |
| 181 const GetUsageStatsConsentCallback& done) { | |
| 182 // Crash dump collection is not implemented on Linux yet. | |
| 183 // http://crbug.com/130678. | |
| 184 done.Run(false, false, false); | |
| 185 } | |
| 186 | |
| 187 void DaemonControllerLinux::SetConfigAndStart( | |
| 188 scoped_ptr<base::DictionaryValue> config, | |
| 189 bool /* consent */, | |
| 190 const CompletionCallback& done) { | |
| 191 // base::Unretained() is safe because we control lifetime of the thread. | |
| 192 file_io_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | |
| 193 &DaemonControllerLinux::DoSetConfigAndStart, base::Unretained(this), | |
| 194 base::Passed(&config), done)); | |
| 195 } | |
| 196 | |
| 197 void DaemonControllerLinux::UpdateConfig( | |
| 198 scoped_ptr<base::DictionaryValue> config, | |
| 199 const CompletionCallback& done_callback) { | |
| 200 file_io_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | |
| 201 &DaemonControllerLinux::DoUpdateConfig, base::Unretained(this), | |
| 202 base::Passed(&config), done_callback)); | |
| 203 } | |
| 204 | |
| 205 void DaemonControllerLinux::Stop(const CompletionCallback& done_callback) { | |
| 206 file_io_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | |
| 207 &DaemonControllerLinux::DoStop, base::Unretained(this), | |
| 208 done_callback)); | |
| 209 } | |
| 210 | |
| 211 void DaemonControllerLinux::SetWindow(void* window_handle) { | |
| 212 // noop | |
| 213 } | |
| 214 | |
| 215 void DaemonControllerLinux::GetVersion( | |
| 216 const GetVersionCallback& done_callback) { | |
| 217 file_io_thread_.message_loop()->PostTask(FROM_HERE, base::Bind( | |
| 218 &DaemonControllerLinux::DoGetVersion, base::Unretained(this), | |
| 219 done_callback)); | |
| 220 } | |
| 221 | |
| 222 base::FilePath DaemonControllerLinux::GetConfigPath() { | |
| 223 std::string filename = "host#" + GetMd5(net::GetHostName()) + ".json"; | |
| 224 return file_util::GetHomeDir(). | |
| 225 Append(".config/chrome-remote-desktop").Append(filename); | |
| 226 } | |
| 227 | |
| 228 void DaemonControllerLinux::DoGetConfig(const GetConfigCallback& callback) { | |
| 229 scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue()); | 152 scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue()); |
| 230 | 153 |
| 231 if (GetState() != remoting::DaemonController::STATE_NOT_IMPLEMENTED) { | 154 if (GetState() != DaemonController::STATE_NOT_IMPLEMENTED) { |
| 232 JsonHostConfig config(GetConfigPath()); | 155 JsonHostConfig config(GetConfigPath()); |
| 233 if (config.Read()) { | 156 if (config.Read()) { |
| 234 std::string value; | 157 std::string value; |
| 235 if (config.GetString(kHostIdConfigPath, &value)) { | 158 if (config.GetString(kHostIdConfigPath, &value)) { |
| 236 result->SetString(kHostIdConfigPath, value); | 159 result->SetString(kHostIdConfigPath, value); |
| 237 } | 160 } |
| 238 if (config.GetString(kXmppLoginConfigPath, &value)) { | 161 if (config.GetString(kXmppLoginConfigPath, &value)) { |
| 239 result->SetString(kXmppLoginConfigPath, value); | 162 result->SetString(kXmppLoginConfigPath, value); |
| 240 } | 163 } |
| 241 } else { | 164 } else { |
| 242 result.reset(); // Return NULL in case of error. | 165 result.reset(); // Return NULL in case of error. |
| 243 } | 166 } |
| 244 } | 167 } |
| 245 | 168 |
| 246 callback.Run(result.Pass()); | 169 return result.Pass(); |
| 247 } | 170 } |
| 248 | 171 |
| 249 void DaemonControllerLinux::DoSetConfigAndStart( | 172 void DaemonControllerDelegateLinux::SetConfigAndStart( |
| 250 scoped_ptr<base::DictionaryValue> config, | 173 scoped_ptr<base::DictionaryValue> config, |
| 251 const CompletionCallback& done_callback) { | 174 bool consent, |
| 252 | 175 const DaemonController::CompletionCallback& done) { |
| 253 // Add the user to chrome-remote-desktop group first. | 176 // Add the user to chrome-remote-desktop group first. |
| 254 std::vector<std::string> args; | 177 std::vector<std::string> args; |
| 255 args.push_back("--add-user"); | 178 args.push_back("--add-user"); |
| 256 int exit_code; | 179 int exit_code; |
| 257 if (!RunHostScriptWithTimeout( | 180 if (!RunHostScriptWithTimeout( |
| 258 args, base::TimeDelta::FromSeconds(kSudoTimeoutSeconds), | 181 args, base::TimeDelta::FromSeconds(kSudoTimeoutSeconds), |
| 259 &exit_code) || | 182 &exit_code) || |
| 260 exit_code != 0) { | 183 exit_code != 0) { |
| 261 LOG(ERROR) << "Failed to add user to chrome-remote-desktop group."; | 184 LOG(ERROR) << "Failed to add user to chrome-remote-desktop group."; |
| 262 done_callback.Run(RESULT_FAILED); | 185 done.Run(DaemonController::RESULT_FAILED); |
| 263 return; | 186 return; |
| 264 } | 187 } |
| 265 | 188 |
| 266 // Ensure the configuration directory exists. | 189 // Ensure the configuration directory exists. |
| 267 base::FilePath config_dir = GetConfigPath().DirName(); | 190 base::FilePath config_dir = GetConfigPath().DirName(); |
| 268 if (!base::DirectoryExists(config_dir) && | 191 if (!base::DirectoryExists(config_dir) && |
| 269 !file_util::CreateDirectory(config_dir)) { | 192 !file_util::CreateDirectory(config_dir)) { |
| 270 LOG(ERROR) << "Failed to create config directory " << config_dir.value(); | 193 LOG(ERROR) << "Failed to create config directory " << config_dir.value(); |
| 271 done_callback.Run(RESULT_FAILED); | 194 done.Run(DaemonController::RESULT_FAILED); |
| 272 return; | 195 return; |
| 273 } | 196 } |
| 274 | 197 |
| 275 // Write config. | 198 // Write config. |
| 276 JsonHostConfig config_file(GetConfigPath()); | 199 JsonHostConfig config_file(GetConfigPath()); |
| 277 if (!config_file.CopyFrom(config.get()) || | 200 if (!config_file.CopyFrom(config.get()) || |
| 278 !config_file.Save()) { | 201 !config_file.Save()) { |
| 279 LOG(ERROR) << "Failed to update config file."; | 202 LOG(ERROR) << "Failed to update config file."; |
| 280 done_callback.Run(RESULT_FAILED); | 203 done.Run(DaemonController::RESULT_FAILED); |
| 281 return; | 204 return; |
| 282 } | 205 } |
| 283 | 206 |
| 284 // Finally start the host. | 207 // Finally start the host. |
| 285 args.clear(); | 208 args.clear(); |
| 286 args.push_back("--start"); | 209 args.push_back("--start"); |
| 287 AsyncResult result; | 210 DaemonController::AsyncResult result = DaemonController::RESULT_FAILED; |
| 288 if (RunHostScript(args, &exit_code)) { | 211 if (RunHostScript(args, &exit_code) && (exit_code == 0)) |
| 289 result = (exit_code == 0) ? RESULT_OK : RESULT_FAILED; | 212 result = DaemonController::RESULT_OK; |
| 290 } else { | 213 |
| 291 result = RESULT_FAILED; | 214 done.Run(result); |
| 292 } | |
| 293 done_callback.Run(result); | |
| 294 } | 215 } |
| 295 | 216 |
| 296 void DaemonControllerLinux::DoUpdateConfig( | 217 void DaemonControllerDelegateLinux::UpdateConfig( |
| 297 scoped_ptr<base::DictionaryValue> config, | 218 scoped_ptr<base::DictionaryValue> config, |
| 298 const CompletionCallback& done_callback) { | 219 const DaemonController::CompletionCallback& done) { |
| 299 JsonHostConfig config_file(GetConfigPath()); | 220 JsonHostConfig config_file(GetConfigPath()); |
| 300 if (!config_file.Read() || | 221 if (!config_file.Read() || |
| 301 !config_file.CopyFrom(config.get()) || | 222 !config_file.CopyFrom(config.get()) || |
| 302 !config_file.Save()) { | 223 !config_file.Save()) { |
| 303 LOG(ERROR) << "Failed to update config file."; | 224 LOG(ERROR) << "Failed to update config file."; |
| 304 done_callback.Run(RESULT_FAILED); | 225 done.Run(DaemonController::RESULT_FAILED); |
| 305 return; | 226 return; |
| 306 } | 227 } |
| 307 | 228 |
| 308 std::vector<std::string> args; | 229 std::vector<std::string> args; |
| 309 args.push_back("--reload"); | 230 args.push_back("--reload"); |
| 310 AsyncResult result; | 231 int exit_code = 0; |
| 311 int exit_code; | 232 DaemonController::AsyncResult result = DaemonController::RESULT_FAILED; |
| 312 if (RunHostScript(args, &exit_code)) { | 233 if (RunHostScript(args, &exit_code) && (exit_code == 0)) |
| 313 result = (exit_code == 0) ? RESULT_OK : RESULT_FAILED; | 234 result = DaemonController::RESULT_OK; |
| 314 } else { | |
| 315 result = RESULT_FAILED; | |
| 316 } | |
| 317 | 235 |
| 318 done_callback.Run(result); | 236 done.Run(result); |
| 319 } | 237 } |
| 320 | 238 |
| 321 void DaemonControllerLinux::DoStop(const CompletionCallback& done_callback) { | 239 void DaemonControllerDelegateLinux::Stop( |
| 240 const DaemonController::CompletionCallback& done) { | |
| 322 std::vector<std::string> args; | 241 std::vector<std::string> args; |
| 323 args.push_back("--stop"); | 242 args.push_back("--stop"); |
| 324 int exit_code = 0; | 243 int exit_code = 0; |
| 325 AsyncResult result; | 244 DaemonController::AsyncResult result = DaemonController::RESULT_FAILED; |
| 326 if (RunHostScript(args, &exit_code)) { | 245 if (RunHostScript(args, &exit_code) && (exit_code == 0)) |
| 327 result = (exit_code == 0) ? RESULT_OK : RESULT_FAILED; | 246 result = DaemonController::RESULT_OK; |
| 328 } else { | 247 |
| 329 result = RESULT_FAILED; | 248 done.Run(result); |
| 330 } | |
| 331 done_callback.Run(result); | |
| 332 } | 249 } |
| 333 | 250 |
| 334 void DaemonControllerLinux::DoGetVersion( | 251 void DaemonControllerDelegateLinux::SetWindow(void* window_handle) { |
| 335 const GetVersionCallback& done_callback) { | 252 // noop |
| 253 } | |
| 254 | |
| 255 std::string DaemonControllerDelegateLinux::GetVersion() { | |
| 336 base::FilePath script_path; | 256 base::FilePath script_path; |
| 337 if (!GetScriptPath(&script_path)) { | 257 if (!GetScriptPath(&script_path)) { |
| 338 done_callback.Run(std::string()); | 258 return std::string(); |
| 339 return; | |
| 340 } | 259 } |
| 341 CommandLine command_line(script_path); | 260 CommandLine command_line(script_path); |
| 342 command_line.AppendArg("--host-version"); | 261 command_line.AppendArg("--host-version"); |
| 343 | 262 |
| 344 std::string version; | 263 std::string version; |
| 345 int exit_code = 0; | 264 int exit_code = 0; |
| 346 int result = | 265 int result = |
| 347 base::GetAppOutputWithExitCode(command_line, &version, &exit_code); | 266 base::GetAppOutputWithExitCode(command_line, &version, &exit_code); |
| 348 if (!result || exit_code != 0) { | 267 if (!result || exit_code != 0) { |
| 349 LOG(ERROR) << "Failed to run \"" << command_line.GetCommandLineString() | 268 LOG(ERROR) << "Failed to run \"" << command_line.GetCommandLineString() |
| 350 << "\". Exit code: " << exit_code; | 269 << "\". Exit code: " << exit_code; |
| 351 done_callback.Run(std::string()); | 270 return std::string(); |
| 352 return; | |
| 353 } | 271 } |
| 354 | 272 |
| 355 TrimWhitespaceASCII(version, TRIM_ALL, &version); | 273 TrimWhitespaceASCII(version, TRIM_ALL, &version); |
| 356 if (!ContainsOnlyChars(version, "0123456789.")) { | 274 if (!ContainsOnlyChars(version, "0123456789.")) { |
| 357 LOG(ERROR) << "Received invalid host version number: " << version; | 275 LOG(ERROR) << "Received invalid host version number: " << version; |
| 358 done_callback.Run(std::string()); | 276 return std::string(); |
| 359 return; | |
| 360 } | 277 } |
| 361 | 278 |
| 362 done_callback.Run(version); | 279 return version; |
| 363 } | 280 } |
| 364 | 281 |
| 365 } // namespace | 282 DaemonController::UsageStatsConsent |
| 283 DaemonControllerDelegateLinux::GetUsageStatsConsent() { | |
| 284 // Crash dump collection is not implemented on Linux yet. | |
| 285 // http://crbug.com/130678. | |
| 286 DaemonController::UsageStatsConsent consent; | |
| 287 consent.supported = false; | |
| 288 consent.allowed = false; | |
| 289 consent.set_by_policy = false; | |
| 290 return consent; | |
| 291 } | |
| 366 | 292 |
| 367 scoped_ptr<DaemonController> remoting::DaemonController::Create() { | 293 scoped_refptr<DaemonController> DaemonController::Create() { |
| 368 return scoped_ptr<DaemonController>(new DaemonControllerLinux()); | 294 scoped_ptr<DaemonController::Delegate> delegate( |
| 295 new DaemonControllerDelegateLinux()); | |
| 296 return new DaemonController(delegate.Pass()); | |
| 369 } | 297 } |
| 370 | 298 |
| 371 } // namespace remoting | 299 } // namespace remoting |
| OLD | NEW |