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

Side by Side Diff: remoting/host/setup/daemon_controller_delegate_linux.cc

Issue 1272833002: Pass error messages from native messaging to web-app. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix start_host. Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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_delegate_linux.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/base_paths.h" 9 #include "base/base_paths.h"
10 #include "base/basictypes.h" 10 #include "base/basictypes.h"
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
58 if (access(candidate_exe.value().c_str(), X_OK) == 0) { 58 if (access(candidate_exe.value().c_str(), X_OK) == 0) {
59 *result = candidate_exe; 59 *result = candidate_exe;
60 return true; 60 return true;
61 } 61 }
62 return false; 62 return false;
63 } 63 }
64 64
65 bool RunHostScriptWithTimeout( 65 bool RunHostScriptWithTimeout(
66 const std::vector<std::string>& args, 66 const std::vector<std::string>& args,
67 base::TimeDelta timeout, 67 base::TimeDelta timeout,
68 int* exit_code) { 68 const DaemonController::ErrorCallback& on_error) {
69 DCHECK(exit_code);
70 69
71 // As long as we're relying on running an external binary from the 70 // As long as we're relying on running an external binary from the
72 // PATH, don't do it as root. 71 // PATH, don't do it as root.
73 if (getuid() == 0) { 72 if (getuid() == 0) {
74 LOG(ERROR) << "Refusing to run script as root."; 73 std::string error_message = "Refusing to run script as root";
74 LOG(ERROR) << error_message;
75 on_error.Run(error_message, FROM_HERE);
75 return false; 76 return false;
76 } 77 }
78
77 base::FilePath script_path; 79 base::FilePath script_path;
78 if (!GetScriptPath(&script_path)) { 80 if (!GetScriptPath(&script_path)) {
79 LOG(ERROR) << "GetScriptPath() failed."; 81 std::string error_message = "GetScriptPath() failed";
82 LOG(ERROR) << error_message;
83 on_error.Run(error_message, FROM_HERE);
80 return false; 84 return false;
81 } 85 }
86
82 base::CommandLine command_line(script_path); 87 base::CommandLine command_line(script_path);
83 for (unsigned int i = 0; i < args.size(); ++i) { 88 for (unsigned int i = 0; i < args.size(); ++i) {
84 command_line.AppendArg(args[i]); 89 command_line.AppendArg(args[i]);
85 } 90 }
86 91
87 // Redirect the child's stdout to the parent's stderr. In the case where this 92 // Redirect the child's stdout to the parent's stderr. In the case where this
88 // parent process is a Native Messaging host, its stdout is used to send 93 // parent process is a Native Messaging host, its stdout is used to send
89 // messages to the web-app. 94 // messages to the web-app.
90 base::FileHandleMappingVector fds_to_remap; 95 base::FileHandleMappingVector fds_to_remap;
91 fds_to_remap.push_back(std::pair<int, int>(STDERR_FILENO, STDOUT_FILENO)); 96 fds_to_remap.push_back(std::pair<int, int>(STDERR_FILENO, STDOUT_FILENO));
92 base::LaunchOptions options; 97 base::LaunchOptions options;
93 options.fds_to_remap = &fds_to_remap; 98 options.fds_to_remap = &fds_to_remap;
94 99
95 #if !defined(OS_CHROMEOS) 100 #if !defined(OS_CHROMEOS)
96 options.allow_new_privs = true; 101 options.allow_new_privs = true;
97 #endif 102 #endif
98 103
99 base::Process process = base::LaunchProcess(command_line, options); 104 base::Process process = base::LaunchProcess(command_line, options);
100 if (!process.IsValid()) { 105 if (!process.IsValid()) {
101 LOG(ERROR) << "Failed to run command: " 106 std::ostringstream error_message;
102 << command_line.GetCommandLineString(); 107 error_message << "Failed to run command: "
108 << command_line.GetCommandLineString();
109 LOG(ERROR) << error_message;
110 on_error.Run(error_message.str(), FROM_HERE);
103 return false; 111 return false;
104 } 112 }
105 113
106 if (!process.WaitForExitWithTimeout(timeout, exit_code)) { 114 int exit_code;
115 if (!process.WaitForExitWithTimeout(timeout, &exit_code)) {
107 process.Terminate(0, false); 116 process.Terminate(0, false);
108 LOG(ERROR) << "Timeout exceeded for command: " 117 std::ostringstream error_message;
109 << command_line.GetCommandLineString(); 118 error_message << "Timeout exceeded for command: "
119 << command_line.GetCommandLineString();
120 LOG(ERROR) << error_message;
121 on_error.Run(error_message.str(), FROM_HERE);
110 return false; 122 return false;
111 } 123 }
112 124
125 if (exit_code != 0) {
126 std::ostringstream error_message;
127 error_message << "Non-zero exit code " << exit_code << " from command: "
128 << command_line.GetCommandLineString();
129 LOG(ERROR) << error_message;
130 on_error.Run(error_message.str(), FROM_HERE);
131 }
132
113 return true; 133 return true;
114 } 134 }
115 135
116 bool RunHostScript(const std::vector<std::string>& args, int* exit_code) { 136 bool RunHostScript(const std::vector<std::string>& args,
137 const DaemonController::ErrorCallback& on_error) {
117 return RunHostScriptWithTimeout( 138 return RunHostScriptWithTimeout(
118 args, base::TimeDelta::FromMilliseconds(kDaemonTimeoutMs), exit_code); 139 args,
140 base::TimeDelta::FromMilliseconds(kDaemonTimeoutMs),
141 on_error);
119 } 142 }
120 143
121 } // namespace 144 } // namespace
122 145
123 DaemonControllerDelegateLinux::DaemonControllerDelegateLinux() { 146 DaemonControllerDelegateLinux::DaemonControllerDelegateLinux() {
124 } 147 }
125 148
126 DaemonControllerDelegateLinux::~DaemonControllerDelegateLinux() { 149 DaemonControllerDelegateLinux::~DaemonControllerDelegateLinux() {
127 } 150 }
128 151
129 DaemonController::State DaemonControllerDelegateLinux::GetState() { 152 DaemonController::State DaemonControllerDelegateLinux::GetState() {
130 base::FilePath script_path; 153 base::FilePath script_path;
131 if (!GetScriptPath(&script_path)) { 154 if (!GetScriptPath(&script_path)) {
132 LOG(ERROR) << "GetScriptPath() failed."; 155 LOG(ERROR) << "GetScriptPath() failed";
133 return DaemonController::STATE_UNKNOWN; 156 return DaemonController::STATE_UNKNOWN;
134 } 157 }
135 base::CommandLine command_line(script_path); 158 base::CommandLine command_line(script_path);
136 command_line.AppendArg("--get-status"); 159 command_line.AppendArg("--get-status");
137 160
138 std::string status; 161 std::string status;
139 int exit_code = 0; 162 int exit_code = 0;
140 if (!base::GetAppOutputWithExitCode(command_line, &status, &exit_code) || 163 if (!base::GetAppOutputWithExitCode(command_line, &status, &exit_code) ||
141 exit_code != 0) { 164 exit_code != 0) {
142 LOG(ERROR) << "Failed to run \"" << command_line.GetCommandLineString() 165 LOG(ERROR) << "Failed to run \"" << command_line.GetCommandLineString()
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 } 198 }
176 if (config->GetString(kXmppLoginConfigPath, &value)) { 199 if (config->GetString(kXmppLoginConfigPath, &value)) {
177 result->SetString(kXmppLoginConfigPath, value); 200 result->SetString(kXmppLoginConfigPath, value);
178 } 201 }
179 return result.Pass(); 202 return result.Pass();
180 } 203 }
181 204
182 void DaemonControllerDelegateLinux::SetConfigAndStart( 205 void DaemonControllerDelegateLinux::SetConfigAndStart(
183 scoped_ptr<base::DictionaryValue> config, 206 scoped_ptr<base::DictionaryValue> config,
184 bool consent, 207 bool consent,
185 const DaemonController::CompletionCallback& done) { 208 const base::Closure& on_done,
209 const DaemonController::ErrorCallback& on_error) {
186 // Add the user to chrome-remote-desktop group first. 210 // Add the user to chrome-remote-desktop group first.
187 std::vector<std::string> args; 211 std::vector<std::string> args;
188 args.push_back("--add-user"); 212 args.push_back("--add-user");
189 int exit_code;
190 if (!RunHostScriptWithTimeout( 213 if (!RunHostScriptWithTimeout(
191 args, base::TimeDelta::FromSeconds(kSudoTimeoutSeconds), 214 args, base::TimeDelta::FromSeconds(kSudoTimeoutSeconds),
192 &exit_code) || 215 on_error)) {
193 exit_code != 0) {
194 LOG(ERROR) << "Failed to add user to chrome-remote-desktop group.";
195 done.Run(DaemonController::RESULT_FAILED);
196 return; 216 return;
197 } 217 }
198 218
199 // Ensure the configuration directory exists. 219 // Ensure the configuration directory exists.
200 base::FilePath config_dir = GetConfigPath().DirName(); 220 base::FilePath config_dir = GetConfigPath().DirName();
201 if (!base::DirectoryExists(config_dir) && 221 if (!base::DirectoryExists(config_dir) &&
202 !base::CreateDirectory(config_dir)) { 222 !base::CreateDirectory(config_dir)) {
203 LOG(ERROR) << "Failed to create config directory " << config_dir.value(); 223 std::ostringstream error_message;
204 done.Run(DaemonController::RESULT_FAILED); 224 error_message << "Failed to create config directory " << config_dir.value();
225 LOG(ERROR) << error_message;
226 on_error.Run(error_message.str(), FROM_HERE);
205 return; 227 return;
206 } 228 }
207 229
208 // Write config. 230 // Write config.
209 if (!HostConfigToJsonFile(*config, GetConfigPath())) { 231 if (!HostConfigToJsonFile(*config, GetConfigPath())) {
210 LOG(ERROR) << "Failed to update config file."; 232 std::string error_message = "Failed to update config file";
211 done.Run(DaemonController::RESULT_FAILED); 233 LOG(ERROR) << error_message;
234 on_error.Run(error_message, FROM_HERE);
212 return; 235 return;
213 } 236 }
214 237
215 // Finally start the host. 238 // Finally start the host.
216 args.clear(); 239 args.clear();
217 args.push_back("--start"); 240 args.push_back("--start");
218 DaemonController::AsyncResult result = DaemonController::RESULT_FAILED; 241 if (RunHostScript(args, on_error)) {
219 if (RunHostScript(args, &exit_code) && (exit_code == 0)) 242 on_done.Run();
220 result = DaemonController::RESULT_OK; 243 }
221
222 done.Run(result);
223 } 244 }
224 245
225 void DaemonControllerDelegateLinux::UpdateConfig( 246 void DaemonControllerDelegateLinux::UpdateConfig(
226 scoped_ptr<base::DictionaryValue> config, 247 scoped_ptr<base::DictionaryValue> config,
227 const DaemonController::CompletionCallback& done) { 248 const base::Closure& on_done,
249 const DaemonController::ErrorCallback& on_error) {
228 scoped_ptr<base::DictionaryValue> new_config( 250 scoped_ptr<base::DictionaryValue> new_config(
229 HostConfigFromJsonFile(GetConfigPath())); 251 HostConfigFromJsonFile(GetConfigPath()));
230 if (new_config) 252 if (!new_config) {
231 new_config->MergeDictionary(config.get()); 253 std::ostringstream error_message;
232 if (!new_config || !HostConfigToJsonFile(*new_config, GetConfigPath())) { 254 error_message << "Reading config from " << GetConfigPath().value()
233 LOG(ERROR) << "Failed to update config file."; 255 << " failed";
234 done.Run(DaemonController::RESULT_FAILED); 256 LOG(ERROR) << error_message;
257 on_error.Run(error_message.str(), FROM_HERE);
258 return;
259 }
260
261 new_config->MergeDictionary(config.get());
262 if (!HostConfigToJsonFile(*new_config, GetConfigPath())) {
263 std::ostringstream error_message;
264 error_message << "Writing config to " << GetConfigPath().value()
265 << " failed";
266 LOG(ERROR) << error_message;
267 on_error.Run(error_message.str(), FROM_HERE);
235 return; 268 return;
236 } 269 }
237 270
238 std::vector<std::string> args; 271 std::vector<std::string> args;
239 args.push_back("--reload"); 272 args.push_back("--reload");
240 int exit_code = 0; 273 if (RunHostScript(args, on_error)) {
241 DaemonController::AsyncResult result = DaemonController::RESULT_FAILED; 274 on_done.Run();
242 if (RunHostScript(args, &exit_code) && (exit_code == 0)) 275 }
243 result = DaemonController::RESULT_OK;
244
245 done.Run(result);
246 } 276 }
247 277
248 void DaemonControllerDelegateLinux::Stop( 278 void DaemonControllerDelegateLinux::Stop(
249 const DaemonController::CompletionCallback& done) { 279 const base::Closure& on_done,
280 const DaemonController::ErrorCallback& on_error) {
250 std::vector<std::string> args; 281 std::vector<std::string> args;
251 args.push_back("--stop"); 282 args.push_back("--stop");
252 int exit_code = 0; 283 if (RunHostScript(args, on_error)) {
253 DaemonController::AsyncResult result = DaemonController::RESULT_FAILED; 284 on_done.Run();
254 if (RunHostScript(args, &exit_code) && (exit_code == 0)) 285 }
255 result = DaemonController::RESULT_OK;
256
257 done.Run(result);
258 } 286 }
259 287
260 DaemonController::UsageStatsConsent 288 DaemonController::UsageStatsConsent
261 DaemonControllerDelegateLinux::GetUsageStatsConsent() { 289 DaemonControllerDelegateLinux::GetUsageStatsConsent() {
262 // Crash dump collection is not implemented on Linux yet. 290 // Crash dump collection is not implemented on Linux yet.
263 // http://crbug.com/130678. 291 // http://crbug.com/130678.
264 DaemonController::UsageStatsConsent consent; 292 DaemonController::UsageStatsConsent consent;
265 consent.supported = false; 293 consent.supported = false;
266 consent.allowed = false; 294 consent.allowed = false;
267 consent.set_by_policy = false; 295 consent.set_by_policy = false;
268 return consent; 296 return consent;
269 } 297 }
270 298
271 scoped_refptr<DaemonController> DaemonController::Create() { 299 scoped_refptr<DaemonController> DaemonController::Create() {
272 scoped_ptr<DaemonController::Delegate> delegate( 300 scoped_ptr<DaemonController::Delegate> delegate(
273 new DaemonControllerDelegateLinux()); 301 new DaemonControllerDelegateLinux());
274 return new DaemonController(delegate.Pass()); 302 return new DaemonController(delegate.Pass());
275 } 303 }
276 304
277 } // namespace remoting 305 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698