Chromium Code Reviews| Index: components/nacl/renderer/ppb_nacl_private_impl.cc |
| diff --git a/components/nacl/renderer/ppb_nacl_private_impl.cc b/components/nacl/renderer/ppb_nacl_private_impl.cc |
| index 1a3f204deef7ca3338154bcc57ce0c135977ebf9..7861de180d9e7c1dcd91c5966c7722b3572fe28f 100644 |
| --- a/components/nacl/renderer/ppb_nacl_private_impl.cc |
| +++ b/components/nacl/renderer/ppb_nacl_private_impl.cc |
| @@ -4,6 +4,8 @@ |
| #include "components/nacl/renderer/ppb_nacl_private_impl.h" |
| +#include "base/bind.h" |
| +#include "base/bind_helpers.h" |
| #include "base/command_line.h" |
| #include "base/containers/scoped_ptr_hash_map.h" |
| #include "base/lazy_instance.h" |
| @@ -13,6 +15,7 @@ |
| #include "components/nacl/common/nacl_messages.h" |
| #include "components/nacl/common/nacl_switches.h" |
| #include "components/nacl/common/nacl_types.h" |
| +#include "components/nacl/renderer/embedder_service_channel.h" |
| #include "components/nacl/renderer/nexe_load_manager.h" |
| #include "components/nacl/renderer/pnacl_translation_resource_host.h" |
| #include "components/nacl/renderer/sandbox_arch.h" |
| @@ -104,6 +107,50 @@ bool IsValidChannelHandle(const IPC::ChannelHandle& channel_handle) { |
| return true; |
| } |
| +// Callback invoked when an IPC channel connection is established. |
| +// As we will establish multiple IPC channels, this takes the number |
| +// of expected invocations and callback. When all channels are established, |
|
dmichael (off chromium)
2014/04/10 23:14:38
nit: "a" callback here, "the given callback" below
hidehiko
2014/04/11 16:28:30
Thanks. Done.
|
| +// given callback will be invoked on the main thread. Its argument will be |
| +// PP_OK, if all the connections are successfully establishe. Otherwise, |
|
dmichael (off chromium)
2014/04/10 23:14:38
nit: no comma after PP_OK, also establishe->establ
hidehiko
2014/04/11 16:28:30
Done.
|
| +// the first error code will be passed, and remaining errors will be ignored. |
| +// Note that PP_CompletionCallback is designed to be called exactly once. |
| +class ChannelConnectedCallback { |
| + public: |
| + ChannelConnectedCallback(int num_expect_calls, |
| + PP_CompletionCallback callback) |
| + : num_remaining_calls_(num_expect_calls), |
| + callback_(callback), |
| + result_(PP_OK) { |
| + } |
| + |
| + ~ChannelConnectedCallback() { |
| + } |
| + |
| + void Run(int32_t result) { |
| + if (result_ == PP_OK && result != PP_OK) { |
| + // This is the first error, so remember it. |
| + result_ = result; |
| + } |
| + |
| + --num_remaining_calls_; |
| + if (num_remaining_calls_ > 0) { |
| + // There still are some pending or on-going tasks. Wait for the results. |
| + return; |
| + } |
| + |
| + ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask( |
| + FROM_HERE, |
| + base::Bind(callback_.func, callback_.user_data, result_)); |
| + } |
| + |
| + private: |
| + int num_remaining_calls_; |
| + PP_CompletionCallback callback_; |
| + int32_t result_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(ChannelConnectedCallback); |
| +}; |
| + |
| // Launch NaCl's sel_ldr process. |
| void LaunchSelLdr(PP_Instance instance, |
| const char* alleged_url, |
| @@ -191,15 +238,15 @@ void LaunchSelLdr(PP_Instance instance, |
| *(static_cast<NaClHandle*>(imc_handle)) = |
| nacl::ToNativeHandle(result_socket); |
| - // TODO(hidehiko): We'll add EmbedderServiceChannel here, and it will wait |
| - // for the connection in parallel with TrustedPluginChannel. |
| - // Thus, the callback will wait for its second invocation to run callback, |
| - // then. |
| - // Note that PP_CompletionCallback is not designed to be called twice or |
| - // more. Thus, it is necessary to create a function to handle multiple |
| - // invocation. |
| - base::Callback<void(int32_t)> completion_callback = |
| - base::Bind(callback.func, callback.user_data); |
| + // Here after, we starts to establish connections for TrustedPluginChannel |
| + // and EmbedderServiceChannel in parallel. The invocation of the callback |
| + // is delegated to their connection completion callback. |
| + base::Callback<void(int32_t)> connected_callback = base::Bind( |
| + &ChannelConnectedCallback::Run, |
| + base::Owned(new ChannelConnectedCallback( |
| + 2, // For TrustedPluginChannel and EmbedderServiceChannel. |
| + callback))); |
| + |
| nacl::NexeLoadManager* load_manager = GetNexeLoadManager(instance); |
| DCHECK(load_manager); |
| @@ -209,11 +256,29 @@ void LaunchSelLdr(PP_Instance instance, |
| scoped_ptr<nacl::TrustedPluginChannel> trusted_plugin_channel( |
| new nacl::TrustedPluginChannel( |
| launch_result.trusted_ipc_channel_handle, |
| - completion_callback, |
| + connected_callback, |
| content::RenderThread::Get()->GetShutdownEvent())); |
| load_manager->set_trusted_plugin_channel(trusted_plugin_channel.Pass()); |
| } else { |
| - completion_callback.Run(PP_ERROR_FAILED); |
| + connected_callback.Run(PP_ERROR_FAILED); |
| + } |
| + |
| + // Stash the embedder service handle as well. |
| + if (load_manager && |
| + IsValidChannelHandle( |
| + launch_result.embedder_service_ipc_channel_handle)) { |
| + scoped_ptr<nacl::EmbedderServiceChannel> embedder_service_channel( |
| + new nacl::EmbedderServiceChannel( |
| + launch_result.embedder_service_ipc_channel_handle, |
| + connected_callback, |
| + content::RenderThread::Get()->GetShutdownEvent())); |
| + load_manager->set_embedder_service_channel( |
| + embedder_service_channel.Pass()); |
| + } else { |
| + // Currently, embedder service works only on linux/non-SFI mode. |
| + // On other platforms, the socket will not be created, and thus this |
| + // condition needs to be handled as success. |
| + connected_callback.Run(PP_OK); |
| } |
| } |