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/renderer/ppb_nacl_private_impl.h" | 5 #include "components/nacl/renderer/ppb_nacl_private_impl.h" |
6 | 6 |
7 #ifndef DISABLE_NACL | 7 #ifndef DISABLE_NACL |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/rand_util.h" | 12 #include "base/rand_util.h" |
13 #include "components/nacl/common/nacl_host_messages.h" | 13 #include "components/nacl/common/nacl_host_messages.h" |
| 14 #include "components/nacl/common/nacl_messages.h" |
14 #include "components/nacl/common/nacl_types.h" | 15 #include "components/nacl/common/nacl_types.h" |
15 #include "components/nacl/renderer/pnacl_translation_resource_host.h" | 16 #include "components/nacl/renderer/pnacl_translation_resource_host.h" |
| 17 #include "components/nacl/renderer/trusted_plugin_channel.h" |
16 #include "content/public/common/content_client.h" | 18 #include "content/public/common/content_client.h" |
17 #include "content/public/common/content_switches.h" | 19 #include "content/public/common/content_switches.h" |
18 #include "content/public/common/sandbox_init.h" | 20 #include "content/public/common/sandbox_init.h" |
19 #include "content/public/renderer/pepper_plugin_instance.h" | 21 #include "content/public/renderer/pepper_plugin_instance.h" |
20 #include "content/public/renderer/render_thread.h" | 22 #include "content/public/renderer/render_thread.h" |
21 #include "content/public/renderer/render_view.h" | 23 #include "content/public/renderer/render_view.h" |
22 #include "content/public/renderer/renderer_ppapi_host.h" | 24 #include "content/public/renderer/renderer_ppapi_host.h" |
23 #include "ppapi/c/pp_bool.h" | 25 #include "ppapi/c/pp_bool.h" |
24 #include "ppapi/c/private/pp_file_handle.h" | 26 #include "ppapi/c/private/pp_file_handle.h" |
25 #include "ppapi/native_client/src/trusted/plugin/nacl_entry_points.h" | 27 #include "ppapi/native_client/src/trusted/plugin/nacl_entry_points.h" |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
60 base::ProcessId plugin_pid; | 62 base::ProcessId plugin_pid; |
61 int plugin_child_id; | 63 int plugin_child_id; |
62 IPC::ChannelHandle channel_handle; | 64 IPC::ChannelHandle channel_handle; |
63 }; | 65 }; |
64 | 66 |
65 typedef std::map<PP_Instance, InstanceInfo> InstanceInfoMap; | 67 typedef std::map<PP_Instance, InstanceInfo> InstanceInfoMap; |
66 | 68 |
67 base::LazyInstance<InstanceInfoMap> g_instance_info = | 69 base::LazyInstance<InstanceInfoMap> g_instance_info = |
68 LAZY_INSTANCE_INITIALIZER; | 70 LAZY_INSTANCE_INITIALIZER; |
69 | 71 |
| 72 typedef std::map<PP_Instance, nacl::TrustedPluginChannel*> |
| 73 InstanceTrustedChannelMap; |
| 74 |
| 75 base::LazyInstance<InstanceTrustedChannelMap> g_channel_map = |
| 76 LAZY_INSTANCE_INITIALIZER; |
| 77 |
70 static int GetRoutingID(PP_Instance instance) { | 78 static int GetRoutingID(PP_Instance instance) { |
71 // Check that we are on the main renderer thread. | 79 // Check that we are on the main renderer thread. |
72 DCHECK(content::RenderThread::Get()); | 80 DCHECK(content::RenderThread::Get()); |
73 content::RendererPpapiHost *host = | 81 content::RendererPpapiHost *host = |
74 content::RendererPpapiHost::GetForPPInstance(instance); | 82 content::RendererPpapiHost::GetForPPInstance(instance); |
75 if (!host) | 83 if (!host) |
76 return 0; | 84 return 0; |
77 return host->GetRoutingIDForWidget(instance); | 85 return host->GetRoutingIDForWidget(instance); |
78 } | 86 } |
79 | 87 |
80 // Launch NaCl's sel_ldr process. | 88 // Launch NaCl's sel_ldr process. |
81 PP_ExternalPluginResult LaunchSelLdr(PP_Instance instance, | 89 void LaunchSelLdr(PP_Instance instance, |
82 const char* alleged_url, | 90 const char* alleged_url, |
83 PP_Bool uses_irt, | 91 PP_Bool uses_irt, |
84 PP_Bool uses_ppapi, | 92 PP_Bool uses_ppapi, |
85 PP_Bool enable_ppapi_dev, | 93 PP_Bool enable_ppapi_dev, |
86 PP_Bool enable_dyncode_syscalls, | 94 PP_Bool enable_dyncode_syscalls, |
87 PP_Bool enable_exception_handling, | 95 PP_Bool enable_exception_handling, |
88 PP_Bool enable_crash_throttling, | 96 PP_Bool enable_crash_throttling, |
89 void* imc_handle, | 97 void* imc_handle, |
90 struct PP_Var* error_message) { | 98 struct PP_Var* error_message, |
| 99 PP_CompletionCallback callback) { |
91 nacl::FileDescriptor result_socket; | 100 nacl::FileDescriptor result_socket; |
92 IPC::Sender* sender = content::RenderThread::Get(); | 101 IPC::Sender* sender = content::RenderThread::Get(); |
93 DCHECK(sender); | 102 DCHECK(sender); |
94 *error_message = PP_MakeUndefined(); | 103 *error_message = PP_MakeUndefined(); |
95 int routing_id = 0; | 104 int routing_id = 0; |
96 // If the nexe uses ppapi APIs, we need a routing ID. | 105 // If the nexe uses ppapi APIs, we need a routing ID. |
97 // To get the routing ID, we must be on the main thread. | 106 // To get the routing ID, we must be on the main thread. |
98 // Some nexes do not use ppapi and launch from the background thread, | 107 // Some nexes do not use ppapi and launch from the background thread, |
99 // so those nexes can skip finding a routing_id. | 108 // so those nexes can skip finding a routing_id. |
100 if (uses_ppapi) { | 109 if (uses_ppapi) { |
101 routing_id = GetRoutingID(instance); | 110 routing_id = GetRoutingID(instance); |
102 if (!routing_id) | 111 if (!routing_id) { |
103 return PP_EXTERNAL_PLUGIN_FAILED; | 112 PP_RunCompletionCallback(&callback, PP_ERROR_FAILED); |
| 113 return; |
| 114 } |
104 } | 115 } |
105 | 116 |
106 InstanceInfo instance_info; | 117 InstanceInfo instance_info; |
107 instance_info.url = GURL(alleged_url); | 118 instance_info.url = GURL(alleged_url); |
108 | 119 |
109 uint32_t perm_bits = ppapi::PERMISSION_NONE; | 120 uint32_t perm_bits = ppapi::PERMISSION_NONE; |
110 // Conditionally block 'Dev' interfaces. We do this for the NaCl process, so | 121 // Conditionally block 'Dev' interfaces. We do this for the NaCl process, so |
111 // it's clearer to developers when they are using 'Dev' inappropriately. We | 122 // it's clearer to developers when they are using 'Dev' inappropriately. We |
112 // must also check on the trusted side of the proxy. | 123 // must also check on the trusted side of the proxy. |
113 if (enable_ppapi_dev) | 124 if (enable_ppapi_dev) |
114 perm_bits |= ppapi::PERMISSION_DEV; | 125 perm_bits |= ppapi::PERMISSION_DEV; |
115 instance_info.permissions = | 126 instance_info.permissions = |
116 ppapi::PpapiPermissions::GetForCommandLine(perm_bits); | 127 ppapi::PpapiPermissions::GetForCommandLine(perm_bits); |
117 std::string error_message_string; | 128 std::string error_message_string; |
118 nacl::NaClLaunchResult launch_result; | 129 nacl::NaClLaunchResult launch_result; |
119 | 130 |
120 if (!sender->Send(new NaClHostMsg_LaunchNaCl( | 131 if (!sender->Send(new NaClHostMsg_LaunchNaCl( |
121 nacl::NaClLaunchParams(instance_info.url.spec(), | 132 nacl::NaClLaunchParams(instance_info.url.spec(), |
122 routing_id, | 133 routing_id, |
123 perm_bits, | 134 perm_bits, |
124 PP_ToBool(uses_irt), | 135 PP_ToBool(uses_irt), |
125 PP_ToBool(enable_dyncode_syscalls), | 136 PP_ToBool(enable_dyncode_syscalls), |
126 PP_ToBool(enable_exception_handling), | 137 PP_ToBool(enable_exception_handling), |
127 PP_ToBool(enable_crash_throttling)), | 138 PP_ToBool(enable_crash_throttling)), |
128 &launch_result, | 139 &launch_result, |
129 &error_message_string))) { | 140 &error_message_string))) { |
130 return PP_EXTERNAL_PLUGIN_FAILED; | 141 PP_RunCompletionCallback(&callback, PP_ERROR_FAILED); |
| 142 return; |
131 } | 143 } |
132 if (!error_message_string.empty()) { | 144 if (!error_message_string.empty()) { |
133 *error_message = ppapi::StringVar::StringToPPVar(error_message_string); | 145 *error_message = ppapi::StringVar::StringToPPVar(error_message_string); |
134 return PP_EXTERNAL_PLUGIN_FAILED; | 146 PP_RunCompletionCallback(&callback, PP_ERROR_FAILED); |
| 147 return; |
135 } | 148 } |
136 result_socket = launch_result.imc_channel_handle; | 149 result_socket = launch_result.imc_channel_handle; |
137 instance_info.channel_handle = launch_result.ipc_channel_handle; | 150 instance_info.channel_handle = launch_result.untrusted_ipc_channel_handle; |
138 instance_info.plugin_pid = launch_result.plugin_pid; | 151 instance_info.plugin_pid = launch_result.plugin_pid; |
139 instance_info.plugin_child_id = launch_result.plugin_child_id; | 152 instance_info.plugin_child_id = launch_result.plugin_child_id; |
140 // Don't save instance_info if channel handle is invalid. | 153 // Don't save instance_info if channel handle is invalid. |
141 bool invalid_handle = instance_info.channel_handle.name.empty(); | 154 bool invalid_handle = instance_info.channel_handle.name.empty(); |
142 #if defined(OS_POSIX) | 155 #if defined(OS_POSIX) |
143 if (!invalid_handle) | 156 if (!invalid_handle) |
144 invalid_handle = (instance_info.channel_handle.socket.fd == -1); | 157 invalid_handle = (instance_info.channel_handle.socket.fd == -1); |
145 #endif | 158 #endif |
146 if (!invalid_handle) | 159 if (!invalid_handle) |
147 g_instance_info.Get()[instance] = instance_info; | 160 g_instance_info.Get()[instance] = instance_info; |
148 | 161 |
149 *(static_cast<NaClHandle*>(imc_handle)) = | 162 // Stash the trusted handle as well. |
150 nacl::ToNativeHandle(result_socket); | 163 invalid_handle = launch_result.trusted_ipc_channel_handle.name.empty(); |
| 164 #if defined(OS_POSIX) |
| 165 if (!invalid_handle) |
| 166 invalid_handle = (launch_result.trusted_ipc_channel_handle.socket.fd == -1); |
| 167 #endif |
151 | 168 |
152 return PP_EXTERNAL_PLUGIN_OK; | 169 if (!invalid_handle) { |
| 170 g_channel_map.Get()[instance] = new nacl::TrustedPluginChannel( |
| 171 launch_result.trusted_ipc_channel_handle, callback); |
| 172 *(static_cast<NaClHandle*>(imc_handle)) = |
| 173 nacl::ToNativeHandle(result_socket); |
| 174 } else { |
| 175 PP_RunCompletionCallback(&callback, PP_ERROR_FAILED); |
| 176 } |
153 } | 177 } |
154 | 178 |
155 PP_ExternalPluginResult StartPpapiProxy(PP_Instance instance) { | 179 PP_ExternalPluginResult StartPpapiProxy(PP_Instance instance) { |
156 InstanceInfoMap& map = g_instance_info.Get(); | 180 InstanceInfoMap& map = g_instance_info.Get(); |
157 InstanceInfoMap::iterator it = map.find(instance); | 181 InstanceInfoMap::iterator it = map.find(instance); |
158 if (it == map.end()) { | 182 if (it == map.end()) { |
159 DLOG(ERROR) << "Could not find instance ID"; | 183 DLOG(ERROR) << "Could not find instance ID"; |
160 return PP_EXTERNAL_PLUGIN_FAILED; | 184 return PP_EXTERNAL_PLUGIN_FAILED; |
161 } | 185 } |
162 InstanceInfo instance_info = it->second; | 186 InstanceInfo instance_info = it->second; |
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
402 } | 426 } |
403 | 427 |
404 void SetReadOnlyProperty(PP_Instance instance, | 428 void SetReadOnlyProperty(PP_Instance instance, |
405 struct PP_Var key, | 429 struct PP_Var key, |
406 struct PP_Var value) { | 430 struct PP_Var value) { |
407 content::PepperPluginInstance* plugin_instance = | 431 content::PepperPluginInstance* plugin_instance = |
408 content::PepperPluginInstance::Get(instance); | 432 content::PepperPluginInstance::Get(instance); |
409 plugin_instance->SetEmbedProperty(key, value); | 433 plugin_instance->SetEmbedProperty(key, value); |
410 } | 434 } |
411 | 435 |
| 436 PP_Bool LoadModule(PP_Instance instance, PP_FileHandle handle, |
| 437 uint32_t *nacl_error_code) { |
| 438 fprintf(stderr, "PPB_NaCl_Private LoadModule()\n"); |
| 439 // We can't use PepperPluginInstance here because it doesn't have sufficient |
| 440 // DEPS to see the NaClProcessMsg_LoadModule message. Therefore, we must do |
| 441 // our own accounting and keep a channel map here. |
| 442 |
| 443 InstanceTrustedChannelMap::iterator it = g_channel_map.Get().find(instance); |
| 444 if (it == g_channel_map.Get().end()) { |
| 445 NOTREACHED(); |
| 446 return PP_FALSE; |
| 447 } |
| 448 nacl::TrustedPluginChannel* channel = it->second; |
| 449 IPC::PlatformFileForTransit platform_file_for_transit; |
| 450 #if defined(OS_WIN) |
| 451 platform_file_for_transit = handle; |
| 452 #elif defined(OS_POSIX) |
| 453 platform_file_for_transit = base::FileDescriptor(handle, false); |
| 454 #endif |
| 455 fprintf(stderr, "sending NaClProcessMsg_LoadModule\n"); |
| 456 NaClErrorCode code; |
| 457 bool ok = channel->Send( |
| 458 new NaClProcessMsg_LoadModule(platform_file_for_transit, |
| 459 &code)); |
| 460 *nacl_error_code = code; |
| 461 fprintf(stderr, "sent NaClProcessMsg_LoadModule\n"); |
| 462 return PP_FromBool(ok); |
| 463 } |
| 464 |
| 465 PP_Bool StartModule(PP_Instance instance) { |
| 466 InstanceTrustedChannelMap::iterator it = g_channel_map.Get().find(instance); |
| 467 if (it == g_channel_map.Get().end()) { |
| 468 NOTREACHED(); |
| 469 return PP_FALSE; |
| 470 } |
| 471 nacl::TrustedPluginChannel* channel = it->second; |
| 472 fprintf(stderr, "sending NaClProcessMsg_StartModule\n"); |
| 473 bool ok = channel->Send(new NaClProcessMsg_StartModule()); |
| 474 fprintf(stderr, "sent NaClProcessMsg_StartModule\n"); |
| 475 return PP_FromBool(ok); |
| 476 } |
| 477 |
412 const PPB_NaCl_Private nacl_interface = { | 478 const PPB_NaCl_Private nacl_interface = { |
413 &LaunchSelLdr, | 479 &LaunchSelLdr, |
414 &StartPpapiProxy, | 480 &StartPpapiProxy, |
415 &UrandomFD, | 481 &UrandomFD, |
416 &Are3DInterfacesDisabled, | 482 &Are3DInterfacesDisabled, |
417 &BrokerDuplicateHandle, | 483 &BrokerDuplicateHandle, |
418 &GetReadonlyPnaclFD, | 484 &GetReadonlyPnaclFD, |
419 &CreateTemporaryFile, | 485 &CreateTemporaryFile, |
420 &GetNexeFd, | 486 &GetNexeFd, |
421 &ReportTranslationFinished, | 487 &ReportTranslationFinished, |
422 &ReportNaClError, | 488 &ReportNaClError, |
423 &OpenNaClExecutable, | 489 &OpenNaClExecutable, |
424 &DispatchEvent, | 490 &DispatchEvent, |
425 &SetReadOnlyProperty | 491 &SetReadOnlyProperty, |
| 492 &LoadModule, |
| 493 &StartModule |
426 }; | 494 }; |
427 | 495 |
428 } // namespace | 496 } // namespace |
429 | 497 |
430 namespace nacl { | 498 namespace nacl { |
431 | 499 |
432 const PPB_NaCl_Private* GetNaClPrivateInterface() { | 500 const PPB_NaCl_Private* GetNaClPrivateInterface() { |
433 return &nacl_interface; | 501 return &nacl_interface; |
434 } | 502 } |
435 | 503 |
436 } // namespace nacl | 504 } // namespace nacl |
437 | 505 |
438 #endif // DISABLE_NACL | 506 #endif // DISABLE_NACL |
OLD | NEW |