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" | 10 #include "base/platform_file.h" |
(...skipping 19 matching lines...) Expand all Loading... | |
30 | 30 |
31 // Message header contains 4-byte integer size of the message. | 31 // Message header contains 4-byte integer size of the message. |
32 const size_t kMessageHeaderSize = 4; | 32 const size_t kMessageHeaderSize = 4; |
33 | 33 |
34 // Size of the buffer to be allocated for each read. | 34 // Size of the buffer to be allocated for each read. |
35 const size_t kReadBufferSize = 4096; | 35 const size_t kReadBufferSize = 4096; |
36 | 36 |
37 const char kFailedToStartError[] = "Failed to start native messaging host."; | 37 const char kFailedToStartError[] = "Failed to start native messaging host."; |
38 const char kInvalidNameError[] = | 38 const char kInvalidNameError[] = |
39 "Invalid native messaging host name specified."; | 39 "Invalid native messaging host name specified."; |
40 const char kNativeHostExited[] = "Native host has exited."; | |
40 const char kNotFoundError[] = "Specified native messaging host not found."; | 41 const char kNotFoundError[] = "Specified native messaging host not found."; |
41 const char kForbiddenError[] = | 42 const char kForbiddenError[] = |
42 "Access to the specified native messaging host is forbidden."; | 43 "Access to the specified native messaging host is forbidden."; |
43 const char kHostInputOuputError[] = | 44 const char kHostInputOuputError[] = |
44 "Error when communicating with the native messaging host."; | 45 "Error when communicating with the native messaging host."; |
45 | 46 |
46 } // namespace | 47 } // namespace |
47 | 48 |
48 namespace extensions { | 49 namespace extensions { |
49 | 50 |
50 NativeMessageProcessHost::NativeMessageProcessHost( | 51 NativeMessageProcessHost::NativeMessageProcessHost( |
51 base::WeakPtr<Client> weak_client_ui, | 52 base::WeakPtr<Client> weak_client_ui, |
52 const std::string& source_extension_id, | 53 const std::string& source_extension_id, |
53 const std::string& native_host_name, | 54 const std::string& native_host_name, |
54 int destination_port, | 55 int destination_port, |
55 scoped_ptr<NativeProcessLauncher> launcher) | 56 scoped_ptr<NativeProcessLauncher> launcher) |
56 : weak_client_ui_(weak_client_ui), | 57 : weak_client_ui_(weak_client_ui), |
57 source_extension_id_(source_extension_id), | 58 source_extension_id_(source_extension_id), |
58 native_host_name_(native_host_name), | 59 native_host_name_(native_host_name), |
59 destination_port_(destination_port), | 60 destination_port_(destination_port), |
60 launcher_(launcher.Pass()), | 61 launcher_(launcher.Pass()), |
61 closed_(false), | 62 closed_(false), |
63 read_file_(base::kInvalidPlatformFileValue), | |
62 read_pending_(false), | 64 read_pending_(false), |
63 read_eof_(false), | |
64 write_pending_(false) { | 65 write_pending_(false) { |
65 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 66 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
66 | 67 |
67 // It's safe to use base::Unretained() here because NativeMessagePort always | 68 // It's safe to use base::Unretained() here because NativeMessagePort always |
68 // deletes us on the IO thread. | 69 // deletes us on the IO thread. |
69 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, | 70 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, |
70 base::Bind(&NativeMessageProcessHost::LaunchHostProcess, | 71 base::Bind(&NativeMessageProcessHost::LaunchHostProcess, |
71 base::Unretained(this))); | 72 base::Unretained(this))); |
72 } | 73 } |
73 | 74 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
189 void NativeMessageProcessHost::OnFileCanWriteWithoutBlocking(int fd) { | 190 void NativeMessageProcessHost::OnFileCanWriteWithoutBlocking(int fd) { |
190 NOTREACHED(); | 191 NOTREACHED(); |
191 } | 192 } |
192 #endif // !defined(OS_POSIX) | 193 #endif // !defined(OS_POSIX) |
193 | 194 |
194 void NativeMessageProcessHost::ReadNowForTesting() { | 195 void NativeMessageProcessHost::ReadNowForTesting() { |
195 DoRead(); | 196 DoRead(); |
196 } | 197 } |
197 | 198 |
198 void NativeMessageProcessHost::WaitRead() { | 199 void NativeMessageProcessHost::WaitRead() { |
199 if (closed_ || read_eof_) | 200 if (closed_) |
200 return; | 201 return; |
201 | 202 |
202 DCHECK(!read_pending_); | 203 DCHECK(!read_pending_); |
203 | 204 |
204 // On POSIX FileStream::Read() uses blocking thread pool, so it's better to | 205 // On POSIX FileStream::Read() uses blocking thread pool, so it's better to |
205 // wait for the file to become readable before calling DoRead(). Otherwise it | 206 // wait for the file to become readable before calling DoRead(). Otherwise it |
206 // would always be consuming one thread in the thread pool. On Windows | 207 // would always be consuming one thread in the thread pool. On Windows |
207 // FileStream uses overlapped IO, so that optimization isn't necessary there. | 208 // FileStream uses overlapped IO, so that optimization isn't necessary there. |
208 #if defined(OS_POSIX) | 209 #if defined(OS_POSIX) |
209 base::MessageLoopForIO::current()->WatchFileDescriptor( | 210 base::MessageLoopForIO::current()->WatchFileDescriptor( |
210 read_file_, false /* persistent */, base::MessageLoopForIO::WATCH_READ, | 211 read_file_, false /* persistent */, base::MessageLoopForIO::WATCH_READ, |
211 &read_watcher_, this); | 212 &read_watcher_, this); |
212 #else // defined(OS_POSIX) | 213 #else // defined(OS_POSIX) |
213 DoRead(); | 214 DoRead(); |
214 #endif // defined(!OS_POSIX) | 215 #endif // defined(!OS_POSIX) |
215 } | 216 } |
216 | 217 |
217 void NativeMessageProcessHost::DoRead() { | 218 void NativeMessageProcessHost::DoRead() { |
218 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 219 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
219 | 220 |
220 while (!closed_ && !read_eof_ && !read_pending_) { | 221 while (!closed_ && !read_pending_) { |
221 read_buffer_ = new net::IOBuffer(kReadBufferSize); | 222 read_buffer_ = new net::IOBuffer(kReadBufferSize); |
222 int result = read_stream_->Read( | 223 int result = read_stream_->Read( |
223 read_buffer_.get(), | 224 read_buffer_.get(), |
224 kReadBufferSize, | 225 kReadBufferSize, |
225 base::Bind(&NativeMessageProcessHost::OnRead, base::Unretained(this))); | 226 base::Bind(&NativeMessageProcessHost::OnRead, base::Unretained(this))); |
226 HandleReadResult(result); | 227 HandleReadResult(result); |
227 } | 228 } |
228 } | 229 } |
229 | 230 |
230 void NativeMessageProcessHost::OnRead(int result) { | 231 void NativeMessageProcessHost::OnRead(int result) { |
231 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 232 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
232 DCHECK(read_pending_); | 233 DCHECK(read_pending_); |
233 read_pending_ = false; | 234 read_pending_ = false; |
234 | 235 |
235 HandleReadResult(result); | 236 HandleReadResult(result); |
236 WaitRead(); | 237 WaitRead(); |
237 } | 238 } |
238 | 239 |
239 void NativeMessageProcessHost::HandleReadResult(int result) { | 240 void NativeMessageProcessHost::HandleReadResult(int result) { |
240 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 241 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
241 | 242 |
242 if (closed_) | 243 if (closed_) |
243 return; | 244 return; |
244 | 245 |
245 if (result > 0) { | 246 if (result > 0) { |
246 ProcessIncomingData(read_buffer_->data(), result); | 247 ProcessIncomingData(read_buffer_->data(), result); |
247 } else if (result == 0) { | |
248 read_eof_ = true; | |
249 } else if (result == net::ERR_IO_PENDING) { | 248 } else if (result == net::ERR_IO_PENDING) { |
250 read_pending_ = true; | 249 read_pending_ = true; |
250 } else if (result == 0 || result == net::ERR_CONNECTION_RESET) { | |
wtc
2013/09/25 23:03:12
On Unix, EPIPE is an error code for write/send. He
akalin
2013/09/25 23:09:32
I'm guessing that we're getting ERROR_BROKEN_PIPE
Sergey Ulanov
2013/09/25 23:30:51
On windows we always get ERROR_BROKEN_PIPE when re
wtc
2013/09/26 17:14:05
Thanks. It would be nice to add a comment about th
| |
251 Close(kNativeHostExited); | |
251 } else { | 252 } else { |
252 LOG(ERROR) << "Error when reading from Native Messaging host: " << result; | 253 LOG(ERROR) << "Error when reading from Native Messaging host: " << result; |
253 Close(kHostInputOuputError); | 254 Close(kHostInputOuputError); |
254 } | 255 } |
255 } | 256 } |
256 | 257 |
257 void NativeMessageProcessHost::ProcessIncomingData( | 258 void NativeMessageProcessHost::ProcessIncomingData( |
258 const char* data, int data_size) { | 259 const char* data, int data_size) { |
259 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 260 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); |
260 | 261 |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
341 closed_ = true; | 342 closed_ = true; |
342 read_stream_.reset(); | 343 read_stream_.reset(); |
343 write_stream_.reset(); | 344 write_stream_.reset(); |
344 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, | 345 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
345 base::Bind(&Client::CloseChannel, weak_client_ui_, | 346 base::Bind(&Client::CloseChannel, weak_client_ui_, |
346 destination_port_, error_message)); | 347 destination_port_, error_message)); |
347 } | 348 } |
348 } | 349 } |
349 | 350 |
350 } // namespace extensions | 351 } // namespace extensions |
OLD | NEW |