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..7daf05aea1902792aff989bd3dbc77e8c4ae5a63 100644 |
--- a/components/nacl/renderer/ppb_nacl_private_impl.cc |
+++ b/components/nacl/renderer/ppb_nacl_private_impl.cc |
@@ -13,6 +13,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 +105,40 @@ bool IsValidChannelHandle(const IPC::ChannelHandle& channel_handle) { |
return true; |
} |
+struct LaunchSelLdrCompletionCallbackData : |
dmichael (off chromium)
2014/04/10 18:06:23
A brief description of what the class does might b
hidehiko
2014/04/10 19:02:08
Done.
|
+ public base::RefCounted<LaunchSelLdrCompletionCallbackData> { |
+ public: |
+ LaunchSelLdrCompletionCallbackData(int num_expect_call) |
dmichael (off chromium)
2014/04/10 18:06:23
nit: explicit
hidehiko
2014/04/10 19:02:08
Acknowledged.
|
+ : num_remaining_call(num_expect_call), |
+ result(PP_OK) { |
+ } |
+ int num_remaining_call; |
dmichael (off chromium)
2014/04/10 18:06:23
nit: call->calls
hidehiko
2014/04/10 19:02:08
Done.
|
+ int32_t result; |
+ |
+ private: |
+ friend class base::RefCounted<LaunchSelLdrCompletionCallbackData>; |
+ ~LaunchSelLdrCompletionCallbackData() { |
+ } |
+}; |
+ |
+void LaunchSelLdrCompletionCallback( |
dmichael (off chromium)
2014/04/10 18:06:23
suggestion: It might simplify things a tiny bit to
hidehiko
2014/04/10 19:02:08
Good idea. How about this?
|
+ scoped_refptr<LaunchSelLdrCompletionCallbackData> data, |
+ PP_CompletionCallback callback, |
+ int32_t result) { |
+ if (data->result == PP_OK && result != PP_OK) |
+ data->result = result; |
+ |
+ --data->num_remaining_call; |
+ if (data->num_remaining_call > 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, data->result)); |
+} |
+ |
// Launch NaCl's sel_ldr process. |
void LaunchSelLdr(PP_Instance instance, |
const char* alleged_url, |
@@ -191,15 +226,17 @@ 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. |
+ // Here after we start to establish TrustedPluginChannel and |
+ // EmbedderServiceChannel in parallel. So, we count the number of connections |
+ // (or errors), and invoke callback when all the connections are established. |
// 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); |
+ base::Callback<void(int32_t)> completion_callback = base::Bind( |
+ &LaunchSelLdrCompletionCallback, |
+ make_scoped_refptr(new LaunchSelLdrCompletionCallbackData(2)), |
+ callback); |
+ |
nacl::NexeLoadManager* load_manager = GetNexeLoadManager(instance); |
DCHECK(load_manager); |
@@ -215,6 +252,24 @@ void LaunchSelLdr(PP_Instance instance, |
} else { |
completion_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, |
+ completion_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. |
+ completion_callback.Run(PP_OK); |
+ } |
} |
// Forward declaration. |