Chromium Code Reviews| 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 |