| OLD | NEW |
| 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 "chromeos/process_proxy/process_proxy_registry.h" | 5 #include "chromeos/process_proxy/process_proxy_registry.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/message_loop/message_loop.h" | 8 #include "base/message_loop/message_loop.h" |
| 9 | 9 |
| 10 namespace chromeos { | 10 namespace chromeos { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 43 | 43 |
| 44 ProcessProxyRegistry::ProcessProxyInfo::~ProcessProxyInfo() { | 44 ProcessProxyRegistry::ProcessProxyInfo::~ProcessProxyInfo() { |
| 45 } | 45 } |
| 46 | 46 |
| 47 ProcessProxyRegistry::ProcessProxyRegistry() { | 47 ProcessProxyRegistry::ProcessProxyRegistry() { |
| 48 } | 48 } |
| 49 | 49 |
| 50 ProcessProxyRegistry::~ProcessProxyRegistry() { | 50 ProcessProxyRegistry::~ProcessProxyRegistry() { |
| 51 // TODO(tbarzic): Fix issue with ProcessProxyRegistry being destroyed | 51 // TODO(tbarzic): Fix issue with ProcessProxyRegistry being destroyed |
| 52 // on a different thread (it's a LazyInstance). | 52 // on a different thread (it's a LazyInstance). |
| 53 DetachFromThread(); | 53 // DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 54 | 54 |
| 55 ShutDown(); | 55 ShutDown(); |
| 56 } | 56 } |
| 57 | 57 |
| 58 void ProcessProxyRegistry::ShutDown() { | 58 void ProcessProxyRegistry::ShutDown() { |
| 59 // Close all proxies we own. | 59 // Close all proxies we own. |
| 60 while (!proxy_map_.empty()) | 60 while (!proxy_map_.empty()) |
| 61 CloseProcess(proxy_map_.begin()->first); | 61 CloseProcess(proxy_map_.begin()->first); |
| 62 | 62 |
| 63 if (watcher_thread_) { | 63 if (watcher_thread_) { |
| 64 watcher_thread_->Stop(); | 64 watcher_thread_->Stop(); |
| 65 watcher_thread_.reset(); | 65 watcher_thread_.reset(); |
| 66 } | 66 } |
| 67 } | 67 } |
| 68 | 68 |
| 69 // static | 69 // static |
| 70 ProcessProxyRegistry* ProcessProxyRegistry::Get() { | 70 ProcessProxyRegistry* ProcessProxyRegistry::Get() { |
| 71 return g_process_proxy_registry.Pointer(); | 71 return g_process_proxy_registry.Pointer(); |
| 72 } | 72 } |
| 73 | 73 |
| 74 int ProcessProxyRegistry::OpenProcess(const std::string& command, | 74 int ProcessProxyRegistry::OpenProcess(const std::string& command, |
| 75 const OutputCallback& output_callback) { | 75 const OutputCallback& output_callback) { |
| 76 DCHECK(CalledOnValidThread()); | 76 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 77 | 77 |
| 78 if (!EnsureWatcherThreadStarted()) | 78 if (!EnsureWatcherThreadStarted()) |
| 79 return -1; | 79 return -1; |
| 80 | 80 |
| 81 // Create and open new proxy. | 81 // Create and open new proxy. |
| 82 scoped_refptr<ProcessProxy> proxy(new ProcessProxy()); | 82 scoped_refptr<ProcessProxy> proxy(new ProcessProxy()); |
| 83 // TODO(tbarzic): Use a random int as an id here instead of process pid. | 83 // TODO(tbarzic): Use a random int as an id here instead of process pid. |
| 84 int terminal_id = proxy->Open(command); | 84 int terminal_id = proxy->Open(command); |
| 85 if (terminal_id < 0) | 85 if (terminal_id < 0) |
| 86 return -1; | 86 return -1; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 97 } | 97 } |
| 98 | 98 |
| 99 ProcessProxyInfo& info = proxy_map_[terminal_id]; | 99 ProcessProxyInfo& info = proxy_map_[terminal_id]; |
| 100 info.proxy.swap(proxy); | 100 info.proxy.swap(proxy); |
| 101 info.callback = output_callback; | 101 info.callback = output_callback; |
| 102 | 102 |
| 103 return terminal_id; | 103 return terminal_id; |
| 104 } | 104 } |
| 105 | 105 |
| 106 bool ProcessProxyRegistry::SendInput(int id, const std::string& data) { | 106 bool ProcessProxyRegistry::SendInput(int id, const std::string& data) { |
| 107 DCHECK(CalledOnValidThread()); | 107 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 108 | 108 |
| 109 std::map<int, ProcessProxyInfo>::iterator it = proxy_map_.find(id); | 109 std::map<int, ProcessProxyInfo>::iterator it = proxy_map_.find(id); |
| 110 if (it == proxy_map_.end()) | 110 if (it == proxy_map_.end()) |
| 111 return false; | 111 return false; |
| 112 return it->second.proxy->Write(data); | 112 return it->second.proxy->Write(data); |
| 113 } | 113 } |
| 114 | 114 |
| 115 bool ProcessProxyRegistry::CloseProcess(int id) { | 115 bool ProcessProxyRegistry::CloseProcess(int id) { |
| 116 DCHECK(CalledOnValidThread()); | 116 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 117 | 117 |
| 118 std::map<int, ProcessProxyInfo>::iterator it = proxy_map_.find(id); | 118 std::map<int, ProcessProxyInfo>::iterator it = proxy_map_.find(id); |
| 119 if (it == proxy_map_.end()) | 119 if (it == proxy_map_.end()) |
| 120 return false; | 120 return false; |
| 121 | 121 |
| 122 it->second.proxy->Close(); | 122 it->second.proxy->Close(); |
| 123 proxy_map_.erase(it); | 123 proxy_map_.erase(it); |
| 124 return true; | 124 return true; |
| 125 } | 125 } |
| 126 | 126 |
| 127 bool ProcessProxyRegistry::OnTerminalResize(int id, int width, int height) { | 127 bool ProcessProxyRegistry::OnTerminalResize(int id, int width, int height) { |
| 128 DCHECK(CalledOnValidThread()); | 128 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 129 | 129 |
| 130 std::map<int, ProcessProxyInfo>::iterator it = proxy_map_.find(id); | 130 std::map<int, ProcessProxyInfo>::iterator it = proxy_map_.find(id); |
| 131 if (it == proxy_map_.end()) | 131 if (it == proxy_map_.end()) |
| 132 return false; | 132 return false; |
| 133 | 133 |
| 134 return it->second.proxy->OnTerminalResize(width, height); | 134 return it->second.proxy->OnTerminalResize(width, height); |
| 135 } | 135 } |
| 136 | 136 |
| 137 void ProcessProxyRegistry::AckOutput(int id) { | 137 void ProcessProxyRegistry::AckOutput(int id) { |
| 138 DCHECK(CalledOnValidThread()); | 138 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 139 | 139 |
| 140 std::map<int, ProcessProxyInfo>::iterator it = proxy_map_.find(id); | 140 std::map<int, ProcessProxyInfo>::iterator it = proxy_map_.find(id); |
| 141 if (it == proxy_map_.end()) | 141 if (it == proxy_map_.end()) |
| 142 return; | 142 return; |
| 143 | 143 |
| 144 it->second.proxy->AckOutput(); | 144 it->second.proxy->AckOutput(); |
| 145 } | 145 } |
| 146 | 146 |
| 147 void ProcessProxyRegistry::OnProcessOutput(int id, | 147 void ProcessProxyRegistry::OnProcessOutput(int id, |
| 148 ProcessOutputType type, | 148 ProcessOutputType type, |
| 149 const std::string& data) { | 149 const std::string& data) { |
| 150 DCHECK(CalledOnValidThread()); | 150 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); |
| 151 | 151 |
| 152 const char* type_str = ProcessOutputTypeToString(type); | 152 const char* type_str = ProcessOutputTypeToString(type); |
| 153 DCHECK(type_str); | 153 DCHECK(type_str); |
| 154 | 154 |
| 155 std::map<int, ProcessProxyInfo>::iterator it = proxy_map_.find(id); | 155 std::map<int, ProcessProxyInfo>::iterator it = proxy_map_.find(id); |
| 156 if (it == proxy_map_.end()) | 156 if (it == proxy_map_.end()) |
| 157 return; | 157 return; |
| 158 it->second.callback.Run(id, std::string(type_str), data); | 158 it->second.callback.Run(id, std::string(type_str), data); |
| 159 | 159 |
| 160 // Contact with the slave end of the terminal has been lost. We have to close | 160 // Contact with the slave end of the terminal has been lost. We have to close |
| 161 // the process. | 161 // the process. |
| 162 if (type == PROCESS_OUTPUT_TYPE_EXIT) | 162 if (type == PROCESS_OUTPUT_TYPE_EXIT) |
| 163 CloseProcess(id); | 163 CloseProcess(id); |
| 164 } | 164 } |
| 165 | 165 |
| 166 bool ProcessProxyRegistry::EnsureWatcherThreadStarted() { | 166 bool ProcessProxyRegistry::EnsureWatcherThreadStarted() { |
| 167 if (watcher_thread_.get()) | 167 if (watcher_thread_.get()) |
| 168 return true; | 168 return true; |
| 169 | 169 |
| 170 // TODO(tbarzic): Change process output watcher to watch for fd readability on | 170 // TODO(tbarzic): Change process output watcher to watch for fd readability on |
| 171 // FILE thread, and move output reading to worker thread instead of | 171 // FILE thread, and move output reading to worker thread instead of |
| 172 // spinning a new thread. | 172 // spinning a new thread. |
| 173 watcher_thread_.reset(new base::Thread(kWatcherThreadName)); | 173 watcher_thread_.reset(new base::Thread(kWatcherThreadName)); |
| 174 return watcher_thread_->StartWithOptions( | 174 return watcher_thread_->StartWithOptions( |
| 175 base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); | 175 base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); |
| 176 } | 176 } |
| 177 | 177 |
| 178 } // namespace chromeos | 178 } // namespace chromeos |
| OLD | NEW |