Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(518)

Side by Side Diff: chrome/browser/extensions/api/messaging/native_message_process_host.cc

Issue 24409004: Disconnect native messaging port on read pipe EOF. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698