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 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 native_host_name_(native_host_name), | 102 native_host_name_(native_host_name), |
103 destination_port_(destination_port), | 103 destination_port_(destination_port), |
104 launcher_(launcher.Pass()), | 104 launcher_(launcher.Pass()), |
105 closed_(false), | 105 closed_(false), |
106 process_handle_(base::kNullProcessHandle), | 106 process_handle_(base::kNullProcessHandle), |
107 #if defined(OS_POSIX) | 107 #if defined(OS_POSIX) |
108 read_file_(base::kInvalidPlatformFileValue), | 108 read_file_(base::kInvalidPlatformFileValue), |
109 #endif | 109 #endif |
110 read_pending_(false), | 110 read_pending_(false), |
111 write_pending_(false) { | 111 write_pending_(false) { |
112 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 112 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
113 | 113 |
114 // It's safe to use base::Unretained() here because NativeMessagePort always | 114 // It's safe to use base::Unretained() here because NativeMessagePort always |
115 // deletes us on the IO thread. | 115 // deletes us on the IO thread. |
116 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, | 116 content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, |
117 base::Bind(&NativeMessageProcessHost::LaunchHostProcess, | 117 base::Bind(&NativeMessageProcessHost::LaunchHostProcess, |
118 base::Unretained(this))); | 118 base::Unretained(this))); |
119 } | 119 } |
120 | 120 |
121 NativeMessageProcessHost::~NativeMessageProcessHost() { | 121 NativeMessageProcessHost::~NativeMessageProcessHost() { |
122 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 122 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
123 Close(std::string()); | 123 Close(std::string()); |
124 } | 124 } |
125 | 125 |
126 // static | 126 // static |
127 scoped_ptr<NativeMessageProcessHost> NativeMessageProcessHost::Create( | 127 scoped_ptr<NativeMessageProcessHost> NativeMessageProcessHost::Create( |
128 gfx::NativeView native_view, | 128 gfx::NativeView native_view, |
129 base::WeakPtr<Client> weak_client_ui, | 129 base::WeakPtr<Client> weak_client_ui, |
130 const std::string& source_extension_id, | 130 const std::string& source_extension_id, |
131 const std::string& native_host_name, | 131 const std::string& native_host_name, |
132 int destination_port, | 132 int destination_port, |
133 bool allow_user_level) { | 133 bool allow_user_level) { |
134 return CreateWithLauncher(weak_client_ui, source_extension_id, | 134 return CreateWithLauncher(weak_client_ui, source_extension_id, |
135 native_host_name, destination_port, | 135 native_host_name, destination_port, |
136 NativeProcessLauncher::CreateDefault( | 136 NativeProcessLauncher::CreateDefault( |
137 allow_user_level, native_view)); | 137 allow_user_level, native_view)); |
138 } | 138 } |
139 | 139 |
140 // static | 140 // static |
141 scoped_ptr<NativeMessageProcessHost> | 141 scoped_ptr<NativeMessageProcessHost> |
142 NativeMessageProcessHost::CreateWithLauncher( | 142 NativeMessageProcessHost::CreateWithLauncher( |
143 base::WeakPtr<Client> weak_client_ui, | 143 base::WeakPtr<Client> weak_client_ui, |
144 const std::string& source_extension_id, | 144 const std::string& source_extension_id, |
145 const std::string& native_host_name, | 145 const std::string& native_host_name, |
146 int destination_port, | 146 int destination_port, |
147 scoped_ptr<NativeProcessLauncher> launcher) { | 147 scoped_ptr<NativeProcessLauncher> launcher) { |
148 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 148 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
149 | 149 |
150 scoped_ptr<NativeMessageProcessHost> process(new NativeMessageProcessHost( | 150 scoped_ptr<NativeMessageProcessHost> process(new NativeMessageProcessHost( |
151 weak_client_ui, source_extension_id, native_host_name, | 151 weak_client_ui, source_extension_id, native_host_name, |
152 destination_port, launcher.Pass())); | 152 destination_port, launcher.Pass())); |
153 | 153 |
154 return process.Pass(); | 154 return process.Pass(); |
155 } | 155 } |
156 | 156 |
157 void NativeMessageProcessHost::LaunchHostProcess() { | 157 void NativeMessageProcessHost::LaunchHostProcess() { |
158 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 158 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
159 | 159 |
160 GURL origin(std::string(kExtensionScheme) + "://" + source_extension_id_); | 160 GURL origin(std::string(kExtensionScheme) + "://" + source_extension_id_); |
161 launcher_->Launch(origin, native_host_name_, | 161 launcher_->Launch(origin, native_host_name_, |
162 base::Bind(&NativeMessageProcessHost::OnHostProcessLaunched, | 162 base::Bind(&NativeMessageProcessHost::OnHostProcessLaunched, |
163 base::Unretained(this))); | 163 base::Unretained(this))); |
164 } | 164 } |
165 | 165 |
166 void NativeMessageProcessHost::OnHostProcessLaunched( | 166 void NativeMessageProcessHost::OnHostProcessLaunched( |
167 NativeProcessLauncher::LaunchResult result, | 167 NativeProcessLauncher::LaunchResult result, |
168 base::ProcessHandle process_handle, | 168 base::ProcessHandle process_handle, |
169 base::File read_file, | 169 base::File read_file, |
170 base::File write_file) { | 170 base::File write_file) { |
171 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 171 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
172 | 172 |
173 switch (result) { | 173 switch (result) { |
174 case NativeProcessLauncher::RESULT_INVALID_NAME: | 174 case NativeProcessLauncher::RESULT_INVALID_NAME: |
175 Close(kInvalidNameError); | 175 Close(kInvalidNameError); |
176 return; | 176 return; |
177 case NativeProcessLauncher::RESULT_NOT_FOUND: | 177 case NativeProcessLauncher::RESULT_NOT_FOUND: |
178 Close(kNotFoundError); | 178 Close(kNotFoundError); |
179 return; | 179 return; |
180 case NativeProcessLauncher::RESULT_FORBIDDEN: | 180 case NativeProcessLauncher::RESULT_FORBIDDEN: |
181 Close(kForbiddenError); | 181 Close(kForbiddenError); |
(...skipping 23 matching lines...) Expand all Loading... |
205 write_stream_.reset(new net::FileStream( | 205 write_stream_.reset(new net::FileStream( |
206 write_file.TakePlatformFile(), | 206 write_file.TakePlatformFile(), |
207 base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC, NULL, | 207 base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_ASYNC, NULL, |
208 task_runner)); | 208 task_runner)); |
209 | 209 |
210 WaitRead(); | 210 WaitRead(); |
211 DoWrite(); | 211 DoWrite(); |
212 } | 212 } |
213 | 213 |
214 void NativeMessageProcessHost::Send(const std::string& json) { | 214 void NativeMessageProcessHost::Send(const std::string& json) { |
215 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 215 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
216 | 216 |
217 if (closed_) | 217 if (closed_) |
218 return; | 218 return; |
219 | 219 |
220 // Allocate new buffer for the message. | 220 // Allocate new buffer for the message. |
221 scoped_refptr<net::IOBufferWithSize> buffer = | 221 scoped_refptr<net::IOBufferWithSize> buffer = |
222 new net::IOBufferWithSize(json.size() + kMessageHeaderSize); | 222 new net::IOBufferWithSize(json.size() + kMessageHeaderSize); |
223 | 223 |
224 // Copy size and content of the message to the buffer. | 224 // Copy size and content of the message to the buffer. |
225 COMPILE_ASSERT(sizeof(uint32) == kMessageHeaderSize, incorrect_header_size); | 225 COMPILE_ASSERT(sizeof(uint32) == kMessageHeaderSize, incorrect_header_size); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 #if defined(OS_POSIX) | 264 #if defined(OS_POSIX) |
265 base::MessageLoopForIO::current()->WatchFileDescriptor( | 265 base::MessageLoopForIO::current()->WatchFileDescriptor( |
266 read_file_, false /* persistent */, | 266 read_file_, false /* persistent */, |
267 base::MessageLoopForIO::WATCH_READ, &read_watcher_, this); | 267 base::MessageLoopForIO::WATCH_READ, &read_watcher_, this); |
268 #else // defined(OS_POSIX) | 268 #else // defined(OS_POSIX) |
269 DoRead(); | 269 DoRead(); |
270 #endif // defined(!OS_POSIX) | 270 #endif // defined(!OS_POSIX) |
271 } | 271 } |
272 | 272 |
273 void NativeMessageProcessHost::DoRead() { | 273 void NativeMessageProcessHost::DoRead() { |
274 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 274 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
275 | 275 |
276 while (!closed_ && !read_pending_) { | 276 while (!closed_ && !read_pending_) { |
277 read_buffer_ = new net::IOBuffer(kReadBufferSize); | 277 read_buffer_ = new net::IOBuffer(kReadBufferSize); |
278 int result = read_stream_->Read( | 278 int result = read_stream_->Read( |
279 read_buffer_.get(), | 279 read_buffer_.get(), |
280 kReadBufferSize, | 280 kReadBufferSize, |
281 base::Bind(&NativeMessageProcessHost::OnRead, base::Unretained(this))); | 281 base::Bind(&NativeMessageProcessHost::OnRead, base::Unretained(this))); |
282 HandleReadResult(result); | 282 HandleReadResult(result); |
283 } | 283 } |
284 } | 284 } |
285 | 285 |
286 void NativeMessageProcessHost::OnRead(int result) { | 286 void NativeMessageProcessHost::OnRead(int result) { |
287 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 287 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
288 DCHECK(read_pending_); | 288 DCHECK(read_pending_); |
289 read_pending_ = false; | 289 read_pending_ = false; |
290 | 290 |
291 HandleReadResult(result); | 291 HandleReadResult(result); |
292 WaitRead(); | 292 WaitRead(); |
293 } | 293 } |
294 | 294 |
295 void NativeMessageProcessHost::HandleReadResult(int result) { | 295 void NativeMessageProcessHost::HandleReadResult(int result) { |
296 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 296 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
297 | 297 |
298 if (closed_) | 298 if (closed_) |
299 return; | 299 return; |
300 | 300 |
301 if (result > 0) { | 301 if (result > 0) { |
302 ProcessIncomingData(read_buffer_->data(), result); | 302 ProcessIncomingData(read_buffer_->data(), result); |
303 } else if (result == net::ERR_IO_PENDING) { | 303 } else if (result == net::ERR_IO_PENDING) { |
304 read_pending_ = true; | 304 read_pending_ = true; |
305 } else if (result == 0 || result == net::ERR_CONNECTION_RESET) { | 305 } else if (result == 0 || result == net::ERR_CONNECTION_RESET) { |
306 // On Windows we get net::ERR_CONNECTION_RESET for a broken pipe, while on | 306 // On Windows we get net::ERR_CONNECTION_RESET for a broken pipe, while on |
307 // Posix read() returns 0 in that case. | 307 // Posix read() returns 0 in that case. |
308 Close(kNativeHostExited); | 308 Close(kNativeHostExited); |
309 } else { | 309 } else { |
310 LOG(ERROR) << "Error when reading from Native Messaging host: " << result; | 310 LOG(ERROR) << "Error when reading from Native Messaging host: " << result; |
311 Close(kHostInputOuputError); | 311 Close(kHostInputOuputError); |
312 } | 312 } |
313 } | 313 } |
314 | 314 |
315 void NativeMessageProcessHost::ProcessIncomingData( | 315 void NativeMessageProcessHost::ProcessIncomingData( |
316 const char* data, int data_size) { | 316 const char* data, int data_size) { |
317 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 317 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
318 | 318 |
319 incoming_data_.append(data, data_size); | 319 incoming_data_.append(data, data_size); |
320 | 320 |
321 while (true) { | 321 while (true) { |
322 if (incoming_data_.size() < kMessageHeaderSize) | 322 if (incoming_data_.size() < kMessageHeaderSize) |
323 return; | 323 return; |
324 | 324 |
325 size_t message_size = | 325 size_t message_size = |
326 *reinterpret_cast<const uint32*>(incoming_data_.data()); | 326 *reinterpret_cast<const uint32*>(incoming_data_.data()); |
327 | 327 |
(...skipping 10 matching lines...) Expand all Loading... |
338 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, | 338 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
339 base::Bind(&Client::PostMessageFromNativeProcess, weak_client_ui_, | 339 base::Bind(&Client::PostMessageFromNativeProcess, weak_client_ui_, |
340 destination_port_, | 340 destination_port_, |
341 incoming_data_.substr(kMessageHeaderSize, message_size))); | 341 incoming_data_.substr(kMessageHeaderSize, message_size))); |
342 | 342 |
343 incoming_data_.erase(0, kMessageHeaderSize + message_size); | 343 incoming_data_.erase(0, kMessageHeaderSize + message_size); |
344 } | 344 } |
345 } | 345 } |
346 | 346 |
347 void NativeMessageProcessHost::DoWrite() { | 347 void NativeMessageProcessHost::DoWrite() { |
348 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 348 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
349 | 349 |
350 while (!write_pending_ && !closed_) { | 350 while (!write_pending_ && !closed_) { |
351 if (!current_write_buffer_.get() || | 351 if (!current_write_buffer_.get() || |
352 !current_write_buffer_->BytesRemaining()) { | 352 !current_write_buffer_->BytesRemaining()) { |
353 if (write_queue_.empty()) | 353 if (write_queue_.empty()) |
354 return; | 354 return; |
355 current_write_buffer_ = new net::DrainableIOBuffer( | 355 current_write_buffer_ = new net::DrainableIOBuffer( |
356 write_queue_.front().get(), write_queue_.front()->size()); | 356 write_queue_.front().get(), write_queue_.front()->size()); |
357 write_queue_.pop(); | 357 write_queue_.pop(); |
358 } | 358 } |
359 | 359 |
360 int result = | 360 int result = |
361 write_stream_->Write(current_write_buffer_.get(), | 361 write_stream_->Write(current_write_buffer_.get(), |
362 current_write_buffer_->BytesRemaining(), | 362 current_write_buffer_->BytesRemaining(), |
363 base::Bind(&NativeMessageProcessHost::OnWritten, | 363 base::Bind(&NativeMessageProcessHost::OnWritten, |
364 base::Unretained(this))); | 364 base::Unretained(this))); |
365 HandleWriteResult(result); | 365 HandleWriteResult(result); |
366 } | 366 } |
367 } | 367 } |
368 | 368 |
369 void NativeMessageProcessHost::HandleWriteResult(int result) { | 369 void NativeMessageProcessHost::HandleWriteResult(int result) { |
370 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 370 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
371 | 371 |
372 if (result <= 0) { | 372 if (result <= 0) { |
373 if (result == net::ERR_IO_PENDING) { | 373 if (result == net::ERR_IO_PENDING) { |
374 write_pending_ = true; | 374 write_pending_ = true; |
375 } else { | 375 } else { |
376 LOG(ERROR) << "Error when writing to Native Messaging host: " << result; | 376 LOG(ERROR) << "Error when writing to Native Messaging host: " << result; |
377 Close(kHostInputOuputError); | 377 Close(kHostInputOuputError); |
378 } | 378 } |
379 return; | 379 return; |
380 } | 380 } |
381 | 381 |
382 current_write_buffer_->DidConsume(result); | 382 current_write_buffer_->DidConsume(result); |
383 } | 383 } |
384 | 384 |
385 void NativeMessageProcessHost::OnWritten(int result) { | 385 void NativeMessageProcessHost::OnWritten(int result) { |
386 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 386 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
387 | 387 |
388 DCHECK(write_pending_); | 388 DCHECK(write_pending_); |
389 write_pending_ = false; | 389 write_pending_ = false; |
390 | 390 |
391 HandleWriteResult(result); | 391 HandleWriteResult(result); |
392 DoWrite(); | 392 DoWrite(); |
393 } | 393 } |
394 | 394 |
395 void NativeMessageProcessHost::Close(const std::string& error_message) { | 395 void NativeMessageProcessHost::Close(const std::string& error_message) { |
396 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); | 396 DCHECK_CURRENTLY_ON(content::BrowserThread::IO); |
397 | 397 |
398 if (!closed_) { | 398 if (!closed_) { |
399 closed_ = true; | 399 closed_ = true; |
400 read_stream_.reset(); | 400 read_stream_.reset(); |
401 write_stream_.reset(); | 401 write_stream_.reset(); |
402 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, | 402 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
403 base::Bind(&Client::CloseChannel, weak_client_ui_, | 403 base::Bind(&Client::CloseChannel, weak_client_ui_, |
404 destination_port_, error_message)); | 404 destination_port_, error_message)); |
405 } | 405 } |
406 | 406 |
407 if (process_handle_ != base::kNullProcessHandle) { | 407 if (process_handle_ != base::kNullProcessHandle) { |
408 // Kill the host process if necessary to make sure we don't leave zombies. | 408 // Kill the host process if necessary to make sure we don't leave zombies. |
409 // On OSX base::EnsureProcessTerminated() may block, so we have to post a | 409 // On OSX base::EnsureProcessTerminated() may block, so we have to post a |
410 // task on the blocking pool. | 410 // task on the blocking pool. |
411 #if defined(OS_MACOSX) | 411 #if defined(OS_MACOSX) |
412 content::BrowserThread::PostBlockingPoolTask( | 412 content::BrowserThread::PostBlockingPoolTask( |
413 FROM_HERE, base::Bind(&base::EnsureProcessTerminated, process_handle_)); | 413 FROM_HERE, base::Bind(&base::EnsureProcessTerminated, process_handle_)); |
414 #else | 414 #else |
415 base::EnsureProcessTerminated(process_handle_); | 415 base::EnsureProcessTerminated(process_handle_); |
416 #endif | 416 #endif |
417 process_handle_ = base::kNullProcessHandle; | 417 process_handle_ = base::kNullProcessHandle; |
418 } | 418 } |
419 } | 419 } |
420 | 420 |
421 } // namespace extensions | 421 } // namespace extensions |
OLD | NEW |