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

Side by Side Diff: remoting/host/win/worker_process_launcher.cc

Issue 15077010: [Chromoting] Refactored worker process launching code and speeded up the desktop process launch. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: - Created 7 years, 7 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/win/worker_process_launcher.h" 5 #include "remoting/host/win/worker_process_launcher.h"
6 6
7 #include "base/location.h" 7 #include "base/location.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/single_thread_task_runner.h" 9 #include "base/single_thread_task_runner.h"
10 #include "base/time.h" 10 #include "base/time.h"
11 #include "base/timer.h"
12 #include "base/win/object_watcher.h"
13 #include "base/win/windows_version.h" 11 #include "base/win/windows_version.h"
14 #include "ipc/ipc_listener.h"
15 #include "ipc/ipc_message.h" 12 #include "ipc/ipc_message.h"
16 #include "net/base/backoff_entry.h"
17 #include "remoting/host/chromoting_messages.h" 13 #include "remoting/host/chromoting_messages.h"
14 #include "remoting/host/host_exit_codes.h"
18 #include "remoting/host/worker_process_ipc_delegate.h" 15 #include "remoting/host/worker_process_ipc_delegate.h"
19 16
20 using base::TimeDelta; 17 using base::TimeDelta;
21 using base::win::ScopedHandle; 18 using base::win::ScopedHandle;
22 19
23 const net::BackoffEntry::Policy kDefaultBackoffPolicy = { 20 const net::BackoffEntry::Policy kDefaultBackoffPolicy = {
24 // Number of initial errors (in sequence) to ignore before applying 21 // Number of initial errors (in sequence) to ignore before applying
25 // exponential back-off rules. 22 // exponential back-off rules.
26 0, 23 0,
27 24
28 // Initial delay for exponential back-off in ms. 25 // Initial delay for exponential back-off in ms.
29 1000, 26 100,
garykac 2013/05/15 23:24:30 Wahoo! 900ms speedup! ^_^
30 27
31 // Factor by which the waiting time will be multiplied. 28 // Factor by which the waiting time will be multiplied.
32 2, 29 2,
33 30
34 // Fuzzing percentage. ex: 10% will spread requests randomly 31 // Fuzzing percentage. ex: 10% will spread requests randomly
35 // between 90%-100% of the calculated time. 32 // between 90%-100% of the calculated time.
36 0, 33 0,
37 34
38 // Maximum amount of time we are willing to delay our request in ms. 35 // Maximum amount of time we are willing to delay our request in ms.
39 60000, 36 60000,
40 37
41 // Time to keep an entry from being discarded even when it 38 // Time to keep an entry from being discarded even when it
42 // has no significant state, -1 to never discard. 39 // has no significant state, -1 to never discard.
43 -1, 40 -1,
44 41
45 // Don't use initial delay unless the last request was an error. 42 // Don't use initial delay unless the last request was an error.
46 false, 43 false,
47 }; 44 };
48 45
49 const int kKillProcessTimeoutSeconds = 5; 46 const int kKillProcessTimeoutSeconds = 5;
50 const int kLaunchSuccessTimeoutSeconds = 2; 47 const int kLaunchResultTimeoutSeconds = 5;
51 48
52 namespace remoting { 49 namespace remoting {
53 50
54 // Launches a worker process that is controlled via an IPC channel. All
55 // interaction with the spawned process is through the IPC::Listener and Send()
56 // method. In case of error the channel is closed and the worker process is
57 // terminated.
58 class WorkerProcessLauncher::Core
59 : public base::RefCountedThreadSafe<Core, Core>,
60 public base::win::ObjectWatcher::Delegate,
61 public IPC::Listener {
62 public:
63 // Creates the launcher that will use |launcher_delegate| to manage the worker
64 // process and |worker_delegate| to handle IPCs. The caller must ensure that
65 // |worker_delegate| remains valid until Stoppable::Stop() method has been
66 // called.
67 //
68 // The caller should call all the methods on this class on
69 // the |caller_task_runner| thread. Methods of both delegate interfaces are
70 // called on the |caller_task_runner| thread as well.
71 Core(scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
72 scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate,
73 WorkerProcessIpcDelegate* worker_delegate);
74
75 // Launches the worker process.
76 void Start();
77
78 // Stops the worker process asynchronously. The caller can drop the reference
79 // to |this| as soon as Stop() returns.
80 void Stop();
81
82 // See WorkerProcessLauncher::Crash().
83 void Crash(const tracked_objects::Location& location);
84
85 // See WorkerProcessLauncher::Send().
86 void Send(IPC::Message* message);
87
88 // Used to emulate |launch_success_timer_| expiration.
89 void ResetLaunchSuccessTimeoutForTest();
90
91 // Set the desired timeout for |kill_process_timer_|.
92 void SetKillProcessTimeoutForTest(const base::TimeDelta& timeout);
93
94 // base::win::ObjectWatcher::Delegate implementation.
95 virtual void OnObjectSignaled(HANDLE object) OVERRIDE;
96
97 // IPC::Listener implementation.
98 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
99 virtual void OnChannelConnected(int32 peer_pid) OVERRIDE;
100 virtual void OnChannelError() OVERRIDE;
101
102 // Destroys |Core| instances on the |caller_task_runner_| thread. This is
103 // needed because base::OneShotTimer instances must be destroyed on the same
104 // thread they were created on.
105 static void Destruct(const Core* core);
106
107 private:
108 friend class base::DeleteHelper<Core>;
109 virtual ~Core();
110
111 // Attempts to launch the worker process. Schedules next launch attempt if
112 // creation of the process fails.
113 void LaunchWorker();
114
115 // Records a successful launch attempt.
116 void RecordSuccessfulLaunch();
117
118 // Stops the worker process asynchronously and schedules next launch attempt
119 // unless Stop() has been called already.
120 void StopWorker();
121
122 // All public methods are called on the |caller_task_runner| thread.
123 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_;
124
125 // Implements specifics of launching a worker process.
126 scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate_;
127
128 // Handles IPC messages sent by the worker process.
129 WorkerProcessIpcDelegate* worker_delegate_;
130
131 // Pointer to GetNamedPipeClientProcessId() API if it is available.
132 typedef BOOL (WINAPI * GetNamedPipeClientProcessIdFn)(HANDLE, DWORD*);
133 GetNamedPipeClientProcessIdFn get_named_pipe_client_pid_;
134
135 // True if IPC messages should be passed to |worker_delegate_|.
136 bool ipc_enabled_;
137
138 // The timer used to delay termination of the worker process when an IPC error
139 // occured or when Crash() request is pending
140 base::OneShotTimer<Core> kill_process_timer_;
141
142 // The default timeout for |kill_process_timer_|.
143 base::TimeDelta kill_process_timeout_;
144
145 // Launch backoff state.
146 net::BackoffEntry launch_backoff_;
147
148 // Timer used to delay recording a successfull launch.
149 base::OneShotTimer<Core> launch_success_timer_;
150
151 // Timer used to schedule the next attempt to launch the process.
152 base::OneShotTimer<Core> launch_timer_;
153
154 // Used to determine when the launched process terminates.
155 base::win::ObjectWatcher process_watcher_;
156
157 // A waiting handle that becomes signalled once the launched process has
158 // been terminated.
159 ScopedHandle process_exit_event_;
160
161 // True when Stop() has been called.
162 bool stopping_;
163
164 DISALLOW_COPY_AND_ASSIGN(Core);
165 };
166
167 WorkerProcessLauncher::Delegate::~Delegate() { 51 WorkerProcessLauncher::Delegate::~Delegate() {
168 } 52 }
169 53
170 WorkerProcessLauncher::Core::Core( 54 WorkerProcessLauncher::WorkerProcessLauncher(
171 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
172 scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate, 55 scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate,
173 WorkerProcessIpcDelegate* worker_delegate) 56 WorkerProcessIpcDelegate* ipc_handler)
174 : caller_task_runner_(caller_task_runner), 57 : ipc_handler_(ipc_handler),
175 launcher_delegate_(launcher_delegate.Pass()), 58 launcher_delegate_(launcher_delegate.Pass()),
176 worker_delegate_(worker_delegate), 59 exit_code_(CONTROL_C_EXIT),
177 get_named_pipe_client_pid_(NULL),
178 ipc_enabled_(false), 60 ipc_enabled_(false),
179 kill_process_timeout_( 61 kill_process_timeout_(
180 base::TimeDelta::FromSeconds(kKillProcessTimeoutSeconds)), 62 base::TimeDelta::FromSeconds(kKillProcessTimeoutSeconds)),
181 launch_backoff_(&kDefaultBackoffPolicy), 63 launch_backoff_(&kDefaultBackoffPolicy) {
182 stopping_(false) { 64 DCHECK(ipc_handler_ != NULL);
183 DCHECK(caller_task_runner_->BelongsToCurrentThread());
184 }
185
186 void WorkerProcessLauncher::Core::Start() {
187 DCHECK(caller_task_runner_->BelongsToCurrentThread());
188 DCHECK(!stopping_);
189 65
190 LaunchWorker(); 66 LaunchWorker();
191 } 67 }
192 68
193 void WorkerProcessLauncher::Core::Stop() { 69 WorkerProcessLauncher::~WorkerProcessLauncher() {
194 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 70 DCHECK(CalledOnValidThread());
195 71
196 if (!stopping_) { 72 ipc_handler_ = NULL;
197 stopping_ = true; 73 StopWorker();
198 worker_delegate_ = NULL;
199 StopWorker();
200 }
201 } 74 }
202 75
203 void WorkerProcessLauncher::Core::Crash( 76 void WorkerProcessLauncher::Crash(
204 const tracked_objects::Location& location) { 77 const tracked_objects::Location& location) {
205 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 78 DCHECK(CalledOnValidThread());
206 79
207 // Ask the worker process to crash voluntarily if it is still connected. 80 // Ask the worker process to crash voluntarily if it is still connected.
208 if (ipc_enabled_) { 81 if (ipc_enabled_) {
209 Send(new ChromotingDaemonMsg_Crash(location.function_name(), 82 Send(new ChromotingDaemonMsg_Crash(location.function_name(),
210 location.file_name(), 83 location.file_name(),
211 location.line_number())); 84 location.line_number()));
212 } 85 }
213 86
214 // Close the channel and ignore any not yet processed messages. 87 // Close the channel and ignore any not yet processed messages.
215 launcher_delegate_->CloseChannel(); 88 launcher_delegate_->CloseChannel();
216 ipc_enabled_ = false; 89 ipc_enabled_ = false;
217 90
218 // Give the worker process some time to crash. 91 // Give the worker process some time to crash.
219 if (!kill_process_timer_.IsRunning()) { 92 if (!kill_process_timer_.IsRunning()) {
220 kill_process_timer_.Start(FROM_HERE, kill_process_timeout_, this, 93 kill_process_timer_.Start(FROM_HERE, kill_process_timeout_, this,
221 &Core::StopWorker); 94 &WorkerProcessLauncher::StopWorker);
222 } 95 }
223 } 96 }
224 97
225 void WorkerProcessLauncher::Core::Send(IPC::Message* message) { 98 void WorkerProcessLauncher::Send(IPC::Message* message) {
226 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 99 DCHECK(CalledOnValidThread());
227 100
228 if (ipc_enabled_) { 101 if (ipc_enabled_) {
229 launcher_delegate_->Send(message); 102 launcher_delegate_->Send(message);
230 } else { 103 } else {
231 delete message; 104 delete message;
232 } 105 }
233 } 106 }
234 107
235 void WorkerProcessLauncher::Core::ResetLaunchSuccessTimeoutForTest() { 108 void WorkerProcessLauncher::OnProcessLaunched(
236 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 109 base::win::ScopedHandle worker_process) {
110 DCHECK(CalledOnValidThread());
111 DCHECK(!ipc_enabled_);
112 DCHECK(!launch_timer_.IsRunning());
113 DCHECK(!process_watcher_.GetWatchedObject());
114 DCHECK(!worker_process_.IsValid());
237 115
238 if (launch_success_timer_.IsRunning()) { 116 if (!process_watcher_.StartWatching(worker_process, this)) {
239 launch_success_timer_.Stop(); 117 StopWorker();
240 RecordSuccessfulLaunch(); 118 return;
241 } 119 }
120
121 ipc_enabled_ = true;
122 worker_process_ = worker_process.Pass();
242 } 123 }
243 124
244 void WorkerProcessLauncher::Core::SetKillProcessTimeoutForTest( 125 void WorkerProcessLauncher::OnFatalError() {
245 const base::TimeDelta& timeout) { 126 DCHECK(CalledOnValidThread());
246 DCHECK(caller_task_runner_->BelongsToCurrentThread());
247
248 kill_process_timeout_ = timeout;
249 }
250
251 void WorkerProcessLauncher::Core::OnObjectSignaled(HANDLE object) {
252 DCHECK(caller_task_runner_->BelongsToCurrentThread());
253 DCHECK(process_watcher_.GetWatchedObject() == NULL);
254 127
255 StopWorker(); 128 StopWorker();
256 } 129 }
257 130
258 bool WorkerProcessLauncher::Core::OnMessageReceived( 131 bool WorkerProcessLauncher::OnMessageReceived(
259 const IPC::Message& message) { 132 const IPC::Message& message) {
260 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 133 DCHECK(CalledOnValidThread());
261 134
262 if (!ipc_enabled_) 135 if (!ipc_enabled_)
263 return false; 136 return false;
264 137
265 return worker_delegate_->OnMessageReceived(message); 138 return ipc_handler_->OnMessageReceived(message);
266 } 139 }
267 140
268 void WorkerProcessLauncher::Core::OnChannelConnected(int32 peer_pid) { 141 void WorkerProcessLauncher::OnChannelConnected(int32 peer_pid) {
269 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 142 DCHECK(CalledOnValidThread());
270 143
271 if (!ipc_enabled_) 144 if (!ipc_enabled_)
272 return; 145 return;
273 146
274 // Verify |peer_pid| because it is controlled by the client and cannot be
garykac 2013/05/15 23:24:30 Could you add a comment in the code mentioning why
alexeypa (please no reviews) 2013/05/16 17:50:04 Added this comment to the declaration of WorkerPro
275 // trusted.
276 DWORD actual_pid = launcher_delegate_->GetProcessId();
277 if (peer_pid != static_cast<int32>(actual_pid)) {
278 LOG(ERROR) << "The actual client PID " << actual_pid
279 << " does not match the one reported by the client: "
280 << peer_pid;
281 StopWorker();
282 return;
283 }
284
285 // This can result in |this| being deleted, so this call must be the last in 147 // This can result in |this| being deleted, so this call must be the last in
286 // this method. 148 // this method.
287 worker_delegate_->OnChannelConnected(peer_pid); 149 ipc_handler_->OnChannelConnected(peer_pid);
288 } 150 }
289 151
290 void WorkerProcessLauncher::Core::OnChannelError() { 152 void WorkerProcessLauncher::OnChannelError() {
291 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 153 DCHECK(CalledOnValidThread());
292 154
293 // Schedule a delayed termination of the worker process. Usually, the pipe is 155 // Schedule a delayed termination of the worker process. Usually, the pipe is
294 // disconnected when the worker process is about to exit. Waiting a little bit 156 // disconnected when the worker process is about to exit. Waiting a little bit
295 // here allows the worker to exit completely and so, notify 157 // here allows the worker to exit completely and so, notify
296 // |process_watcher_|. As the result KillProcess() will not be called and 158 // |process_watcher_|. As the result KillProcess() will not be called and
297 // the original exit code reported by the worker process will be retrieved. 159 // the original exit code reported by the worker process will be retrieved.
298 if (!kill_process_timer_.IsRunning()) { 160 if (!kill_process_timer_.IsRunning()) {
299 kill_process_timer_.Start(FROM_HERE, kill_process_timeout_, this, 161 kill_process_timer_.Start(FROM_HERE, kill_process_timeout_, this,
300 &Core::StopWorker); 162 &WorkerProcessLauncher::StopWorker);
301 } 163 }
302 } 164 }
303 165
304 // static 166 void WorkerProcessLauncher::OnObjectSignaled(HANDLE object) {
305 void WorkerProcessLauncher::Core::Destruct(const Core* core) { 167 DCHECK(CalledOnValidThread());
306 core->caller_task_runner_->DeleteSoon(FROM_HERE, core); 168 DCHECK(!process_watcher_.GetWatchedObject());
307 } 169 DCHECK_EQ(exit_code_, CONTROL_C_EXIT);
170 DCHECK_EQ(worker_process_, object);
308 171
309 WorkerProcessLauncher::Core::~Core() { 172 // Get exit code of the worker process if it is available.
310 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 173 if (!::GetExitCodeProcess(worker_process_, &exit_code_)) {
311 DCHECK(stopping_); 174 LOG_GETLASTERROR(INFO)
312 } 175 << "Failed to query the exit code of the worker process";
313 176 exit_code_ = CONTROL_C_EXIT;
314 void WorkerProcessLauncher::Core::LaunchWorker() {
315 DCHECK(caller_task_runner_->BelongsToCurrentThread());
316 DCHECK(!ipc_enabled_);
317 DCHECK(!launch_success_timer_.IsRunning());
318 DCHECK(!launch_timer_.IsRunning());
319 DCHECK(!process_exit_event_.IsValid());
320 DCHECK(process_watcher_.GetWatchedObject() == NULL);
321
322 // Launch the process and attach an object watcher to the returned process
323 // handle so that we get notified if the process terminates.
324 if (launcher_delegate_->LaunchProcess(this, &process_exit_event_)) {
325 if (process_watcher_.StartWatching(process_exit_event_, this)) {
326 ipc_enabled_ = true;
327 // Record a successful launch once the process has been running for at
328 // least two seconds.
329 launch_success_timer_.Start(
330 FROM_HERE, base::TimeDelta::FromSeconds(kLaunchSuccessTimeoutSeconds),
331 this, &Core::RecordSuccessfulLaunch);
332 return;
333 }
334
335 launcher_delegate_->KillProcess(CONTROL_C_EXIT);
336 } 177 }
337 178
338 launch_backoff_.InformOfRequest(false); 179 worker_process_.Close();
339 StopWorker(); 180 StopWorker();
340 } 181 }
341 182
342 void WorkerProcessLauncher::Core::RecordSuccessfulLaunch() { 183 void WorkerProcessLauncher::LaunchWorker() {
343 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 184 DCHECK(CalledOnValidThread());
185 DCHECK(!ipc_enabled_);
186 DCHECK(!kill_process_timer_.IsRunning());
187 DCHECK(!launch_timer_.IsRunning());
188 DCHECK(!process_watcher_.GetWatchedObject());
189 DCHECK(!launch_result_timer_.IsRunning());
344 190
191 exit_code_ = CONTROL_C_EXIT;
192
193 // Make sure launching a process will not take forever.
194 launch_result_timer_.Start(
195 FROM_HERE, base::TimeDelta::FromSeconds(kLaunchResultTimeoutSeconds),
196 this, &WorkerProcessLauncher::RecordLaunchResult);
197
198 launcher_delegate_->LaunchProcess(this);
199 }
200
201 void WorkerProcessLauncher::RecordLaunchResult() {
202 DCHECK(CalledOnValidThread());
203
204 if (!worker_process_.IsValid()) {
205 LOG(WARNING) << "A worker process failed to start within "
206 << kLaunchResultTimeoutSeconds << " seconds.";
207
208 launch_backoff_.InformOfRequest(false);
209 StopWorker();
210 return;
211 }
212
213 // Assume success if the worker process has been running for a few seconds.
345 launch_backoff_.InformOfRequest(true); 214 launch_backoff_.InformOfRequest(true);
346 } 215 }
347 216
348 void WorkerProcessLauncher::Core::StopWorker() { 217 void WorkerProcessLauncher::RecordSuccessfulLaunchForTest() {
349 DCHECK(caller_task_runner_->BelongsToCurrentThread()); 218 DCHECK(CalledOnValidThread());
350 219
351 // Keep the object alive in case one of delegates decides to delete |this|. 220 if (launch_result_timer_.IsRunning()) {
352 scoped_refptr<Core> self = this; 221 launch_result_timer_.Stop();
222 RecordLaunchResult();
223 }
224 }
225
226 void WorkerProcessLauncher::SetKillProcessTimeoutForTest(
227 const base::TimeDelta& timeout) {
228 DCHECK(CalledOnValidThread());
229
230 kill_process_timeout_ = timeout;
231 }
232
233 void WorkerProcessLauncher::StopWorker() {
234 DCHECK(CalledOnValidThread());
353 235
354 // Record a launch failure if the process exited too soon. 236 // Record a launch failure if the process exited too soon.
355 if (launch_success_timer_.IsRunning()) { 237 if (launch_result_timer_.IsRunning()) {
356 launch_success_timer_.Stop();
357 launch_backoff_.InformOfRequest(false); 238 launch_backoff_.InformOfRequest(false);
239 launch_result_timer_.Stop();
358 } 240 }
359 241
360 // Ignore any remaining IPC messages. 242 // Ignore any remaining IPC messages.
361 ipc_enabled_ = false; 243 ipc_enabled_ = false;
362 244
363 // Kill the process if it has been started already. 245 // Stop monitoring the worker process.
364 if (process_watcher_.GetWatchedObject() != NULL) { 246 process_watcher_.StopWatching();
365 launcher_delegate_->KillProcess(CONTROL_C_EXIT); 247 worker_process_.Close();
366 248
367 // Wait until the process is actually stopped if the caller keeps 249 kill_process_timer_.Stop();
368 // a reference to |this|. Otherwise terminate everything right now - there 250 launcher_delegate_->KillProcess();
369 // won't be a second chance.
370 if (!stopping_)
371 return;
372 251
373 process_watcher_.StopWatching(); 252 // Do not relaunch the worker process if the caller has asked us to stop.
253 if (stopping())
254 return;
255
256 // Stop trying to restart the worker process if it exited due to
257 // misconfiguration.
258 if (kMinPermanentErrorExitCode <= exit_code_ &&
259 exit_code_ <= kMaxPermanentErrorExitCode) {
260 ipc_handler_->OnPermanentError();
261 return;
374 } 262 }
375 263
376 kill_process_timer_.Stop(); 264 // Schedule the next attempt to launch the worker process.
377 process_exit_event_.Close(); 265 launch_timer_.Start(FROM_HERE, launch_backoff_.GetTimeUntilRelease(), this,
378 266 &WorkerProcessLauncher::LaunchWorker);
379 // Do not relaunch the worker process if the caller has asked us to stop.
380 if (stopping_)
381 return;
382
383 if (launcher_delegate_->IsPermanentError(launch_backoff_.failure_count())) {
384 if (!stopping_)
385 worker_delegate_->OnPermanentError();
386 } else {
387 // Schedule the next attempt to launch the worker process.
388 launch_timer_.Start(FROM_HERE, launch_backoff_.GetTimeUntilRelease(), this,
389 &Core::LaunchWorker);
390 }
391 } 267 }
392 268
393 WorkerProcessLauncher::WorkerProcessLauncher(
394 scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
395 scoped_ptr<Delegate> launcher_delegate,
396 WorkerProcessIpcDelegate* worker_delegate) {
397 core_ = new Core(caller_task_runner, launcher_delegate.Pass(),
398 worker_delegate);
399 core_->Start();
400 }
401
402 WorkerProcessLauncher::~WorkerProcessLauncher() {
403 core_->Stop();
404 core_ = NULL;
405 }
406
407 void WorkerProcessLauncher::Crash(const tracked_objects::Location& location) {
408 core_->Crash(location);
409 }
410
411 void WorkerProcessLauncher::Send(IPC::Message* message) {
412 core_->Send(message);
413 }
414
415 void WorkerProcessLauncher::ResetLaunchSuccessTimeoutForTest() {
416 core_->ResetLaunchSuccessTimeoutForTest();
417 }
418
419 void WorkerProcessLauncher::SetKillProcessTimeoutForTest(
420 const base::TimeDelta& timeout) {
421 core_->SetKillProcessTimeoutForTest(timeout);
422 }
423
424
425 } // namespace remoting 269 } // namespace remoting
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698