15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 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)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/win/worker_process_launcher.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/location.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/single_thread_task_runner.h"
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ipc/ipc_message.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "remoting/host/chromoting_messages.h"
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "remoting/host/host_exit_codes.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/worker_process_ipc_delegate.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::win::ScopedHandle;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const net::BackoffEntry::Policy kDefaultBackoffPolicy = {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Number of initial errors (in sequence) to ignore before applying
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // exponential back-off rules.
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initial delay for exponential back-off in ms.
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  100,
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Factor by which the waiting time will be multiplied.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  2,
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Fuzzing percentage. ex: 10% will spread requests randomly
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // between 90%-100% of the calculated time.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0,
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Maximum amount of time we are willing to delay our request in ms.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  60000,
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Time to keep an entry from being discarded even when it
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // has no significant state, -1 to never discard.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  -1,
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't use initial delay unless the last request was an error.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  false,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kKillProcessTimeoutSeconds = 5;
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)const int kLaunchResultTimeoutSeconds = 5;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)WorkerProcessLauncher::Delegate::~Delegate() {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)WorkerProcessLauncher::WorkerProcessLauncher(
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<WorkerProcessLauncher::Delegate> launcher_delegate,
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    WorkerProcessIpcDelegate* ipc_handler)
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    : ipc_handler_(ipc_handler),
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      launcher_delegate_(launcher_delegate.Pass()),
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      exit_code_(CONTROL_C_EXIT),
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ipc_enabled_(false),
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kill_process_timeout_(
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::TimeDelta::FromSeconds(kKillProcessTimeoutSeconds)),
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      launch_backoff_(&kDefaultBackoffPolicy) {
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(ipc_handler_ != NULL);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LaunchWorker();
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)WorkerProcessLauncher::~WorkerProcessLauncher() {
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(CalledOnValidThread());
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ipc_handler_ = NULL;
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  StopWorker();
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void WorkerProcessLauncher::Crash(
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const tracked_objects::Location& location) {
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(CalledOnValidThread());
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ask the worker process to crash voluntarily if it is still connected.
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (ipc_enabled_) {
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Send(new ChromotingDaemonMsg_Crash(location.function_name(),
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       location.file_name(),
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                       location.line_number()));
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Close the channel and ignore any not yet processed messages.
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  launcher_delegate_->CloseChannel();
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ipc_enabled_ = false;
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Give the worker process some time to crash.
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!kill_process_timer_.IsRunning()) {
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    kill_process_timer_.Start(FROM_HERE, kill_process_timeout_, this,
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                              &WorkerProcessLauncher::StopWorker);
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void WorkerProcessLauncher::Send(IPC::Message* message) {
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(CalledOnValidThread());
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ipc_enabled_) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    launcher_delegate_->Send(message);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete message;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void WorkerProcessLauncher::OnProcessLaunched(
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    base::win::ScopedHandle worker_process) {
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(CalledOnValidThread());
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!ipc_enabled_);
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!launch_timer_.IsRunning());
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!process_watcher_.GetWatchedObject());
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!worker_process_.IsValid());
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!process_watcher_.StartWatching(worker_process.Get(), this)) {
11790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    StopWorker();
11890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ipc_enabled_ = true;
12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  worker_process_ = worker_process.Pass();
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void WorkerProcessLauncher::OnFatalError() {
12690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(CalledOnValidThread());
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StopWorker();
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool WorkerProcessLauncher::OnMessageReceived(
13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const IPC::Message& message) {
13390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(CalledOnValidThread());
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ipc_enabled_)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return ipc_handler_->OnMessageReceived(message);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void WorkerProcessLauncher::OnChannelConnected(int32 peer_pid) {
14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(CalledOnValidThread());
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ipc_enabled_)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This can result in |this| being deleted, so this call must be the last in
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this method.
14990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ipc_handler_->OnChannelConnected(peer_pid);
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void WorkerProcessLauncher::OnChannelError() {
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(CalledOnValidThread());
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Schedule a delayed termination of the worker process. Usually, the pipe is
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // disconnected when the worker process is about to exit. Waiting a little bit
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // here allows the worker to exit completely and so, notify
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |process_watcher_|. As the result KillProcess() will not be called and
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the original exit code reported by the worker process will be retrieved.
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!kill_process_timer_.IsRunning()) {
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    kill_process_timer_.Start(FROM_HERE, kill_process_timeout_, this,
16290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                              &WorkerProcessLauncher::StopWorker);
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void WorkerProcessLauncher::OnObjectSignaled(HANDLE object) {
16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(CalledOnValidThread());
16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!process_watcher_.GetWatchedObject());
16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_EQ(exit_code_, CONTROL_C_EXIT);
1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_EQ(worker_process_.Get(), object);
17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Get exit code of the worker process if it is available.
1731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!::GetExitCodeProcess(worker_process_.Get(), &exit_code_)) {
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    PLOG(INFO) << "Failed to query the exit code of the worker process";
17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    exit_code_ = CONTROL_C_EXIT;
17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  worker_process_.Close();
17990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  StopWorker();
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void WorkerProcessLauncher::LaunchWorker() {
18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(CalledOnValidThread());
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!ipc_enabled_);
18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!kill_process_timer_.IsRunning());
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!launch_timer_.IsRunning());
18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!process_watcher_.GetWatchedObject());
18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!launch_result_timer_.IsRunning());
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  exit_code_ = CONTROL_C_EXIT;
19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Make sure launching a process will not take forever.
19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  launch_result_timer_.Start(
19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      FROM_HERE, base::TimeDelta::FromSeconds(kLaunchResultTimeoutSeconds),
19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      this, &WorkerProcessLauncher::RecordLaunchResult);
19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  launcher_delegate_->LaunchProcess(this);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void WorkerProcessLauncher::RecordLaunchResult() {
20190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(CalledOnValidThread());
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!worker_process_.IsValid()) {
20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    LOG(WARNING) << "A worker process failed to start within "
20590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                 << kLaunchResultTimeoutSeconds << " seconds.";
20690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
20790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    launch_backoff_.InformOfRequest(false);
20890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    StopWorker();
20990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Assume success if the worker process has been running for a few seconds.
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  launch_backoff_.InformOfRequest(true);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void WorkerProcessLauncher::RecordSuccessfulLaunchForTest() {
21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(CalledOnValidThread());
21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
21990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (launch_result_timer_.IsRunning()) {
22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    launch_result_timer_.Stop();
22190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    RecordLaunchResult();
22290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
22390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
22490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
22590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void WorkerProcessLauncher::SetKillProcessTimeoutForTest(
22690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const base::TimeDelta& timeout) {
22790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(CalledOnValidThread());
22890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  kill_process_timeout_ = timeout;
23090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void WorkerProcessLauncher::StopWorker() {
23390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(CalledOnValidThread());
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Record a launch failure if the process exited too soon.
23690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (launch_result_timer_.IsRunning()) {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    launch_backoff_.InformOfRequest(false);
23890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    launch_result_timer_.Stop();
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ignore any remaining IPC messages.
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ipc_enabled_ = false;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Stop monitoring the worker process.
24590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  process_watcher_.StopWatching();
24690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  worker_process_.Close();
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  kill_process_timer_.Stop();
24990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  launcher_delegate_->KillProcess();
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do not relaunch the worker process if the caller has asked us to stop.
25290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (stopping())
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Stop trying to restart the worker process if it exited due to
25690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // misconfiguration.
25790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (kMinPermanentErrorExitCode <= exit_code_ &&
25890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      exit_code_ <= kMaxPermanentErrorExitCode) {
259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    ipc_handler_->OnPermanentError(exit_code_);
26090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
26390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Schedule the next attempt to launch the worker process.
26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  launch_timer_.Start(FROM_HERE, launch_backoff_.GetTimeUntilRelease(), this,
26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                      &WorkerProcessLauncher::LaunchWorker);
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace remoting
269