| 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 9f88e584c779c045770578de2079ab6c83f1d026..a4c9af9b2f18befa096ef16ffbd7d1cd3e3e33ae 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/manifest_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"
|
| @@ -105,6 +108,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 a callback. When all channels are established,
|
| +// the given callback will be invoked on the main thread. Its argument will be
|
| +// PP_OK if all the connections are successfully established. Otherwise,
|
| +// 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,
|
| @@ -192,15 +239,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 ManifestServiceChannel 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 ManifestServiceChannel.
|
| + callback)));
|
| +
|
| nacl::NexeLoadManager* load_manager = GetNexeLoadManager(instance);
|
| DCHECK(load_manager);
|
|
|
| @@ -210,11 +257,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 manifest service handle as well.
|
| + if (load_manager &&
|
| + IsValidChannelHandle(
|
| + launch_result.manifest_service_ipc_channel_handle)) {
|
| + scoped_ptr<nacl::ManifestServiceChannel> manifest_service_channel(
|
| + new nacl::ManifestServiceChannel(
|
| + launch_result.manifest_service_ipc_channel_handle,
|
| + connected_callback,
|
| + content::RenderThread::Get()->GetShutdownEvent()));
|
| + load_manager->set_manifest_service_channel(
|
| + manifest_service_channel.Pass());
|
| + } else {
|
| + // Currently, manifest 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);
|
| }
|
| }
|
|
|
|
|