158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "remoting/host/setup/daemon_controller_delegate_linux.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/base_paths.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/environment.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h" 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_writer.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/md5.h" 20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/path_service.h" 21a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "base/process/kill.h" 22a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "base/process/launch.h" 23a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch#include "base/process/process_handle.h" 245e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h" 265e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h" 2758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/thread_task_runner_handle.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 2946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "build/build_config.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/host_config.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/json_host_config.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/usage_stats_consent.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kDaemonScript[] = 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "/opt/google/chrome-remote-desktop/chrome-remote-desktop"; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Timeout for running daemon script. The script itself sets a timeout when 433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// waiting for the host to come online, so the setting here should be at least 443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// as long. 453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)const int64 kDaemonTimeoutMs = 60000; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Timeout for commands that require password prompt - 5 minutes. 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int64 kSudoTimeoutSeconds = 5 * 60; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetMd5(const std::string& value) { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Context ctx; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Init(&ctx); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Update(&ctx, value); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Digest digest; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::MD5Final(&digest, &ctx); 566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return base::StringToLowerASCII(base::HexEncode(digest.a, sizeof(digest.a))); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)base::FilePath GetConfigPath() { 6058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::string filename = "host#" + GetMd5(net::GetHostName()) + ".json"; 61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::FilePath homedir; 62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PathService::Get(base::DIR_HOME, &homedir); 63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return homedir.Append(".config/chrome-remote-desktop").Append(filename); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool GetScriptPath(base::FilePath* result) { 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath candidate_exe(kDaemonScript); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (access(candidate_exe.value().c_str(), X_OK) == 0) { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *result = candidate_exe; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool RunHostScriptWithTimeout( 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::vector<std::string>& args, 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta timeout, 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* exit_code) { 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(exit_code); 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // As long as we're relying on running an external binary from the 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // PATH, don't do it as root. 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (getuid() == 0) { 84424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) LOG(ERROR) << "Refusing to run script as root."; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath script_path; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetScriptPath(&script_path)) { 89424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) LOG(ERROR) << "GetScriptPath() failed."; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::CommandLine command_line(script_path); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (unsigned int i = 0; i < args.size(); ++i) { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_line.AppendArg(args[i]); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::ProcessHandle process_handle; 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Redirect the child's stdout to the parent's stderr. In the case where this 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // parent process is a Native Messaging host, its stdout is used to send 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // messages to the web-app. 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::FileHandleMappingVector fds_to_remap; 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) fds_to_remap.push_back(std::pair<int, int>(STDERR_FILENO, STDOUT_FILENO)); 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::LaunchOptions options; 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) options.fds_to_remap = &fds_to_remap; 10546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 10646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#if !defined(OS_CHROMEOS) 10746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) options.allow_new_privs = true; 10846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#endif 10946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!base::LaunchProcess(command_line, options, &process_handle)) { 111424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) LOG(ERROR) << "Failed to run command: " 112424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) << command_line.GetCommandLineString(); 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!base::WaitForExitCodeWithTimeout(process_handle, exit_code, timeout)) { 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::KillProcess(process_handle, 0, false); 118424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) LOG(ERROR) << "Timeout exceeded for command: " 119424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) << command_line.GetCommandLineString(); 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool RunHostScript(const std::vector<std::string>& args, int* exit_code) { 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return RunHostScriptWithTimeout( 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args, base::TimeDelta::FromMilliseconds(kDaemonTimeoutMs), exit_code); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} // namespace 13258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 13358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)DaemonControllerDelegateLinux::DaemonControllerDelegateLinux() { 13458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 13558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 13658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)DaemonControllerDelegateLinux::~DaemonControllerDelegateLinux() { 13758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 13858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 13958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)DaemonController::State DaemonControllerDelegateLinux::GetState() { 1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath script_path; 1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!GetScriptPath(&script_path)) { 1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return DaemonController::STATE_NOT_IMPLEMENTED; 1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::CommandLine command_line(script_path); 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) command_line.AppendArg("--get-status"); 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string status; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int exit_code = 0; 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool result = 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::GetAppOutputWithExitCode(command_line, &status, &exit_code); 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!result) { 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(jamiewalch): When we have a good story for installing, return 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOT_INSTALLED rather than NOT_IMPLEMENTED (the former suppresses 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the relevant UI in the web-app). 15558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return DaemonController::STATE_NOT_IMPLEMENTED; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (exit_code != 0) { 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Failed to run \"" << command_line.GetCommandLineString() 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << "\". Exit code: " << exit_code; 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return DaemonController::STATE_UNKNOWN; 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TrimWhitespaceASCII(status, base::TRIM_ALL, &status); 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (status == "STARTED") { 16758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return DaemonController::STATE_STARTED; 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else if (status == "STOPPED") { 16958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return DaemonController::STATE_STOPPED; 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else if (status == "NOT_IMPLEMENTED") { 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return DaemonController::STATE_NOT_IMPLEMENTED; 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) LOG(ERROR) << "Unknown status string returned from \"" 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << command_line.GetCommandLineString() 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) << "\": " << status; 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return DaemonController::STATE_UNKNOWN; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)scoped_ptr<base::DictionaryValue> DaemonControllerDelegateLinux::GetConfig() { 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue()); 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (GetState() != DaemonController::STATE_NOT_IMPLEMENTED) { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JsonHostConfig config(GetConfigPath()); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (config.Read()) { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string value; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (config.GetString(kHostIdConfigPath, &value)) { 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->SetString(kHostIdConfigPath, value); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (config.GetString(kXmppLoginConfigPath, &value)) { 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result->SetString(kXmppLoginConfigPath, value); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) result.reset(); // Return NULL in case of error. 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return result.Pass(); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 201a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid DaemonControllerDelegateLinux::InstallHost( 202a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const DaemonController::CompletionCallback& done) { 203a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch NOTREACHED(); 204a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} 205a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 20658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void DaemonControllerDelegateLinux::SetConfigAndStart( 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::DictionaryValue> config, 20858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bool consent, 20958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const DaemonController::CompletionCallback& done) { 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the user to chrome-remote-desktop group first. 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string> args; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.push_back("--add-user"); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int exit_code; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!RunHostScriptWithTimeout( 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) args, base::TimeDelta::FromSeconds(kSudoTimeoutSeconds), 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &exit_code) || 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) exit_code != 0) { 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to add user to chrome-remote-desktop group."; 21958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) done.Run(DaemonController::RESULT_FAILED); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensure the configuration directory exists. 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath config_dir = GetConfigPath().DirName(); 2257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!base::DirectoryExists(config_dir) && 226a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) !base::CreateDirectory(config_dir)) { 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to create config directory " << config_dir.value(); 22858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) done.Run(DaemonController::RESULT_FAILED); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Write config. 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JsonHostConfig config_file(GetConfigPath()); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!config_file.CopyFrom(config.get()) || 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !config_file.Save()) { 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to update config file."; 23758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) done.Run(DaemonController::RESULT_FAILED); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Finally start the host. 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.clear(); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.push_back("--start"); 24458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DaemonController::AsyncResult result = DaemonController::RESULT_FAILED; 24558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (RunHostScript(args, &exit_code) && (exit_code == 0)) 24658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) result = DaemonController::RESULT_OK; 24758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 24858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) done.Run(result); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void DaemonControllerDelegateLinux::UpdateConfig( 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::DictionaryValue> config, 25358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const DaemonController::CompletionCallback& done) { 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JsonHostConfig config_file(GetConfigPath()); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!config_file.Read() || 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !config_file.CopyFrom(config.get()) || 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !config_file.Save()) { 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to update config file."; 25958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) done.Run(DaemonController::RESULT_FAILED); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string> args; 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.push_back("--reload"); 26558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) int exit_code = 0; 26658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DaemonController::AsyncResult result = DaemonController::RESULT_FAILED; 26758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (RunHostScript(args, &exit_code) && (exit_code == 0)) 26858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) result = DaemonController::RESULT_OK; 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) done.Run(result); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void DaemonControllerDelegateLinux::Stop( 27458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const DaemonController::CompletionCallback& done) { 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string> args; 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) args.push_back("--stop"); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int exit_code = 0; 27858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DaemonController::AsyncResult result = DaemonController::RESULT_FAILED; 27958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (RunHostScript(args, &exit_code) && (exit_code == 0)) 28058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) result = DaemonController::RESULT_OK; 28158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 28258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) done.Run(result); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void DaemonControllerDelegateLinux::SetWindow(void* window_handle) { 28658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // noop 28758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 28858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 28958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)std::string DaemonControllerDelegateLinux::GetVersion() { 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath script_path; 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetScriptPath(&script_path)) { 29258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return std::string(); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 294cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::CommandLine command_line(script_path); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command_line.AppendArg("--host-version"); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string version; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int exit_code = 0; 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::GetAppOutputWithExitCode(command_line, &version, &exit_code); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!result || exit_code != 0) { 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to run \"" << command_line.GetCommandLineString() 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "\". Exit code: " << exit_code; 30458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return std::string(); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TrimWhitespaceASCII(version, base::TRIM_ALL, &version); 308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!base::ContainsOnlyChars(version, "0123456789.")) { 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Received invalid host version number: " << version; 31058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return std::string(); 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 31358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return version; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 31658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)DaemonController::UsageStatsConsent 31758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)DaemonControllerDelegateLinux::GetUsageStatsConsent() { 31858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Crash dump collection is not implemented on Linux yet. 31958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // http://crbug.com/130678. 32058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) DaemonController::UsageStatsConsent consent; 32158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) consent.supported = false; 32258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) consent.allowed = false; 32358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) consent.set_by_policy = false; 32458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return consent; 32558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 32758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)scoped_refptr<DaemonController> DaemonController::Create() { 32858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) scoped_ptr<DaemonController::Delegate> delegate( 32958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) new DaemonControllerDelegateLinux()); 33058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return new DaemonController(delegate.Pass()); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace remoting 334