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/nacl_host/nacl_process_host.h" | 5 #include "chrome/browser/nacl_host/nacl_process_host.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 handles_for_sel_ldr->push_back(channel); | 103 handles_for_sel_ldr->push_back(channel); |
104 #endif | 104 #endif |
105 return true; | 105 return true; |
106 } | 106 } |
107 | 107 |
108 } // namespace | 108 } // namespace |
109 | 109 |
110 struct NaClProcessHost::NaClInternal { | 110 struct NaClProcessHost::NaClInternal { |
111 std::vector<nacl::Handle> sockets_for_renderer; | 111 std::vector<nacl::Handle> sockets_for_renderer; |
112 std::vector<nacl::Handle> sockets_for_sel_ldr; | 112 std::vector<nacl::Handle> sockets_for_sel_ldr; |
| 113 std::vector<nacl::FileDescriptor> handles_for_renderer; |
113 }; | 114 }; |
114 | 115 |
115 // ----------------------------------------------------------------------------- | 116 // ----------------------------------------------------------------------------- |
116 | 117 |
117 NaClProcessHost::NaClProcessHost(const GURL& manifest_url, bool off_the_record) | 118 NaClProcessHost::NaClProcessHost(const GURL& manifest_url, bool off_the_record) |
118 : manifest_url_(manifest_url), | 119 : manifest_url_(manifest_url), |
119 #if defined(OS_WIN) | 120 #if defined(OS_WIN) |
120 process_launched_by_broker_(false), | 121 process_launched_by_broker_(false), |
121 #elif defined(OS_LINUX) | 122 #elif defined(OS_LINUX) |
122 wait_for_nacl_gdb_(false), | 123 wait_for_nacl_gdb_(false), |
(...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
530 bool handled = true; | 531 bool handled = true; |
531 IPC_BEGIN_MESSAGE_MAP(NaClProcessHost, msg) | 532 IPC_BEGIN_MESSAGE_MAP(NaClProcessHost, msg) |
532 IPC_MESSAGE_HANDLER(NaClProcessMsg_QueryKnownToValidate, | 533 IPC_MESSAGE_HANDLER(NaClProcessMsg_QueryKnownToValidate, |
533 OnQueryKnownToValidate) | 534 OnQueryKnownToValidate) |
534 IPC_MESSAGE_HANDLER(NaClProcessMsg_SetKnownToValidate, | 535 IPC_MESSAGE_HANDLER(NaClProcessMsg_SetKnownToValidate, |
535 OnSetKnownToValidate) | 536 OnSetKnownToValidate) |
536 #if defined(OS_WIN) | 537 #if defined(OS_WIN) |
537 IPC_MESSAGE_HANDLER_DELAY_REPLY(NaClProcessMsg_AttachDebugExceptionHandler, | 538 IPC_MESSAGE_HANDLER_DELAY_REPLY(NaClProcessMsg_AttachDebugExceptionHandler, |
538 OnAttachDebugExceptionHandler) | 539 OnAttachDebugExceptionHandler) |
539 #endif | 540 #endif |
| 541 IPC_MESSAGE_HANDLER(NaClProcessHostMsg_PpapiChannelCreated, |
| 542 OnPpapiChannelCreated) |
540 IPC_MESSAGE_UNHANDLED(handled = false) | 543 IPC_MESSAGE_UNHANDLED(handled = false) |
541 IPC_END_MESSAGE_MAP() | 544 IPC_END_MESSAGE_MAP() |
542 return handled; | 545 return handled; |
543 } | 546 } |
544 | 547 |
545 void NaClProcessHost::OnProcessLaunched() { | 548 void NaClProcessHost::OnProcessLaunched() { |
546 if (!StartWithLaunchedProcess()) | 549 if (!StartWithLaunchedProcess()) |
547 delete this; | 550 delete this; |
548 } | 551 } |
549 | 552 |
550 // Called when the NaClBrowser singleton has been fully initialized. | 553 // Called when the NaClBrowser singleton has been fully initialized. |
551 void NaClProcessHost::OnResourcesReady() { | 554 void NaClProcessHost::OnResourcesReady() { |
552 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); | 555 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
553 if (!nacl_browser->IsReady() || !SendStart()) { | 556 if (!nacl_browser->IsReady() || !SendStart()) { |
554 DLOG(ERROR) << "Cannot launch NaCl process"; | 557 DLOG(ERROR) << "Cannot launch NaCl process"; |
555 delete this; | 558 delete this; |
556 } | 559 } |
557 } | 560 } |
558 | 561 |
559 bool NaClProcessHost::ReplyToRenderer() { | 562 bool NaClProcessHost::SendStart() { |
560 std::vector<nacl::FileDescriptor> handles_for_renderer; | 563 const ChildProcessData& data = process_->GetData(); |
561 for (size_t i = 0; i < internal_->sockets_for_renderer.size(); i++) { | |
562 #if defined(OS_WIN) | |
563 // Copy the handle into the renderer process. | |
564 HANDLE handle_in_renderer; | |
565 if (!DuplicateHandle(base::GetCurrentProcessHandle(), | |
566 reinterpret_cast<HANDLE>( | |
567 internal_->sockets_for_renderer[i]), | |
568 chrome_render_message_filter_->peer_handle(), | |
569 &handle_in_renderer, | |
570 0, // Unused given DUPLICATE_SAME_ACCESS. | |
571 FALSE, | |
572 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { | |
573 DLOG(ERROR) << "DuplicateHandle() failed"; | |
574 return false; | |
575 } | |
576 handles_for_renderer.push_back( | |
577 reinterpret_cast<nacl::FileDescriptor>(handle_in_renderer)); | |
578 #else | |
579 // No need to dup the imc_handle - we don't pass it anywhere else so | |
580 // it cannot be closed. | |
581 nacl::FileDescriptor imc_handle; | |
582 imc_handle.fd = internal_->sockets_for_renderer[i]; | |
583 imc_handle.auto_close = true; | |
584 handles_for_renderer.push_back(imc_handle); | |
585 #endif | |
586 } | |
587 | |
588 #if defined(OS_WIN) | 564 #if defined(OS_WIN) |
589 // If we are on 64-bit Windows, the NaCl process's sandbox is | 565 // If we are on 64-bit Windows, the NaCl process's sandbox is |
590 // managed by a different process from the renderer's sandbox. We | 566 // managed by a different process from the renderer's sandbox. We |
591 // need to inform the renderer's sandbox about the NaCl process so | 567 // need to inform the renderer's sandbox about the NaCl process so |
592 // that the renderer can send handles to the NaCl process using | 568 // that the renderer can send handles to the NaCl process using |
593 // BrokerDuplicateHandle(). | 569 // BrokerDuplicateHandle(). |
594 if (RunningOnWOW64()) { | 570 if (RunningOnWOW64()) { |
595 if (!content::BrokerAddTargetPeer(process_->GetData().handle)) { | 571 if (!content::BrokerAddTargetPeer(data.handle)) { |
596 DLOG(ERROR) << "Failed to add NaCl process PID"; | 572 DLOG(ERROR) << "Failed to add NaCl process PID"; |
597 return false; | 573 return false; |
598 } | 574 } |
599 } | 575 } |
600 #endif | 576 #endif |
601 | 577 |
602 ChromeViewHostMsg_LaunchNaCl::WriteReplyParams( | |
603 reply_msg_, handles_for_renderer); | |
604 chrome_render_message_filter_->Send(reply_msg_); | |
605 chrome_render_message_filter_ = NULL; | |
606 reply_msg_ = NULL; | |
607 internal_->sockets_for_renderer.clear(); | |
608 return true; | |
609 } | |
610 | |
611 bool NaClProcessHost::StartNaClExecution() { | |
612 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); | 578 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
613 | 579 |
614 nacl::NaClStartParams params; | 580 nacl::NaClStartParams params; |
615 params.validation_cache_enabled = nacl_browser->ValidationCacheIsEnabled(); | 581 params.validation_cache_enabled = nacl_browser->ValidationCacheIsEnabled(); |
616 params.validation_cache_key = nacl_browser->GetValidationCacheKey(); | 582 params.validation_cache_key = nacl_browser->GetValidationCacheKey(); |
617 params.version = chrome::VersionInfo().CreateVersionString(); | 583 params.version = chrome::VersionInfo().CreateVersionString(); |
618 params.enable_exception_handling = enable_exception_handling_; | 584 params.enable_exception_handling = enable_exception_handling_; |
619 params.enable_debug_stub = | 585 params.enable_debug_stub = |
620 CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableNaClDebug); | 586 CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableNaClDebug); |
| 587 params.enable_ipc_proxy = CommandLine::ForCurrentProcess()->HasSwitch( |
| 588 switches::kEnableNaClIPCProxy); |
621 | 589 |
622 base::PlatformFile irt_file = nacl_browser->IrtFile(); | 590 base::PlatformFile irt_file = nacl_browser->IrtFile(); |
623 CHECK_NE(irt_file, base::kInvalidPlatformFileValue); | 591 CHECK_NE(irt_file, base::kInvalidPlatformFileValue); |
624 | 592 |
625 const ChildProcessData& data = process_->GetData(); | 593 // TODO(bbudge) In case of errors, the destructor may close handles that |
| 594 // have already been closed by DuplicateHandle, which is unsafe. Add some |
| 595 // helper functions that can be invoked when handle duplication fails, to |
| 596 // clean more carefully. |
626 for (size_t i = 0; i < internal_->sockets_for_sel_ldr.size(); i++) { | 597 for (size_t i = 0; i < internal_->sockets_for_sel_ldr.size(); i++) { |
627 if (!ShareHandleToSelLdr(data.handle, | 598 if (!ShareHandleToSelLdr(data.handle, |
628 internal_->sockets_for_sel_ldr[i], true, | 599 internal_->sockets_for_sel_ldr[i], true, |
629 ¶ms.handles)) { | 600 ¶ms.handles)) { |
630 return false; | 601 return false; |
631 } | 602 } |
632 } | 603 } |
633 | 604 |
634 // Send over the IRT file handle. We don't close our own copy! | 605 // Send over the IRT file handle. We don't close our own copy! |
635 if (!ShareHandleToSelLdr(data.handle, irt_file, false, ¶ms.handles)) | 606 if (!ShareHandleToSelLdr(data.handle, irt_file, false, ¶ms.handles)) |
(...skipping 15 matching lines...) Expand all Loading... |
651 nacl::FileDescriptor memory_fd; | 622 nacl::FileDescriptor memory_fd; |
652 memory_fd.fd = dup(memory_buffer.handle().fd); | 623 memory_fd.fd = dup(memory_buffer.handle().fd); |
653 if (memory_fd.fd < 0) { | 624 if (memory_fd.fd < 0) { |
654 DLOG(ERROR) << "Failed to dup() a file descriptor"; | 625 DLOG(ERROR) << "Failed to dup() a file descriptor"; |
655 return false; | 626 return false; |
656 } | 627 } |
657 memory_fd.auto_close = true; | 628 memory_fd.auto_close = true; |
658 params.handles.push_back(memory_fd); | 629 params.handles.push_back(memory_fd); |
659 #endif | 630 #endif |
660 | 631 |
| 632 for (size_t i = 0; i < internal_->sockets_for_renderer.size(); i++) { |
| 633 #if defined(OS_WIN) |
| 634 // Copy the handle into the renderer process. |
| 635 HANDLE handle_in_renderer; |
| 636 if (!DuplicateHandle(base::GetCurrentProcessHandle(), |
| 637 reinterpret_cast<HANDLE>( |
| 638 internal_->sockets_for_renderer[i]), |
| 639 chrome_render_message_filter_->peer_handle(), |
| 640 &handle_in_renderer, |
| 641 0, // Unused given DUPLICATE_SAME_ACCESS. |
| 642 FALSE, |
| 643 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { |
| 644 DLOG(ERROR) << "DuplicateHandle() failed"; |
| 645 return false; |
| 646 } |
| 647 internal_->handles_for_renderer.push_back( |
| 648 reinterpret_cast<nacl::FileDescriptor>(handle_in_renderer)); |
| 649 #else |
| 650 // No need to dup the imc_handle - we don't pass it anywhere else so |
| 651 // it cannot be closed. |
| 652 nacl::FileDescriptor imc_handle; |
| 653 imc_handle.fd = internal_->sockets_for_renderer[i]; |
| 654 imc_handle.auto_close = true; |
| 655 internal_->handles_for_renderer.push_back(imc_handle); |
| 656 #endif |
| 657 } |
| 658 |
| 659 // The start message should only be sent once we are sure we won't delete |
| 660 // ourselves. |
661 process_->Send(new NaClProcessMsg_Start(params)); | 661 process_->Send(new NaClProcessMsg_Start(params)); |
662 | 662 |
663 internal_->sockets_for_sel_ldr.clear(); | 663 internal_->sockets_for_sel_ldr.clear(); |
| 664 |
| 665 // If we aren't creating the IPC channel, send the reply message without |
| 666 // waiting for the NaCl process to signal that it's ready. |
| 667 // TODO(bbudge) remove this after we switch to the IPC proxy. |
| 668 if (!params.enable_ipc_proxy) { |
| 669 OnPpapiChannelCreated(IPC::ChannelHandle()); |
| 670 } |
| 671 |
664 return true; | 672 return true; |
665 } | 673 } |
666 | 674 |
667 bool NaClProcessHost::SendStart() { | 675 void NaClProcessHost::OnPpapiChannelCreated( |
668 return ReplyToRenderer() && StartNaClExecution(); | 676 const IPC::ChannelHandle& channel_handle) { |
| 677 // Now that the server end of the channel has been created, send the reply to |
| 678 // the renderer. |
| 679 ChromeViewHostMsg_LaunchNaCl::WriteReplyParams( |
| 680 reply_msg_, internal_->handles_for_renderer, channel_handle); |
| 681 chrome_render_message_filter_->Send(reply_msg_); |
| 682 chrome_render_message_filter_ = NULL; |
| 683 reply_msg_ = NULL; |
| 684 |
| 685 internal_->sockets_for_renderer.clear(); |
| 686 internal_->handles_for_renderer.clear(); |
669 } | 687 } |
670 | 688 |
671 bool NaClProcessHost::StartWithLaunchedProcess() { | 689 bool NaClProcessHost::StartWithLaunchedProcess() { |
672 #if defined(OS_LINUX) | 690 #if defined(OS_LINUX) |
673 if (wait_for_nacl_gdb_) { | 691 if (wait_for_nacl_gdb_) { |
674 if (LaunchNaClGdb(base::GetProcId(process_->GetData().handle))) { | 692 if (LaunchNaClGdb(base::GetProcId(process_->GetData().handle))) { |
675 // We will be called with wait_for_nacl_gdb_ = false once debugger is | 693 // We will be called with wait_for_nacl_gdb_ = false once debugger is |
676 // attached to the program. | 694 // attached to the program. |
677 return true; | 695 return true; |
678 } | 696 } |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
765 } else { | 783 } else { |
766 NaClStartDebugExceptionHandlerThread( | 784 NaClStartDebugExceptionHandlerThread( |
767 process_handle.Take(), info, | 785 process_handle.Take(), info, |
768 base::MessageLoopProxy::current(), | 786 base::MessageLoopProxy::current(), |
769 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, | 787 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, |
770 weak_factory_.GetWeakPtr())); | 788 weak_factory_.GetWeakPtr())); |
771 return true; | 789 return true; |
772 } | 790 } |
773 } | 791 } |
774 #endif | 792 #endif |
OLD | NEW |