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 "components/nacl/browser/nacl_process_host.h" | 5 #include "components/nacl/browser/nacl_process_host.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
196 | 196 |
197 void CloseFile(base::File file) { | 197 void CloseFile(base::File file) { |
198 // The base::File destructor will close the file for us. | 198 // The base::File destructor will close the file for us. |
199 } | 199 } |
200 | 200 |
201 } // namespace | 201 } // namespace |
202 | 202 |
203 unsigned NaClProcessHost::keepalive_throttle_interval_milliseconds_ = | 203 unsigned NaClProcessHost::keepalive_throttle_interval_milliseconds_ = |
204 ppapi::kKeepaliveThrottleIntervalDefaultMilliseconds; | 204 ppapi::kKeepaliveThrottleIntervalDefaultMilliseconds; |
205 | 205 |
206 // Unfortunately, we cannot use ScopedGeneric directly for IPC::ChannelHandle, | |
207 // because there is neither operator== nor operator != definition for it. | |
208 // Instead, define a simple wrapper for IPC::ChannelHandle with an assumption | |
209 // that this only takes a transferred IPC::ChannelHandle or one to be | |
210 // transferred via IPC. | |
211 class NaClProcessHost::ScopedChannelHandle { | |
212 MOVE_ONLY_TYPE_FOR_CPP_03(ScopedChannelHandle, RValue); | |
213 public: | |
214 ScopedChannelHandle() { | |
215 } | |
216 explicit ScopedChannelHandle(const IPC::ChannelHandle& handle) | |
217 : handle_(handle) { | |
218 DCHECK(IsSupportedHandle(handle_)); | |
219 } | |
220 ScopedChannelHandle(RValue other) : handle_(other.object->handle_) { | |
221 other.object->handle_ = IPC::ChannelHandle(); | |
222 DCHECK(IsSupportedHandle(handle_)); | |
223 } | |
224 ~ScopedChannelHandle() { | |
225 CloseIfNecessary(); | |
226 } | |
227 | |
228 const IPC::ChannelHandle& get() const { return handle_; } | |
229 IPC::ChannelHandle release() WARN_UNUSED_RESULT { | |
230 IPC::ChannelHandle result = handle_; | |
231 handle_ = IPC::ChannelHandle(); | |
232 return result; | |
233 } | |
234 | |
235 void reset(const IPC::ChannelHandle& handle = IPC::ChannelHandle()) { | |
236 DCHECK(IsSupportedHandle(handle)); | |
237 #if defined(OS_POSIX) | |
238 // Following the manner of base::ScopedGeneric, we do not support | |
239 // reset() with same handle for simplicity of the implementation. | |
240 CHECK(handle.socket.fd == -1 || handle.socket.fd != handle_.socket.fd); | |
241 #endif | |
242 CloseIfNecessary(); | |
243 handle_ = handle; | |
244 } | |
245 | |
246 private: | |
247 // Returns true if the given handle is closable automatically by this | |
248 // class. This function is just a helper for the validation. | |
Mark Seaborn
2015/05/06 21:24:52
Nit: "for validation"? (no "the")
hidehiko
2015/05/07 01:29:06
Done.
| |
249 static bool IsSupportedHandle(const IPC::ChannelHandle& handle) { | |
250 #if defined(OS_WIN) | |
251 // On Windows, it is not supported to marshal the |pipe.handle|. | |
252 // In our case, we wrap a transferred ChannelHandle (or one to be | |
253 // transferred) via IPC, so we can assume |handle.pipe.handle| is NULL. | |
254 return handle.pipe.handle == NULL; | |
255 #else | |
256 return true; | |
257 #endif | |
258 } | |
259 | |
260 void CloseIfNecessary() { | |
261 #if defined(OS_POSIX) | |
262 if (handle_.socket.auto_close) { | |
263 // Defer closing task to the ScopedFD. | |
264 base::ScopedFD(handle_.socket.fd); | |
265 } | |
266 #endif | |
267 } | |
268 | |
269 IPC::ChannelHandle handle_; | |
270 }; | |
271 | |
206 NaClProcessHost::NaClProcessHost( | 272 NaClProcessHost::NaClProcessHost( |
207 const GURL& manifest_url, | 273 const GURL& manifest_url, |
208 base::File nexe_file, | 274 base::File nexe_file, |
209 const NaClFileToken& nexe_token, | 275 const NaClFileToken& nexe_token, |
210 const std::vector<NaClResourcePrefetchResult>& prefetched_resource_files, | 276 const std::vector<NaClResourcePrefetchResult>& prefetched_resource_files, |
211 ppapi::PpapiPermissions permissions, | 277 ppapi::PpapiPermissions permissions, |
212 int render_view_id, | 278 int render_view_id, |
213 uint32 permission_bits, | 279 uint32 permission_bits, |
214 bool uses_nonsfi_mode, | 280 bool uses_nonsfi_mode, |
215 bool off_the_record, | 281 bool off_the_record, |
(...skipping 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
650 void NaClProcessHost::OnResourcesReady() { | 716 void NaClProcessHost::OnResourcesReady() { |
651 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); | 717 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
652 if (!nacl_browser->IsReady()) { | 718 if (!nacl_browser->IsReady()) { |
653 SendErrorToRenderer("could not acquire shared resources needed by NaCl"); | 719 SendErrorToRenderer("could not acquire shared resources needed by NaCl"); |
654 delete this; | 720 delete this; |
655 } else if (!StartNaClExecution()) { | 721 } else if (!StartNaClExecution()) { |
656 delete this; | 722 delete this; |
657 } | 723 } |
658 } | 724 } |
659 | 725 |
660 bool NaClProcessHost::ReplyToRenderer( | 726 void NaClProcessHost::ReplyToRenderer( |
661 const IPC::ChannelHandle& ppapi_channel_handle, | 727 ScopedChannelHandle ppapi_channel_handle, |
662 const IPC::ChannelHandle& trusted_channel_handle, | 728 ScopedChannelHandle trusted_channel_handle, |
663 const IPC::ChannelHandle& manifest_service_channel_handle) { | 729 ScopedChannelHandle manifest_service_channel_handle) { |
664 #if defined(OS_WIN) | 730 #if defined(OS_WIN) |
665 // If we are on 64-bit Windows, the NaCl process's sandbox is | 731 // If we are on 64-bit Windows, the NaCl process's sandbox is |
666 // managed by a different process from the renderer's sandbox. We | 732 // managed by a different process from the renderer's sandbox. We |
667 // need to inform the renderer's sandbox about the NaCl process so | 733 // need to inform the renderer's sandbox about the NaCl process so |
668 // that the renderer can send handles to the NaCl process using | 734 // that the renderer can send handles to the NaCl process using |
669 // BrokerDuplicateHandle(). | 735 // BrokerDuplicateHandle(). |
670 if (RunningOnWOW64()) { | 736 if (RunningOnWOW64()) { |
671 if (!content::BrokerAddTargetPeer(process_->GetData().handle)) { | 737 if (!content::BrokerAddTargetPeer(process_->GetData().handle)) { |
672 SendErrorToRenderer("BrokerAddTargetPeer() failed"); | 738 SendErrorToRenderer("BrokerAddTargetPeer() failed"); |
673 return false; | 739 return; |
674 } | 740 } |
675 } | 741 } |
676 #endif | 742 #endif |
677 | 743 |
678 FileDescriptor imc_handle_for_renderer; | 744 // Hereafter, always we send an IPC message with handles which are not |
Mark Seaborn
2015/05/06 21:24:52
Nit: "we always"
hidehiko
2015/05/07 01:29:06
Done.
| |
679 #if defined(OS_WIN) | 745 // closable in this process. |
Mark Seaborn
2015/05/06 21:24:53
Nit: Clarify that the unclosability applies only t
hidehiko
2015/05/07 01:29:06
Done.
| |
680 // Copy the handle into the renderer process. | 746 IPC::PlatformFileForTransit imc_handle_for_renderer = |
681 HANDLE handle_in_renderer; | 747 IPC::TakeFileHandleForProcess(socket_for_renderer_.Pass(), |
682 if (!DuplicateHandle(base::GetCurrentProcessHandle(), | 748 nacl_host_message_filter_->PeerHandle()); |
683 socket_for_renderer_.TakePlatformFile(), | |
684 nacl_host_message_filter_->PeerHandle(), | |
685 &handle_in_renderer, | |
686 0, // Unused given DUPLICATE_SAME_ACCESS. | |
687 FALSE, | |
688 DUPLICATE_CLOSE_SOURCE | DUPLICATE_SAME_ACCESS)) { | |
689 SendErrorToRenderer("DuplicateHandle() failed"); | |
690 return false; | |
691 } | |
692 imc_handle_for_renderer = reinterpret_cast<FileDescriptor>( | |
693 handle_in_renderer); | |
694 #else | |
695 // No need to dup the imc_handle - we don't pass it anywhere else so | |
696 // it cannot be closed. | |
697 FileDescriptor imc_handle; | |
698 imc_handle.fd = socket_for_renderer_.TakePlatformFile(); | |
699 imc_handle.auto_close = true; | |
700 imc_handle_for_renderer = imc_handle; | |
701 #endif | |
702 | 749 |
703 const ChildProcessData& data = process_->GetData(); | 750 std::string error_message; |
704 base::SharedMemoryHandle crash_info_shmem_renderer_handle; | 751 base::SharedMemoryHandle crash_info_shmem_renderer_handle; |
705 if (!crash_info_shmem_.ShareToProcess(nacl_host_message_filter_->PeerHandle(), | 752 if (!crash_info_shmem_.ShareToProcess(nacl_host_message_filter_->PeerHandle(), |
706 &crash_info_shmem_renderer_handle)) { | 753 &crash_info_shmem_renderer_handle)) { |
707 SendErrorToRenderer("ShareToProcess() failed"); | 754 // On error, we do not send "IPC::ChannelHandle"s to the renderer process. |
Mark Seaborn
2015/05/06 21:24:52
Can you also add:
"Some other FDs/handles still g
hidehiko
2015/05/07 01:29:06
Done.
| |
708 return false; | 755 ppapi_channel_handle.reset(); |
756 trusted_channel_handle.reset(); | |
757 manifest_service_channel_handle.reset(); | |
758 error_message = "ShareToProcess() failed"; | |
709 } | 759 } |
710 | 760 |
761 const ChildProcessData& data = process_->GetData(); | |
Mark Seaborn
2015/05/06 21:24:52
Nit: if you're moving this, you could just use "pr
hidehiko
2015/05/07 01:29:06
Pls let me keep it as is. |data| is also used for
| |
711 SendMessageToRenderer( | 762 SendMessageToRenderer( |
712 NaClLaunchResult(imc_handle_for_renderer, | 763 NaClLaunchResult(imc_handle_for_renderer, |
713 ppapi_channel_handle, | 764 ppapi_channel_handle.release(), |
714 trusted_channel_handle, | 765 trusted_channel_handle.release(), |
715 manifest_service_channel_handle, | 766 manifest_service_channel_handle.release(), |
716 base::GetProcId(data.handle), | 767 base::GetProcId(data.handle), |
717 data.id, | 768 data.id, |
718 crash_info_shmem_renderer_handle), | 769 crash_info_shmem_renderer_handle), |
719 std::string() /* error_message */); | 770 error_message); |
720 | 771 |
721 // Now that the crash information shmem handles have been shared with the | 772 // Now that the crash information shmem handles have been shared with the |
722 // plugin and the renderer, the browser can close its handle. | 773 // plugin and the renderer, the browser can close its handle. |
723 crash_info_shmem_.Close(); | 774 crash_info_shmem_.Close(); |
724 return true; | |
725 } | 775 } |
726 | 776 |
727 void NaClProcessHost::SendErrorToRenderer(const std::string& error_message) { | 777 void NaClProcessHost::SendErrorToRenderer(const std::string& error_message) { |
728 LOG(ERROR) << "NaCl process launch failed: " << error_message; | 778 LOG(ERROR) << "NaCl process launch failed: " << error_message; |
729 SendMessageToRenderer(NaClLaunchResult(), error_message); | 779 SendMessageToRenderer(NaClLaunchResult(), error_message); |
730 } | 780 } |
731 | 781 |
732 void NaClProcessHost::SendMessageToRenderer( | 782 void NaClProcessHost::SendMessageToRenderer( |
733 const NaClLaunchResult& result, | 783 const NaClLaunchResult& result, |
734 const std::string& error_message) { | 784 const std::string& error_message) { |
735 DCHECK(nacl_host_message_filter_.get()); | 785 DCHECK(nacl_host_message_filter_.get()); |
736 DCHECK(reply_msg_); | 786 DCHECK(reply_msg_); |
737 if (nacl_host_message_filter_.get() != NULL && reply_msg_ != NULL) { | 787 if (nacl_host_message_filter_.get() == NULL || reply_msg_ == NULL) { |
738 NaClHostMsg_LaunchNaCl::WriteReplyParams( | 788 // As DCHECKed above, this case should not happen in general. |
739 reply_msg_, result, error_message); | 789 // Though, in the case, unfortunately there is no proper way to release |
Mark Seaborn
2015/05/06 21:24:52
Nit: "in the case" -> "in this case"
hidehiko
2015/05/07 01:29:06
Done.
| |
740 nacl_host_message_filter_->Send(reply_msg_); | 790 // resources which are already created in |result|. We just give up to |
Mark Seaborn
2015/05/06 21:24:52
Nit: "give up on releasing them"
hidehiko
2015/05/07 01:29:06
Done.
| |
741 nacl_host_message_filter_ = NULL; | 791 // release them, and leak them. |
742 reply_msg_ = NULL; | 792 return; |
743 } | 793 } |
794 | |
795 NaClHostMsg_LaunchNaCl::WriteReplyParams(reply_msg_, result, error_message); | |
796 nacl_host_message_filter_->Send(reply_msg_); | |
797 nacl_host_message_filter_ = NULL; | |
798 reply_msg_ = NULL; | |
744 } | 799 } |
745 | 800 |
746 void NaClProcessHost::SetDebugStubPort(int port) { | 801 void NaClProcessHost::SetDebugStubPort(int port) { |
747 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); | 802 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
748 nacl_browser->SetProcessGdbDebugStubPort(process_->GetData().id, port); | 803 nacl_browser->SetProcessGdbDebugStubPort(process_->GetData().id, port); |
749 } | 804 } |
750 | 805 |
751 #if defined(OS_POSIX) | 806 #if defined(OS_POSIX) |
752 // TCP port we chose for NaCl debug stub. It can be any other number. | 807 // TCP port we chose for NaCl debug stub. It can be any other number. |
753 static const uint16_t kInitialDebugStubPort = 4014; | 808 static const uint16_t kInitialDebugStubPort = 4014; |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
932 } else { | 987 } else { |
933 params.nexe_file = IPC::TakeFileHandleForProcess( | 988 params.nexe_file = IPC::TakeFileHandleForProcess( |
934 nexe_file_.Pass(), process_->GetData().handle); | 989 nexe_file_.Pass(), process_->GetData().handle); |
935 } | 990 } |
936 process_->Send(new NaClProcessMsg_Start(params)); | 991 process_->Send(new NaClProcessMsg_Start(params)); |
937 } | 992 } |
938 | 993 |
939 // This method is called when NaClProcessHostMsg_PpapiChannelCreated is | 994 // This method is called when NaClProcessHostMsg_PpapiChannelCreated is |
940 // received. | 995 // received. |
941 void NaClProcessHost::OnPpapiChannelsCreated( | 996 void NaClProcessHost::OnPpapiChannelsCreated( |
942 const IPC::ChannelHandle& browser_channel_handle, | 997 const IPC::ChannelHandle& raw_browser_channel_handle, |
943 const IPC::ChannelHandle& ppapi_renderer_channel_handle, | 998 const IPC::ChannelHandle& raw_ppapi_renderer_channel_handle, |
944 const IPC::ChannelHandle& trusted_renderer_channel_handle, | 999 const IPC::ChannelHandle& raw_trusted_renderer_channel_handle, |
945 const IPC::ChannelHandle& manifest_service_channel_handle) { | 1000 const IPC::ChannelHandle& raw_manifest_service_channel_handle) { |
1001 ScopedChannelHandle browser_channel_handle(raw_browser_channel_handle); | |
1002 ScopedChannelHandle ppapi_renderer_channel_handle( | |
1003 raw_ppapi_renderer_channel_handle); | |
1004 ScopedChannelHandle trusted_renderer_channel_handle( | |
1005 raw_trusted_renderer_channel_handle); | |
1006 ScopedChannelHandle manifest_service_channel_handle( | |
1007 raw_manifest_service_channel_handle); | |
1008 | |
946 if (!enable_ppapi_proxy()) { | 1009 if (!enable_ppapi_proxy()) { |
947 ReplyToRenderer(IPC::ChannelHandle(), | 1010 ReplyToRenderer(ScopedChannelHandle(), |
948 trusted_renderer_channel_handle, | 1011 trusted_renderer_channel_handle.Pass(), |
949 manifest_service_channel_handle); | 1012 manifest_service_channel_handle.Pass()); |
950 return; | 1013 return; |
951 } | 1014 } |
952 | 1015 |
953 if (!ipc_proxy_channel_.get()) { | 1016 if (ipc_proxy_channel_.get()) { |
954 DCHECK_EQ(PROCESS_TYPE_NACL_LOADER, process_->GetData().process_type); | |
955 | |
956 ipc_proxy_channel_ = | |
957 IPC::ChannelProxy::Create(browser_channel_handle, | |
958 IPC::Channel::MODE_CLIENT, | |
959 NULL, | |
960 base::MessageLoopProxy::current().get()); | |
961 // Create the browser ppapi host and enable PPAPI message dispatching to the | |
962 // browser process. | |
963 ppapi_host_.reset(content::BrowserPpapiHost::CreateExternalPluginProcess( | |
964 ipc_proxy_channel_.get(), // sender | |
965 permissions_, | |
966 process_->GetData().handle, | |
967 ipc_proxy_channel_.get(), | |
968 nacl_host_message_filter_->render_process_id(), | |
969 render_view_id_, | |
970 profile_directory_)); | |
971 ppapi_host_->SetOnKeepaliveCallback( | |
972 NaClBrowser::GetDelegate()->GetOnKeepaliveCallback()); | |
973 | |
974 ppapi::PpapiNaClPluginArgs args; | |
975 args.off_the_record = nacl_host_message_filter_->off_the_record(); | |
976 args.permissions = permissions_; | |
977 args.keepalive_throttle_interval_milliseconds = | |
978 keepalive_throttle_interval_milliseconds_; | |
979 base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); | |
980 DCHECK(cmdline); | |
981 std::string flag_whitelist[] = { | |
982 switches::kV, | |
983 switches::kVModule, | |
984 }; | |
985 for (size_t i = 0; i < arraysize(flag_whitelist); ++i) { | |
986 std::string value = cmdline->GetSwitchValueASCII(flag_whitelist[i]); | |
987 if (!value.empty()) { | |
988 args.switch_names.push_back(flag_whitelist[i]); | |
989 args.switch_values.push_back(value); | |
990 } | |
991 } | |
992 | |
993 ppapi_host_->GetPpapiHost()->AddHostFactoryFilter( | |
994 scoped_ptr<ppapi::host::HostFactory>( | |
995 NaClBrowser::GetDelegate()->CreatePpapiHostFactory( | |
996 ppapi_host_.get()))); | |
997 | |
998 // Send a message to initialize the IPC dispatchers in the NaCl plugin. | |
999 ipc_proxy_channel_->Send(new PpapiMsg_InitializeNaClDispatcher(args)); | |
1000 | |
1001 // Let the renderer know that the IPC channels are established. | |
1002 ReplyToRenderer(ppapi_renderer_channel_handle, | |
1003 trusted_renderer_channel_handle, | |
1004 manifest_service_channel_handle); | |
1005 } else { | |
1006 // Attempt to open more than 1 browser channel is not supported. | 1017 // Attempt to open more than 1 browser channel is not supported. |
1007 // Shut down the NaCl process. | 1018 // Shut down the NaCl process. |
1008 process_->GetHost()->ForceShutdown(); | 1019 process_->GetHost()->ForceShutdown(); |
1020 return; | |
1009 } | 1021 } |
1022 | |
1023 DCHECK_EQ(PROCESS_TYPE_NACL_LOADER, process_->GetData().process_type); | |
1024 | |
1025 ipc_proxy_channel_ = | |
1026 IPC::ChannelProxy::Create(browser_channel_handle.release(), | |
1027 IPC::Channel::MODE_CLIENT, | |
1028 NULL, | |
1029 base::MessageLoopProxy::current().get()); | |
1030 // Create the browser ppapi host and enable PPAPI message dispatching to the | |
1031 // browser process. | |
1032 ppapi_host_.reset(content::BrowserPpapiHost::CreateExternalPluginProcess( | |
1033 ipc_proxy_channel_.get(), // sender | |
1034 permissions_, | |
1035 process_->GetData().handle, | |
1036 ipc_proxy_channel_.get(), | |
1037 nacl_host_message_filter_->render_process_id(), | |
1038 render_view_id_, | |
1039 profile_directory_)); | |
1040 ppapi_host_->SetOnKeepaliveCallback( | |
1041 NaClBrowser::GetDelegate()->GetOnKeepaliveCallback()); | |
1042 | |
1043 ppapi::PpapiNaClPluginArgs args; | |
1044 args.off_the_record = nacl_host_message_filter_->off_the_record(); | |
1045 args.permissions = permissions_; | |
1046 args.keepalive_throttle_interval_milliseconds = | |
1047 keepalive_throttle_interval_milliseconds_; | |
1048 base::CommandLine* cmdline = base::CommandLine::ForCurrentProcess(); | |
1049 DCHECK(cmdline); | |
1050 std::string flag_whitelist[] = { | |
1051 switches::kV, | |
1052 switches::kVModule, | |
1053 }; | |
1054 for (size_t i = 0; i < arraysize(flag_whitelist); ++i) { | |
1055 std::string value = cmdline->GetSwitchValueASCII(flag_whitelist[i]); | |
1056 if (!value.empty()) { | |
1057 args.switch_names.push_back(flag_whitelist[i]); | |
1058 args.switch_values.push_back(value); | |
1059 } | |
1060 } | |
1061 | |
1062 ppapi_host_->GetPpapiHost()->AddHostFactoryFilter( | |
1063 scoped_ptr<ppapi::host::HostFactory>( | |
1064 NaClBrowser::GetDelegate()->CreatePpapiHostFactory( | |
1065 ppapi_host_.get()))); | |
1066 | |
1067 // Send a message to initialize the IPC dispatchers in the NaCl plugin. | |
1068 ipc_proxy_channel_->Send(new PpapiMsg_InitializeNaClDispatcher(args)); | |
1069 | |
1070 // Let the renderer know that the IPC channels are established. | |
1071 ReplyToRenderer(ppapi_renderer_channel_handle.Pass(), | |
1072 trusted_renderer_channel_handle.Pass(), | |
1073 manifest_service_channel_handle.Pass()); | |
1010 } | 1074 } |
1011 | 1075 |
1012 bool NaClProcessHost::StartWithLaunchedProcess() { | 1076 bool NaClProcessHost::StartWithLaunchedProcess() { |
1013 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); | 1077 NaClBrowser* nacl_browser = NaClBrowser::GetInstance(); |
1014 | 1078 |
1015 if (nacl_browser->IsReady()) { | 1079 if (nacl_browser->IsReady()) { |
1016 return StartNaClExecution(); | 1080 return StartNaClExecution(); |
1017 } else if (nacl_browser->IsOk()) { | 1081 } else if (nacl_browser->IsOk()) { |
1018 nacl_browser->WaitForResources( | 1082 nacl_browser->WaitForResources( |
1019 base::Bind(&NaClProcessHost::OnResourcesReady, | 1083 base::Bind(&NaClProcessHost::OnResourcesReady, |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1180 process.Pass(), info, | 1244 process.Pass(), info, |
1181 base::MessageLoopProxy::current(), | 1245 base::MessageLoopProxy::current(), |
1182 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, | 1246 base::Bind(&NaClProcessHost::OnDebugExceptionHandlerLaunchedByBroker, |
1183 weak_factory_.GetWeakPtr())); | 1247 weak_factory_.GetWeakPtr())); |
1184 return true; | 1248 return true; |
1185 } | 1249 } |
1186 } | 1250 } |
1187 #endif | 1251 #endif |
1188 | 1252 |
1189 } // namespace nacl | 1253 } // namespace nacl |
OLD | NEW |