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

Side by Side Diff: remoting/host/daemon_process_win.cc

Issue 10855249: [Chromoting] The daemon process now starts the networking process and passes the host configuration… (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 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 | Annotate | Revision Log
OLDNEW
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/daemon_process.h" 5 #include "remoting/host/daemon_process.h"
6 6
7 #include "base/base_switches.h"
8 #include "base/bind.h"
9 #include "base/bind_helpers.h"
7 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/path_service.h"
8 #include "base/single_thread_task_runner.h" 12 #include "base/single_thread_task_runner.h"
13 #include "base/time.h"
14 #include "base/timer.h"
15 #include "base/utf_string_conversions.h"
9 #include "base/win/scoped_handle.h" 16 #include "base/win/scoped_handle.h"
17 #include "remoting/host/constants.h"
18 #include "remoting/host/win/launch_process_with_token.h"
19 #include "remoting/host/win/worker_process_launcher.h"
20
21 using base::win::ScopedHandle;
22 using base::TimeDelta;
23
24 namespace {
25
26 // The minimum and maximum delays between attempts to launch the networking
27 // process.
28 const int kMaxLaunchDelaySeconds = 60;
29 const int kMinLaunchDelaySeconds = 1;
30
31 const FilePath::CharType kMe2meHostBinaryName[] =
32 FILE_PATH_LITERAL("remoting_me2me_host.exe");
33
34 // The IPC channel name is passed to the networking process in the command line.
35 const char kDaemonPipeSwitchName[] = "daemon-pipe";
36
37 // The command line parameters that should be copied from the service's command
38 // line to the host process.
Wez 2012/08/21 00:18:57 nit: host process -> network process?
alexeypa (please no reviews) 2012/08/23 23:53:01 Done.
39 const char* kCopiedSwitchNames[] = {
40 "auth-config", "host-config", switches::kV, switches::kVModule };
41
42 // The security descriptor of the Chromoting IPC channel. It gives full access
Wez 2012/08/21 00:18:57 nit: Chromoting -> daemon, or just remove qualifie
alexeypa (please no reviews) 2012/08/23 23:53:01 Done.
43 // to LocalSystem and denies access by anyone else.
44 const char kDaemonPipeSecurityDescriptor[] = "O:SYG:SYD:(A;;GA;;;SY)";
45
46 } // namespace
10 47
11 namespace remoting { 48 namespace remoting {
12 49
13 class DaemonProcessWin : public DaemonProcess { 50 class DaemonProcessWin : public DaemonProcess,
51 public WorkerProcessLauncher::Delegate {
14 public: 52 public:
15 DaemonProcessWin(scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, 53 DaemonProcessWin(scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
16 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, 54 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
17 const base::Closure& stopped_callback); 55 const base::Closure& stopped_callback);
18 virtual ~DaemonProcessWin(); 56 virtual ~DaemonProcessWin();
19 57
20 // DaemonProcess implementation. 58 // DaemonProcess implementation.
21 virtual bool LaunchNetworkProcess() OVERRIDE; 59 virtual void LaunchNetworkProcess() OVERRIDE;
60
61 // WorkerProcessDelegate implementation.
Wez 2012/08/21 00:18:57 nit: WorkerProcessDelegate is inherited via Daemon
alexeypa (please no reviews) 2012/08/23 23:53:01 Done.
62 virtual void OnChannelConnected() OVERRIDE;
63
64 // Sends an IPC message to the worker process. This method can be called only
65 // after successful Start() and until Stop() is called or an error occurred.
66 virtual void Send(IPC::Message* message) OVERRIDE;
67
68 // WorkerProcessLauncher::Delegate implementation.
69 virtual bool DoLaunchProcess(
70 const std::string& channel_name,
71 ScopedHandle* process_exit_event_out) OVERRIDE;
72 virtual void DoKillProcess(DWORD exit_code) OVERRIDE;
73
74 protected:
75 // Stoppable implementation.
76 virtual void DoStop() OVERRIDE;
22 77
23 private: 78 private:
79 // Called when the launcher reports the process to be stopped.
Wez 2012/08/21 00:18:57 nit: ... reports the worker process has stopped.
alexeypa (please no reviews) 2012/08/23 23:53:01 Done.
80 void OnLauncherStopped();
81
82 // True if the network process is connected.
Wez 2012/08/21 00:18:57 nit: Connected to the Daemon, connected to Talk, o
alexeypa (please no reviews) 2012/08/23 23:53:01 Done.
83 bool connected_;
84
85 // Time of the last launch attempt.
86 base::Time launch_time_;
87
88 // Current backoff delay.
89 base::TimeDelta launch_backoff_;
90
91 // Timer used to schedule the next attempt to launch the process.
92 base::OneShotTimer<DaemonProcessWin> timer_;
93
94 scoped_ptr<WorkerProcessLauncher> launcher_;
95
96 ScopedHandle network_process_;
97
24 DISALLOW_COPY_AND_ASSIGN(DaemonProcessWin); 98 DISALLOW_COPY_AND_ASSIGN(DaemonProcessWin);
25 }; 99 };
26 100
27 DaemonProcessWin::DaemonProcessWin( 101 DaemonProcessWin::DaemonProcessWin(
28 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, 102 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
29 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, 103 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
30 const base::Closure& stopped_callback) 104 const base::Closure& stopped_callback)
31 : DaemonProcess(main_task_runner, io_task_runner, stopped_callback) { 105 : DaemonProcess(main_task_runner, io_task_runner, stopped_callback),
106 connected_(false) {
32 } 107 }
33 108
34 DaemonProcessWin::~DaemonProcessWin() { 109 DaemonProcessWin::~DaemonProcessWin() {
110 // Make sure that the object is completely stopped. The same check exists
111 // in Stoppable::~Stoppable() but this one allows us to examine the state of
112 // the object before destruction.
Wez 2012/08/21 00:18:57 But you're not examining any state; aren't you rea
alexeypa (please no reviews) 2012/08/21 17:16:36 In this case "us" are human beings equipped with a
Wez 2012/08/24 22:20:37 OK, so the comment is just misleading. ;) It's imp
alexeypa (please no reviews) 2012/08/27 23:16:41 OK, let try another version. In the cases like th
Wez 2012/08/30 20:36:04 You're right - sorry, I'll try to do that in futur
113 CHECK_EQ(stoppable_state(), Stoppable::kStopped);
35 } 114 }
36 115
37 bool DaemonProcessWin::LaunchNetworkProcess() { 116 void DaemonProcessWin::LaunchNetworkProcess() {
38 NOTIMPLEMENTED(); 117 DCHECK(main_task_runner()->BelongsToCurrentThread());
39 return false; 118 DCHECK(launcher_.get() == NULL);
119 DCHECK(!network_process_.IsValid());
120 DCHECK(!timer_.IsRunning());
121
122 launch_time_ = base::Time::Now();
123 launcher_.reset(new WorkerProcessLauncher(
124 this, this,
125 base::Bind(&DaemonProcessWin::OnLauncherStopped, base::Unretained(this)),
126 main_task_runner(),
127 io_task_runner()));
128 launcher_->Start(kDaemonPipeSecurityDescriptor);
129 }
130
131 void DaemonProcessWin::OnChannelConnected() {
132 connected_ = true;
133 DaemonProcess::OnChannelConnected();
134 }
135
136 void DaemonProcessWin::Send(IPC::Message* message) {
137 if (connected_) {
138 launcher_->Send(message);
139 } else {
140 delete message;
141 }
142 }
143
144 bool DaemonProcessWin::DoLaunchProcess(
145 const std::string& channel_name,
146 ScopedHandle* process_exit_event_out) {
147 DCHECK(main_task_runner()->BelongsToCurrentThread());
148 DCHECK(!network_process_.IsValid());
149
150 // Construct the host binary name.
151 FilePath dir_path;
152 if (!PathService::Get(base::DIR_EXE, &dir_path)) {
153 LOG(ERROR) << "Failed to get the executable file name.";
154 return false;
155 }
156 FilePath host_binary = dir_path.Append(kMe2meHostBinaryName);
157
158 // Create the host process command line passing the name of the IPC channel
159 // to use and copying known switches from the service's command line.
160 CommandLine command_line(host_binary);
161 command_line.AppendSwitchNative(kDaemonPipeSwitchName,
162 UTF8ToWide(channel_name));
163 command_line.CopySwitchesFrom(*CommandLine::ForCurrentProcess(),
164 kCopiedSwitchNames,
165 _countof(kCopiedSwitchNames));
166
167 // TODO(alexeypa): replace with a restricted token.
168 // See http://crbug.com/134694.
Wez 2012/08/21 00:18:57 nit: It's not clear what this comment means, even
alexeypa (please no reviews) 2012/08/23 23:53:01 Done.
169 ScopedHandle token;
170 if (!OpenProcessToken(GetCurrentProcess(),
171 MAXIMUM_ALLOWED,
172 token.Receive())) {
173 LOG_GETLASTERROR(ERROR) << "Failed to open process token";
Wez 2012/08/21 00:18:57 Is there ever a situation in which this can happen
alexeypa (please no reviews) 2012/08/23 23:53:01 Done.
174 return false;
175 }
176
177 // Try to launch the process and attach an object watcher to the returned
178 // handle so that we get notified when the process terminates.
179 ScopedHandle worker_thread;
180 if (!LaunchProcessWithToken(host_binary,
181 command_line.GetCommandLineString(),
182 token,
183 0,
184 &network_process_,
185 &worker_thread)) {
186 return false;
187 }
188
189 ScopedHandle process_exit_event;
190 if (!DuplicateHandle(GetCurrentProcess(),
191 network_process_,
192 GetCurrentProcess(),
193 process_exit_event.Receive(),
194 SYNCHRONIZE,
195 FALSE,
196 0)) {
197 LOG_GETLASTERROR(ERROR) << "Failed to duplicate a handle";
198 DoKillProcess(CONTROL_C_EXIT);
199 return false;
200 }
201
202 *process_exit_event_out = process_exit_event.Pass();
203 return true;
204 }
205
206 void DaemonProcessWin::DoKillProcess(DWORD exit_code) {
207 DCHECK(main_task_runner()->BelongsToCurrentThread());
208
209 if (network_process_.IsValid()) {
210 TerminateProcess(network_process_, exit_code);
211 }
212 }
213
214 void DaemonProcessWin::DoStop() {
215 DCHECK(main_task_runner()->BelongsToCurrentThread());
216
217 launch_backoff_ = base::TimeDelta();
Wez 2012/08/21 00:18:57 Why zero the backoff here? Isn't it useful to let
alexeypa (please no reviews) 2012/08/21 17:16:36 It will not start starting/stopping rapidly becaus
218 timer_.Stop();
219
220 if (launcher_.get() != NULL) {
221 launcher_->Stop();
222 }
223
224 // Wait for |launcher_| to be completely stopped.
Wez 2012/08/21 00:18:57 nit: Suggest: "Early exit if we're still waiting f
alexeypa (please no reviews) 2012/08/23 23:53:01 Done.
225 if (launcher_.get() != NULL) {
226 return;
227 }
228
229 DaemonProcess::DoStop();
230 }
231
232 void DaemonProcessWin::OnLauncherStopped() {
233 DCHECK(main_task_runner()->BelongsToCurrentThread());
234
235 DWORD exit_code = CONTROL_C_EXIT;
236 if (network_process_.IsValid()) {
Wez 2012/08/21 00:18:57 Should it be possible for |network_process_| not t
alexeypa (please no reviews) 2012/08/23 23:53:01 Done.
237 if (!::GetExitCodeProcess(network_process_, &exit_code)) {
238 LOG_GETLASTERROR(INFO)
239 << "Failed to query the exit code of the worker process";
240 exit_code = CONTROL_C_EXIT;
241 }
242
243 network_process_.Close();
244 }
245
246 connected_ = false;
247 launcher_.reset(NULL);
248
249 // Do not relaunch the network process if the caller has asked us to stop.
250 if (stoppable_state() != Stoppable::kRunning) {
251 Stop();
252 return;
253 }
254
255 // Stop trying to restart the worker process if its process exited due to
256 // misconfiguration.
257 if (kMinPermanentErrorExitCode <= exit_code &&
258 exit_code <= kMaxPermanentErrorExitCode) {
259 Stop();
260 return;
261 }
262
263 // Expand the backoff interval if the process has died quickly or reset it
264 // if it was up longer than the maximum backoff delay.
265 base::TimeDelta delta = base::Time::Now() - launch_time_;
266 if (delta < base::TimeDelta() ||
267 delta >= base::TimeDelta::FromSeconds(kMaxLaunchDelaySeconds)) {
268 launch_backoff_ = base::TimeDelta();
269 } else {
270 launch_backoff_ = std::max(
271 launch_backoff_ * 2, TimeDelta::FromSeconds(kMinLaunchDelaySeconds));
272 launch_backoff_ = std::min(
273 launch_backoff_, TimeDelta::FromSeconds(kMaxLaunchDelaySeconds));
274 }
275
276 // Try to launch the worker process.
277 timer_.Start(FROM_HERE, launch_backoff_,
278 this, &DaemonProcessWin::LaunchNetworkProcess);
40 } 279 }
41 280
42 scoped_ptr<DaemonProcess> DaemonProcess::Create( 281 scoped_ptr<DaemonProcess> DaemonProcess::Create(
43 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, 282 scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
44 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, 283 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
45 const base::Closure& stopped_callback) { 284 const base::Closure& stopped_callback) {
46 scoped_ptr<DaemonProcessWin> daemon_process( 285 scoped_ptr<DaemonProcessWin> daemon_process(
47 new DaemonProcessWin(main_task_runner, io_task_runner, stopped_callback)); 286 new DaemonProcessWin(main_task_runner, io_task_runner, stopped_callback));
48 return daemon_process.PassAs<DaemonProcess>(); 287 return daemon_process.PassAs<DaemonProcess>();
49 } 288 }
50 289
51 } // namespace remoting 290 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698