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 "chrome/browser/extensions/api/messaging/native_message_process_host.h" | 5 #include "chrome/browser/extensions/api/messaging/native_message_process_host.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/files/file_path.h" | 8 #include "base/files/file_path.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/platform_file.h" | |
11 #include "base/prefs/pref_service.h" | 10 #include "base/prefs/pref_service.h" |
12 #include "base/process/kill.h" | 11 #include "base/process/kill.h" |
13 #include "base/threading/sequenced_worker_pool.h" | 12 #include "base/threading/sequenced_worker_pool.h" |
14 #include "base/values.h" | 13 #include "base/values.h" |
15 #include "chrome/browser/extensions/api/messaging/native_messaging_host_manifest
.h" | 14 #include "chrome/browser/extensions/api/messaging/native_messaging_host_manifest
.h" |
16 #include "chrome/browser/extensions/api/messaging/native_process_launcher.h" | 15 #include "chrome/browser/extensions/api/messaging/native_process_launcher.h" |
17 #include "chrome/common/chrome_version_info.h" | 16 #include "chrome/common/chrome_version_info.h" |
18 #include "content/public/browser/browser_thread.h" | 17 #include "content/public/browser/browser_thread.h" |
19 #include "extensions/browser/pref_names.h" | 18 #include "extensions/browser/pref_names.h" |
20 #include "extensions/common/constants.h" | 19 #include "extensions/common/constants.h" |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
95 base::WeakPtr<Client> weak_client_ui, | 94 base::WeakPtr<Client> weak_client_ui, |
96 const std::string& source_extension_id, | 95 const std::string& source_extension_id, |
97 const std::string& native_host_name, | 96 const std::string& native_host_name, |
98 int destination_port, | 97 int destination_port, |
99 scoped_ptr<NativeProcessLauncher> launcher) | 98 scoped_ptr<NativeProcessLauncher> launcher) |
100 : weak_client_ui_(weak_client_ui), | 99 : weak_client_ui_(weak_client_ui), |
101 source_extension_id_(source_extension_id), | 100 source_extension_id_(source_extension_id), |
102 native_host_name_(native_host_name), | 101 native_host_name_(native_host_name), |
103 destination_port_(destination_port), | 102 destination_port_(destination_port), |
104 launcher_(launcher.Pass()), | 103 launcher_(launcher.Pass()), |
| 104 process_handle_(base::kNullProcessHandle), |
105 closed_(false), | 105 closed_(false), |
106 process_handle_(base::kNullProcessHandle), | |
107 #if defined(OS_POSIX) | |
108 read_file_(base::kInvalidPlatformFileValue), | |
109 #endif | |
110 read_pending_(false), | 106 read_pending_(false), |
111 write_pending_(false) { | 107 write_pending_(false), |
| 108 direct_read_for_test_(false) { |
112 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 109 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
113 | 110 |
114 // It's safe to use base::Unretained() here because NativeMessagePort always | 111 // It's safe to use base::Unretained() here because NativeMessagePort always |
115 // deletes us on the IO thread. | 112 // deletes us on the IO thread. |
116 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, | 113 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, |
117 base::Bind(&NativeMessageProcessHost::LaunchHostProcess, | 114 base::Bind(&NativeMessageProcessHost::LaunchHostProcess, |
118 base::Unretained(this))); | 115 base::Unretained(this))); |
119 } | 116 } |
120 | 117 |
121 NativeMessageProcessHost::~NativeMessageProcessHost() { | 118 NativeMessageProcessHost::~NativeMessageProcessHost() { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
181 Close(kForbiddenError); | 178 Close(kForbiddenError); |
182 return; | 179 return; |
183 case NativeProcessLauncher::RESULT_FAILED_TO_START: | 180 case NativeProcessLauncher::RESULT_FAILED_TO_START: |
184 Close(kFailedToStartError); | 181 Close(kFailedToStartError); |
185 return; | 182 return; |
186 case NativeProcessLauncher::RESULT_SUCCESS: | 183 case NativeProcessLauncher::RESULT_SUCCESS: |
187 break; | 184 break; |
188 } | 185 } |
189 | 186 |
190 process_handle_ = process_handle; | 187 process_handle_ = process_handle; |
191 #if defined(OS_POSIX) | |
192 // This object is not the owner of the file so it should not keep an fd. | |
193 read_file_ = read_file.GetPlatformFile(); | |
194 #endif | |
195 | 188 |
196 scoped_refptr<base::TaskRunner> task_runner( | 189 scoped_refptr<base::TaskRunner> task_runner( |
197 content::BrowserThread::GetBlockingPool()-> | 190 content::BrowserThread::GetBlockingPool()-> |
198 GetTaskRunnerWithShutdownBehavior( | 191 GetTaskRunnerWithShutdownBehavior( |
199 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); | 192 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN)); |
200 | 193 |
201 read_stream_.reset(new net::FileStream(read_file.Pass(), task_runner)); | 194 read_stream_.reset(new net::FileStream(read_file.Pass(), task_runner)); |
202 write_stream_.reset(new net::FileStream(write_file.Pass(), task_runner)); | 195 write_stream_.reset(new net::FileStream(write_file.Pass(), task_runner)); |
203 | 196 |
204 WaitRead(); | 197 WaitRead(); |
(...skipping 18 matching lines...) Expand all Loading... |
223 // Push new message to the write queue. | 216 // Push new message to the write queue. |
224 write_queue_.push(buffer); | 217 write_queue_.push(buffer); |
225 | 218 |
226 // Send() may be called before the host process is started. In that case the | 219 // Send() may be called before the host process is started. In that case the |
227 // message will be written when OnHostProcessLaunched() is called. If it's | 220 // message will be written when OnHostProcessLaunched() is called. If it's |
228 // already started then write the message now. | 221 // already started then write the message now. |
229 if (write_stream_) | 222 if (write_stream_) |
230 DoWrite(); | 223 DoWrite(); |
231 } | 224 } |
232 | 225 |
233 #if defined(OS_POSIX) | 226 void NativeMessageProcessHost::DontWaitToReadForTesting() { |
234 void NativeMessageProcessHost::OnFileCanReadWithoutBlocking(int fd) { | 227 direct_read_for_test_ = true; |
235 DCHECK_EQ(fd, read_file_); | |
236 DoRead(); | |
237 } | |
238 | |
239 void NativeMessageProcessHost::OnFileCanWriteWithoutBlocking(int fd) { | |
240 NOTREACHED(); | |
241 } | |
242 #endif // !defined(OS_POSIX) | |
243 | |
244 void NativeMessageProcessHost::ReadNowForTesting() { | |
245 DoRead(); | |
246 } | 228 } |
247 | 229 |
248 void NativeMessageProcessHost::WaitRead() { | 230 void NativeMessageProcessHost::WaitRead() { |
249 if (closed_) | 231 if (closed_) |
250 return; | 232 return; |
251 | 233 |
252 DCHECK(!read_pending_); | 234 DCHECK(!read_pending_); |
253 | |
254 // On POSIX FileStream::Read() uses blocking thread pool, so it's better to | |
255 // wait for the file to become readable before calling DoRead(). Otherwise it | |
256 // would always be consuming one thread in the thread pool. On Windows | |
257 // FileStream uses overlapped IO, so that optimization isn't necessary there. | |
258 #if defined(OS_POSIX) | |
259 base::MessageLoopForIO::current()->WatchFileDescriptor( | |
260 read_file_, false /* persistent */, | |
261 base::MessageLoopForIO::WATCH_READ, &read_watcher_, this); | |
262 #else // defined(OS_POSIX) | |
263 DoRead(); | 235 DoRead(); |
264 #endif // defined(!OS_POSIX) | |
265 } | 236 } |
266 | 237 |
267 void NativeMessageProcessHost::DoRead() { | 238 void NativeMessageProcessHost::DoRead() { |
268 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 239 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
269 | 240 |
270 while (!closed_ && !read_pending_) { | 241 while (!closed_ && !read_pending_) { |
271 read_buffer_ = new net::IOBuffer(kReadBufferSize); | 242 read_buffer_ = new net::IOBuffer(kReadBufferSize); |
272 int result = read_stream_->Read( | 243 int result; |
273 read_buffer_.get(), | 244 if (direct_read_for_test_) { |
274 kReadBufferSize, | 245 result = read_stream_->Read( |
275 base::Bind(&NativeMessageProcessHost::OnRead, base::Unretained(this))); | 246 read_buffer_.get(), |
| 247 kReadBufferSize, |
| 248 base::Bind(&NativeMessageProcessHost::OnRead, |
| 249 base::Unretained(this))); |
| 250 } else { |
| 251 result = read_stream_->ReadNoBlocking( |
| 252 read_buffer_.get(), |
| 253 kReadBufferSize, |
| 254 base::Bind(&NativeMessageProcessHost::OnRead, |
| 255 base::Unretained(this))); |
| 256 } |
276 HandleReadResult(result); | 257 HandleReadResult(result); |
277 } | 258 } |
278 } | 259 } |
279 | 260 |
280 void NativeMessageProcessHost::OnRead(int result) { | 261 void NativeMessageProcessHost::OnRead(int result) { |
281 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); | 262 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
282 DCHECK(read_pending_); | 263 DCHECK(read_pending_); |
283 read_pending_ = false; | 264 read_pending_ = false; |
284 | 265 |
285 HandleReadResult(result); | 266 HandleReadResult(result); |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 content::BrowserThread::PostBlockingPoolTask( | 387 content::BrowserThread::PostBlockingPoolTask( |
407 FROM_HERE, base::Bind(&base::EnsureProcessTerminated, process_handle_)); | 388 FROM_HERE, base::Bind(&base::EnsureProcessTerminated, process_handle_)); |
408 #else | 389 #else |
409 base::EnsureProcessTerminated(process_handle_); | 390 base::EnsureProcessTerminated(process_handle_); |
410 #endif | 391 #endif |
411 process_handle_ = base::kNullProcessHandle; | 392 process_handle_ = base::kNullProcessHandle; |
412 } | 393 } |
413 } | 394 } |
414 | 395 |
415 } // namespace extensions | 396 } // namespace extensions |
OLD | NEW |