Index: chrome/browser/chromeos/process_proxy/process_proxy.cc |
diff --git a/chrome/browser/chromeos/process_proxy/process_proxy.cc b/chrome/browser/chromeos/process_proxy/process_proxy.cc |
deleted file mode 100644 |
index 98ac0c008f8c198ca27687e425def525264318ac..0000000000000000000000000000000000000000 |
--- a/chrome/browser/chromeos/process_proxy/process_proxy.cc |
+++ /dev/null |
@@ -1,254 +0,0 @@ |
-// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "chrome/browser/chromeos/process_proxy/process_proxy.h" |
- |
-#include <fcntl.h> |
-#include <stdlib.h> |
-#include <sys/ioctl.h> |
- |
-#include "base/bind.h" |
-#include "base/command_line.h" |
-#include "base/file_util.h" |
-#include "base/posix/eintr_wrapper.h" |
-#include "base/process_util.h" |
-#include "base/logging.h" |
-#include "base/threading/thread.h" |
-#include "chrome/browser/chromeos/process_proxy/process_output_watcher.h" |
-#include "content/public/browser/browser_thread.h" |
- |
-namespace { |
- |
-enum PipeEnd { |
- PIPE_END_READ, |
- PIPE_END_WRITE |
-}; |
- |
-enum PseudoTerminalFd { |
- PT_MASTER_FD, |
- PT_SLAVE_FD |
-}; |
- |
-const int kInvalidFd = -1; |
- |
-} // namespace |
- |
-ProcessProxy::ProcessProxy(): process_launched_(false), |
- callback_set_(false), |
- watcher_started_(false) { |
- // Set pipes to initial, invalid value so we can easily know if a pipe was |
- // opened by us. |
- ClearAllFdPairs(); |
-}; |
- |
-bool ProcessProxy::Open(const std::string& command, pid_t* pid) { |
- if (process_launched_) |
- return false; |
- |
- if (!CreatePseudoTerminalPair(pt_pair_)) { |
- return false; |
- } |
- |
- process_launched_ = LaunchProcess(command, pt_pair_[PT_SLAVE_FD], &pid_); |
- |
- if (process_launched_) { |
- // We won't need these anymore. These will be used by the launched process. |
- CloseFd(&pt_pair_[PT_SLAVE_FD]); |
- *pid = pid_; |
- LOG(WARNING) << "Process launched: " << pid_; |
- } else { |
- CloseFdPair(pt_pair_); |
- } |
- return process_launched_; |
-} |
- |
-bool ProcessProxy::StartWatchingOnThread(base::Thread* watch_thread, |
- const ProcessOutputCallback& callback) { |
- DCHECK(process_launched_); |
- if (watcher_started_) |
- return false; |
- if (pipe(shutdown_pipe_)) |
- return false; |
- |
- // We give ProcessOutputWatcher a copy of master to make life easier during |
- // tear down. |
- // TODO(tbarzic): improve fd managment. |
- int master_copy = HANDLE_EINTR(dup(pt_pair_[PT_MASTER_FD])); |
- if (master_copy == -1) |
- return false; |
- |
- callback_set_ = true; |
- callback_ = callback; |
- |
- // This object will delete itself once watching is stopped. |
- // It also takes ownership of the passed fds. |
- ProcessOutputWatcher* output_watcher = |
- new ProcessOutputWatcher(master_copy, |
- shutdown_pipe_[PIPE_END_READ], |
- base::Bind(&ProcessProxy::OnProcessOutput, |
- this)); |
- |
- // Output watcher took ownership of the read end of shutdown pipe. |
- shutdown_pipe_[PIPE_END_READ] = -1; |
- |
- // |watch| thread is blocked by |output_watcher| from now on. |
- watch_thread->message_loop()->PostTask(FROM_HERE, |
- base::Bind(&ProcessOutputWatcher::Start, |
- base::Unretained(output_watcher))); |
- watcher_started_ = true; |
- return true; |
-} |
- |
-void ProcessProxy::OnProcessOutput(ProcessOutputType type, |
- const std::string& output) { |
- // We have to check if callback is set on FILE thread.. |
- if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)) { |
- content::BrowserThread::PostTask(content::BrowserThread::FILE, FROM_HERE, |
- base::Bind(&ProcessProxy::OnProcessOutput, this, type, output)); |
- return; |
- } |
- |
- // We may receive some output even after Close was called (crosh process does |
- // not have to quit instantly, or there may be some trailing data left in |
- // output stream fds). In that case owner of the callback may be gone so we |
- // don't want to send it anything. |callback_set_| is reset when this gets |
- // closed. |
- if (callback_set_) |
- callback_.Run(type, output); |
-} |
- |
-bool ProcessProxy::StopWatching() { |
- if (!watcher_started_) |
- return true; |
- // Signal Watcher that we are done. We use self-pipe trick to unblock watcher. |
- // Anything may be written to the pipe. |
- const char message[] = "q"; |
- return file_util::WriteFileDescriptor(shutdown_pipe_[PIPE_END_WRITE], |
- message, sizeof(message)); |
-} |
- |
-void ProcessProxy::Close() { |
- if (!process_launched_) |
- return; |
- |
- process_launched_ = false; |
- callback_set_ = false; |
- |
- base::KillProcess(pid_, 0, true /* wait */); |
- |
- // TODO(tbarzic): What if this fails? |
- StopWatching(); |
- |
- CloseAllFdPairs(); |
-} |
- |
-bool ProcessProxy::Write(const std::string& text) { |
- if (!process_launched_) |
- return false; |
- |
- // We don't want to write '\0' to the pipe. |
- size_t data_size = text.length() * sizeof(*text.c_str()); |
- int bytes_written = |
- file_util::WriteFileDescriptor(pt_pair_[PT_MASTER_FD], |
- text.c_str(), data_size); |
- return (bytes_written == static_cast<int>(data_size)); |
-} |
- |
-bool ProcessProxy::OnTerminalResize(int width, int height) { |
- if (width < 0 || height < 0) |
- return false; |
- |
- winsize ws; |
- // Number of rows. |
- ws.ws_row = height; |
- // Number of columns. |
- ws.ws_col = width; |
- |
- return (HANDLE_EINTR(ioctl(pt_pair_[PT_MASTER_FD], TIOCSWINSZ, &ws)) != -1); |
-} |
- |
-ProcessProxy::~ProcessProxy() { |
- // In case watcher did not started, we may get deleted without calling Close. |
- // In that case we have to clean up created pipes. If watcher had been |
- // started, there will be a callback with our reference owned by |
- // process_output_watcher until Close is called, so we know Close has been |
- // called by now (and pipes have been cleaned). |
- if (!watcher_started_) |
- CloseAllFdPairs(); |
-} |
- |
-bool ProcessProxy::CreatePseudoTerminalPair(int *pt_pair) { |
- ClearFdPair(pt_pair); |
- |
- // Open Master. |
- pt_pair[PT_MASTER_FD] = HANDLE_EINTR(posix_openpt(O_RDWR | O_NOCTTY)); |
- if (pt_pair[PT_MASTER_FD] == -1) |
- return false; |
- |
- if (grantpt(pt_pair_[PT_MASTER_FD]) != 0 || |
- unlockpt(pt_pair_[PT_MASTER_FD]) != 0) { |
- CloseFd(&pt_pair[PT_MASTER_FD]); |
- return false; |
- } |
- char* slave_name = NULL; |
- // Per man page, slave_name must not be freed. |
- slave_name = ptsname(pt_pair_[PT_MASTER_FD]); |
- if (slave_name) |
- pt_pair_[PT_SLAVE_FD] = HANDLE_EINTR(open(slave_name, O_RDWR | O_NOCTTY)); |
- |
- if (pt_pair_[PT_SLAVE_FD] == -1) { |
- CloseFdPair(pt_pair); |
- return false; |
- } |
- |
- return true; |
-} |
- |
-bool ProcessProxy::LaunchProcess(const std::string& command, int slave_fd, |
- pid_t* pid) { |
- // Redirect crosh process' output and input so we can read it. |
- base::FileHandleMappingVector fds_mapping; |
- fds_mapping.push_back(std::make_pair(slave_fd, STDIN_FILENO)); |
- fds_mapping.push_back(std::make_pair(slave_fd, STDOUT_FILENO)); |
- fds_mapping.push_back(std::make_pair(slave_fd, STDERR_FILENO)); |
- base::LaunchOptions options; |
- options.fds_to_remap = &fds_mapping; |
- options.ctrl_terminal_fd = slave_fd; |
- |
- base::EnvironmentVector environ; |
- environ.push_back(std::make_pair("TERM", "xterm")); |
- options.environ = &environ; |
- |
- // Launch the process. |
- return base::LaunchProcess(CommandLine(base::FilePath(command)), options, |
- pid); |
-} |
- |
-void ProcessProxy::CloseAllFdPairs() { |
- CloseFdPair(pt_pair_); |
- CloseFdPair(shutdown_pipe_); |
-} |
- |
-void ProcessProxy::CloseFdPair(int* pipe) { |
- CloseFd(&(pipe[PIPE_END_READ])); |
- CloseFd(&(pipe[PIPE_END_WRITE])); |
-} |
- |
-void ProcessProxy::CloseFd(int* fd) { |
- if (*fd != kInvalidFd) { |
- if (HANDLE_EINTR(close(*fd)) != 0) |
- DPLOG(WARNING) << "close fd failed."; |
- } |
- *fd = kInvalidFd; |
-} |
- |
-void ProcessProxy::ClearAllFdPairs() { |
- ClearFdPair(pt_pair_); |
- ClearFdPair(shutdown_pipe_); |
-} |
- |
-void ProcessProxy::ClearFdPair(int* pipe) { |
- pipe[PIPE_END_READ] = kInvalidFd; |
- pipe[PIPE_END_WRITE] = kInvalidFd; |
-} |