OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/loader/nacl_listener.h" | 5 #include "components/nacl/loader/nacl_listener.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 #include <stdlib.h> | 9 #include <stdlib.h> |
10 #include <string.h> | 10 #include <string.h> |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
139 // Creates the PPAPI IPC channel between the NaCl IRT and the host | 139 // Creates the PPAPI IPC channel between the NaCl IRT and the host |
140 // (browser/renderer) process, and starts to listen it on the thread where | 140 // (browser/renderer) process, and starts to listen it on the thread where |
141 // the given message_loop_proxy runs. | 141 // the given message_loop_proxy runs. |
142 // Also, creates and sets the corresponding NaClDesc to the given nap with | 142 // Also, creates and sets the corresponding NaClDesc to the given nap with |
143 // the FD #. | 143 // the FD #. |
144 void SetUpIPCAdapter( | 144 void SetUpIPCAdapter( |
145 IPC::ChannelHandle* handle, | 145 IPC::ChannelHandle* handle, |
146 scoped_refptr<base::MessageLoopProxy> message_loop_proxy, | 146 scoped_refptr<base::MessageLoopProxy> message_loop_proxy, |
147 struct NaClApp* nap, | 147 struct NaClApp* nap, |
148 int nacl_fd, | 148 int nacl_fd, |
149 NaClIPCAdapter::ResolveFileTokenCallback resolve_file_token_cb) { | 149 NaClIPCAdapter::ResolveFileTokenCallback resolve_file_token_cb, |
| 150 NaClIPCAdapter::OpenResourceCallback open_resource_cb) { |
150 scoped_refptr<NaClIPCAdapter> ipc_adapter( | 151 scoped_refptr<NaClIPCAdapter> ipc_adapter( |
151 new NaClIPCAdapter(*handle, | 152 new NaClIPCAdapter(*handle, |
152 message_loop_proxy.get(), | 153 message_loop_proxy.get(), |
153 resolve_file_token_cb)); | 154 resolve_file_token_cb, |
| 155 open_resource_cb)); |
154 ipc_adapter->ConnectChannel(); | 156 ipc_adapter->ConnectChannel(); |
155 #if defined(OS_POSIX) | 157 #if defined(OS_POSIX) |
156 handle->socket = | 158 handle->socket = |
157 base::FileDescriptor(ipc_adapter->TakeClientFileDescriptor()); | 159 base::FileDescriptor(ipc_adapter->TakeClientFileDescriptor()); |
158 #endif | 160 #endif |
159 | 161 |
160 // Pass a NaClDesc to the untrusted side. This will hold a ref to the | 162 // Pass a NaClDesc to the untrusted side. This will hold a ref to the |
161 // NaClIPCAdapter. | 163 // NaClIPCAdapter. |
162 NaClAppSetDesc(nap, nacl_fd, ipc_adapter->MakeNaClDesc()); | 164 NaClAppSetDesc(nap, nacl_fd, ipc_adapter->MakeNaClDesc()); |
163 } | 165 } |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 | 274 |
273 bool NaClListener::OnMessageReceived(const IPC::Message& msg) { | 275 bool NaClListener::OnMessageReceived(const IPC::Message& msg) { |
274 bool handled = true; | 276 bool handled = true; |
275 IPC_BEGIN_MESSAGE_MAP(NaClListener, msg) | 277 IPC_BEGIN_MESSAGE_MAP(NaClListener, msg) |
276 IPC_MESSAGE_HANDLER(NaClProcessMsg_Start, OnStart) | 278 IPC_MESSAGE_HANDLER(NaClProcessMsg_Start, OnStart) |
277 IPC_MESSAGE_UNHANDLED(handled = false) | 279 IPC_MESSAGE_UNHANDLED(handled = false) |
278 IPC_END_MESSAGE_MAP() | 280 IPC_END_MESSAGE_MAP() |
279 return handled; | 281 return handled; |
280 } | 282 } |
281 | 283 |
| 284 bool NaClListener::OnOpenResource( |
| 285 const IPC::Message& msg, |
| 286 const std::string& key, |
| 287 NaClIPCAdapter::OpenResourceReplyCallback cb) { |
| 288 // This callback is executed only on |io_thread_| with NaClIPCAdapter's |
| 289 // |lock_| not being held. |
| 290 DCHECK(!cb.is_null()); |
| 291 PrefetchedResourceFilesMap::iterator it = |
| 292 prefetched_resource_files_.find(key); |
| 293 |
| 294 if (it != prefetched_resource_files_.end()) { |
| 295 // Fast path for prefetched FDs. |
| 296 IPC::PlatformFileForTransit file = it->second.first; |
| 297 base::FilePath path = it->second.second; |
| 298 prefetched_resource_files_.erase(it); |
| 299 // A pre-opened resource descriptor is available. Run the reply callback |
| 300 // and return true. |
| 301 cb.Run(msg, file, path); |
| 302 return true; |
| 303 } |
| 304 |
| 305 // Return false to fall back to the slow path. Let NaClIPCAdapter issue an |
| 306 // IPC to the renderer. |
| 307 return false; |
| 308 } |
| 309 |
282 void NaClListener::OnStart(const nacl::NaClStartParams& params) { | 310 void NaClListener::OnStart(const nacl::NaClStartParams& params) { |
283 #if defined(OS_LINUX) || defined(OS_MACOSX) | 311 #if defined(OS_LINUX) || defined(OS_MACOSX) |
284 int urandom_fd = dup(base::GetUrandomFD()); | 312 int urandom_fd = dup(base::GetUrandomFD()); |
285 if (urandom_fd < 0) { | 313 if (urandom_fd < 0) { |
286 LOG(ERROR) << "Failed to dup() the urandom FD"; | 314 LOG(ERROR) << "Failed to dup() the urandom FD"; |
287 return; | 315 return; |
288 } | 316 } |
289 NaClChromeMainSetUrandomFd(urandom_fd); | 317 NaClChromeMainSetUrandomFd(urandom_fd); |
290 #endif | 318 #endif |
291 struct NaClApp* nap = NULL; | 319 struct NaClApp* nap = NULL; |
292 NaClChromeMainInit(); | 320 NaClChromeMainInit(); |
293 | 321 |
294 CHECK(base::SharedMemory::IsHandleValid(params.crash_info_shmem_handle)); | 322 CHECK(base::SharedMemory::IsHandleValid(params.crash_info_shmem_handle)); |
295 crash_info_shmem_.reset(new base::SharedMemory( | 323 crash_info_shmem_.reset(new base::SharedMemory( |
296 params.crash_info_shmem_handle, false /* not readonly */)); | 324 params.crash_info_shmem_handle, false /* not readonly */)); |
297 CHECK(crash_info_shmem_->Map(nacl::kNaClCrashInfoShmemSize)); | 325 CHECK(crash_info_shmem_->Map(nacl::kNaClCrashInfoShmemSize)); |
298 NaClSetFatalErrorCallback(&FatalLogHandler); | 326 NaClSetFatalErrorCallback(&FatalLogHandler); |
299 | 327 |
300 nap = NaClAppCreate(); | 328 nap = NaClAppCreate(); |
301 if (nap == NULL) { | 329 if (nap == NULL) { |
302 LOG(ERROR) << "NaClAppCreate() failed"; | 330 LOG(ERROR) << "NaClAppCreate() failed"; |
303 return; | 331 return; |
304 } | 332 } |
305 | 333 |
306 IPC::ChannelHandle browser_handle; | 334 IPC::ChannelHandle browser_handle; |
307 IPC::ChannelHandle ppapi_renderer_handle; | 335 IPC::ChannelHandle ppapi_renderer_handle; |
308 IPC::ChannelHandle manifest_service_handle; | 336 IPC::ChannelHandle manifest_service_handle; |
309 | 337 |
| 338 for (size_t i = 0; i < params.prefetched_resource_files.size(); ++i) { |
| 339 bool result = prefetched_resource_files_.insert(std::make_pair( |
| 340 params.prefetched_resource_files[i].file_key, |
| 341 std::make_pair( |
| 342 params.prefetched_resource_files[i].file, |
| 343 params.prefetched_resource_files[i].file_path_metadata))).second; |
| 344 if (!result) { |
| 345 LOG(FATAL) << "Duplicated open_resource key: " |
| 346 << params.prefetched_resource_files[i].file_key; |
| 347 } |
| 348 } |
| 349 |
310 if (params.enable_ipc_proxy) { | 350 if (params.enable_ipc_proxy) { |
311 browser_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); | 351 browser_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); |
312 ppapi_renderer_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); | 352 ppapi_renderer_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); |
313 manifest_service_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); | 353 manifest_service_handle = IPC::Channel::GenerateVerifiedChannelID("nacl"); |
314 | 354 |
315 // Create the PPAPI IPC channels between the NaCl IRT and the host | 355 // Create the PPAPI IPC channels between the NaCl IRT and the host |
316 // (browser/renderer) processes. The IRT uses these channels to | 356 // (browser/renderer) processes. The IRT uses these channels to |
317 // communicate with the host and to initialize the IPC dispatchers. | 357 // communicate with the host and to initialize the IPC dispatchers. |
318 SetUpIPCAdapter(&browser_handle, io_thread_.message_loop_proxy(), | 358 SetUpIPCAdapter(&browser_handle, io_thread_.message_loop_proxy(), |
319 nap, NACL_CHROME_DESC_BASE, | 359 nap, NACL_CHROME_DESC_BASE, |
320 NaClIPCAdapter::ResolveFileTokenCallback()); | 360 NaClIPCAdapter::ResolveFileTokenCallback(), |
| 361 NaClIPCAdapter::OpenResourceCallback()); |
321 SetUpIPCAdapter(&ppapi_renderer_handle, io_thread_.message_loop_proxy(), | 362 SetUpIPCAdapter(&ppapi_renderer_handle, io_thread_.message_loop_proxy(), |
322 nap, NACL_CHROME_DESC_BASE + 1, | 363 nap, NACL_CHROME_DESC_BASE + 1, |
323 NaClIPCAdapter::ResolveFileTokenCallback()); | 364 NaClIPCAdapter::ResolveFileTokenCallback(), |
| 365 NaClIPCAdapter::OpenResourceCallback()); |
324 SetUpIPCAdapter(&manifest_service_handle, | 366 SetUpIPCAdapter(&manifest_service_handle, |
325 io_thread_.message_loop_proxy(), | 367 io_thread_.message_loop_proxy(), |
326 nap, | 368 nap, |
327 NACL_CHROME_DESC_BASE + 2, | 369 NACL_CHROME_DESC_BASE + 2, |
328 base::Bind(&NaClListener::ResolveFileToken, | 370 base::Bind(&NaClListener::ResolveFileToken, |
| 371 base::Unretained(this)), |
| 372 base::Bind(&NaClListener::OnOpenResource, |
329 base::Unretained(this))); | 373 base::Unretained(this))); |
330 } | 374 } |
331 | 375 |
332 trusted_listener_ = new NaClTrustedListener( | 376 trusted_listener_ = new NaClTrustedListener( |
333 IPC::Channel::GenerateVerifiedChannelID("nacl"), | 377 IPC::Channel::GenerateVerifiedChannelID("nacl"), |
334 io_thread_.message_loop_proxy().get(), | 378 io_thread_.message_loop_proxy().get(), |
335 &shutdown_event_); | 379 &shutdown_event_); |
336 if (!Send(new NaClProcessHostMsg_PpapiChannelsCreated( | 380 if (!Send(new NaClProcessHostMsg_PpapiChannelsCreated( |
337 browser_handle, | 381 browser_handle, |
338 ppapi_renderer_handle, | 382 ppapi_renderer_handle, |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
427 #if defined(OS_LINUX) | 471 #if defined(OS_LINUX) |
428 args->prereserved_sandbox_size = prereserved_sandbox_size_; | 472 args->prereserved_sandbox_size = prereserved_sandbox_size_; |
429 #endif | 473 #endif |
430 | 474 |
431 base::PlatformFile nexe_file = IPC::PlatformFileForTransitToPlatformFile( | 475 base::PlatformFile nexe_file = IPC::PlatformFileForTransitToPlatformFile( |
432 params.nexe_file); | 476 params.nexe_file); |
433 std::string file_path_str = params.nexe_file_path_metadata.AsUTF8Unsafe(); | 477 std::string file_path_str = params.nexe_file_path_metadata.AsUTF8Unsafe(); |
434 args->nexe_desc = NaClDescCreateWithFilePathMetadata(nexe_file, | 478 args->nexe_desc = NaClDescCreateWithFilePathMetadata(nexe_file, |
435 file_path_str.c_str()); | 479 file_path_str.c_str()); |
436 | 480 |
437 // TODO(yusukes): Support pre-opening resource files. | |
438 CHECK(params.prefetched_resource_files.empty()); | |
439 | |
440 int exit_status; | 481 int exit_status; |
441 if (!NaClChromeMainStart(nap, args, &exit_status)) | 482 if (!NaClChromeMainStart(nap, args, &exit_status)) |
442 NaClExit(1); | 483 NaClExit(1); |
443 | 484 |
444 // Report the plugin's exit status if the application started successfully. | 485 // Report the plugin's exit status if the application started successfully. |
445 trusted_listener_->Send(new NaClRendererMsg_ReportExitStatus(exit_status)); | 486 trusted_listener_->Send(new NaClRendererMsg_ReportExitStatus(exit_status)); |
446 NaClExit(exit_status); | 487 NaClExit(exit_status); |
447 } | 488 } |
448 | 489 |
449 void NaClListener::ResolveFileToken( | 490 void NaClListener::ResolveFileToken( |
450 uint64_t token_lo, | 491 uint64_t token_lo, |
451 uint64_t token_hi, | 492 uint64_t token_hi, |
452 base::Callback<void(IPC::PlatformFileForTransit, base::FilePath)> cb) { | 493 base::Callback<void(IPC::PlatformFileForTransit, base::FilePath)> cb) { |
453 if (!Send(new NaClProcessMsg_ResolveFileToken(token_lo, token_hi))) { | 494 if (!Send(new NaClProcessMsg_ResolveFileToken(token_lo, token_hi))) { |
454 cb.Run(IPC::PlatformFileForTransit(), base::FilePath()); | 495 cb.Run(IPC::PlatformFileForTransit(), base::FilePath()); |
455 return; | 496 return; |
456 } | 497 } |
457 resolved_cb_ = cb; | 498 resolved_cb_ = cb; |
458 } | 499 } |
459 | 500 |
460 void NaClListener::OnFileTokenResolved( | 501 void NaClListener::OnFileTokenResolved( |
461 uint64_t token_lo, | 502 uint64_t token_lo, |
462 uint64_t token_hi, | 503 uint64_t token_hi, |
463 IPC::PlatformFileForTransit ipc_fd, | 504 IPC::PlatformFileForTransit ipc_fd, |
464 base::FilePath file_path) { | 505 base::FilePath file_path) { |
465 resolved_cb_.Run(ipc_fd, file_path); | 506 resolved_cb_.Run(ipc_fd, file_path); |
466 resolved_cb_.Reset(); | 507 resolved_cb_.Reset(); |
467 } | 508 } |
OLD | NEW |