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 #include <numeric> | 7 #include <numeric> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
294 DCHECK(pp_process_type > PP_UNKNOWN_NACL_PROCESS_TYPE && | 294 DCHECK(pp_process_type > PP_UNKNOWN_NACL_PROCESS_TYPE && |
295 pp_process_type < PP_NUM_NACL_PROCESS_TYPES); | 295 pp_process_type < PP_NUM_NACL_PROCESS_TYPES); |
296 return static_cast<NaClAppProcessType>(pp_process_type); | 296 return static_cast<NaClAppProcessType>(pp_process_type); |
297 } | 297 } |
298 | 298 |
299 // Launch NaCl's sel_ldr process. | 299 // Launch NaCl's sel_ldr process. |
300 void LaunchSelLdr(PP_Instance instance, | 300 void LaunchSelLdr(PP_Instance instance, |
301 PP_Bool main_service_runtime, | 301 PP_Bool main_service_runtime, |
302 const char* alleged_url, | 302 const char* alleged_url, |
303 const PP_NaClFileInfo* nexe_file_info, | 303 const PP_NaClFileInfo* nexe_file_info, |
304 const PP_NaClResourceFileHandle* resource_file_handles, | |
304 PP_Bool uses_nonsfi_mode, | 305 PP_Bool uses_nonsfi_mode, |
305 PP_Bool enable_ppapi_dev, | 306 PP_Bool enable_ppapi_dev, |
306 PP_NaClAppProcessType pp_process_type, | 307 PP_NaClAppProcessType pp_process_type, |
307 void* imc_handle, | 308 void* imc_handle, |
308 PP_CompletionCallback callback) { | 309 PP_CompletionCallback callback) { |
309 CHECK(ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()-> | 310 CHECK(ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()-> |
310 BelongsToCurrentThread()); | 311 BelongsToCurrentThread()); |
311 NaClAppProcessType process_type = PP_ToNaClAppProcessType(pp_process_type); | 312 NaClAppProcessType process_type = PP_ToNaClAppProcessType(pp_process_type); |
312 // Create the manifest service proxy here, so on error case, it will be | 313 // Create the manifest service proxy here, so on error case, it will be |
313 // destructed (without passing it to ManifestServiceChannel). | 314 // destructed (without passing it to ManifestServiceChannel). |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
347 // must also check on the trusted side of the proxy. | 348 // must also check on the trusted side of the proxy. |
348 if (enable_ppapi_dev) | 349 if (enable_ppapi_dev) |
349 perm_bits |= ppapi::PERMISSION_DEV; | 350 perm_bits |= ppapi::PERMISSION_DEV; |
350 instance_info.permissions = | 351 instance_info.permissions = |
351 ppapi::PpapiPermissions::GetForCommandLine(perm_bits); | 352 ppapi::PpapiPermissions::GetForCommandLine(perm_bits); |
352 std::string error_message_string; | 353 std::string error_message_string; |
353 NaClLaunchResult launch_result; | 354 NaClLaunchResult launch_result; |
354 | 355 |
355 IPC::PlatformFileForTransit nexe_for_transit = | 356 IPC::PlatformFileForTransit nexe_for_transit = |
356 IPC::InvalidPlatformFileForTransit(); | 357 IPC::InvalidPlatformFileForTransit(); |
358 std::vector<IPC::PlatformFileForTransit> resource_files_for_transit; | |
359 std::vector<std::pair<uint64, uint64> > resource_file_tokens; | |
360 std::vector<std::string> resource_keys; | |
357 #if defined(OS_POSIX) | 361 #if defined(OS_POSIX) |
358 if (nexe_file_info->handle != PP_kInvalidFileHandle) | 362 if (nexe_file_info->handle != PP_kInvalidFileHandle) |
359 nexe_for_transit = base::FileDescriptor(nexe_file_info->handle, true); | 363 nexe_for_transit = base::FileDescriptor(nexe_file_info->handle, true); |
364 for (size_t i = 0; | |
365 resource_file_handles && | |
366 (resource_file_handles[i].handle != PP_kInvalidFileHandle); | |
367 ++i) { | |
368 resource_files_for_transit.push_back( | |
369 base::FileDescriptor(resource_file_handles[i].handle, true)); | |
370 resource_file_tokens.push_back( | |
371 std::make_pair(resource_file_handles[i].token_lo, | |
372 resource_file_handles[i].token_hi)); | |
373 resource_keys.push_back(resource_file_handles[i].key); | |
374 } | |
360 #elif defined(OS_WIN) | 375 #elif defined(OS_WIN) |
361 // Duplicate the handle on the browser side instead of the renderer. | 376 // Duplicate the handle on the browser side instead of the renderer. |
362 // This is because BrokerGetFileForProcess isn't part of content/public, and | 377 // This is because BrokerGetFileForProcess isn't part of content/public, and |
363 // it's simpler to do the duplication in the browser anyway. | 378 // it's simpler to do the duplication in the browser anyway. |
364 nexe_for_transit = nexe_file_info->handle; | 379 nexe_for_transit = nexe_file_info->handle; |
380 // TODO(yusukes): Support pre-opening resource files. | |
381 CHECK(resource_file_handles == NULL); | |
365 #else | 382 #else |
366 #error Unsupported target platform. | 383 #error Unsupported target platform. |
367 #endif | 384 #endif |
368 if (!sender->Send(new NaClHostMsg_LaunchNaCl( | 385 if (!sender->Send(new NaClHostMsg_LaunchNaCl( |
369 NaClLaunchParams( | 386 NaClLaunchParams( |
370 instance_info.url.spec(), | 387 instance_info.url.spec(), |
371 nexe_for_transit, | 388 nexe_for_transit, |
372 nexe_file_info->token_lo, | 389 nexe_file_info->token_lo, |
373 nexe_file_info->token_hi, | 390 nexe_file_info->token_hi, |
391 resource_files_for_transit, | |
392 resource_file_tokens, | |
393 resource_keys, | |
374 routing_id, | 394 routing_id, |
375 perm_bits, | 395 perm_bits, |
376 PP_ToBool(uses_nonsfi_mode), | 396 PP_ToBool(uses_nonsfi_mode), |
377 process_type), | 397 process_type), |
378 &launch_result, | 398 &launch_result, |
379 &error_message_string))) { | 399 &error_message_string))) { |
380 ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask( | 400 ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask( |
381 FROM_HERE, | 401 FROM_HERE, |
382 base::Bind(callback.func, callback.user_data, | 402 base::Bind(callback.func, callback.user_data, |
383 static_cast<int32_t>(PP_ERROR_FAILED))); | 403 static_cast<int32_t>(PP_ERROR_FAILED))); |
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
674 } | 694 } |
675 } | 695 } |
676 | 696 |
677 // If the resource host isn't initialized, don't try to do that here. | 697 // If the resource host isn't initialized, don't try to do that here. |
678 // Just return because something is already very wrong. | 698 // Just return because something is already very wrong. |
679 if (g_pnacl_resource_host.Get().get() == NULL) | 699 if (g_pnacl_resource_host.Get().get() == NULL) |
680 return; | 700 return; |
681 g_pnacl_resource_host.Get()->ReportTranslationFinished(instance, success); | 701 g_pnacl_resource_host.Get()->ReportTranslationFinished(instance, success); |
682 } | 702 } |
683 | 703 |
684 PP_FileHandle OpenNaClExecutable(PP_Instance instance, | 704 PP_FileHandle OpenNaClExecutable( |
teravest
2014/10/24 16:18:06
OpenNaClExecutable should probably be renamed to O
Yusuke Sato
2014/11/04 22:50:22
Done.
| |
685 const char* file_url, | 705 PP_Instance instance, |
686 uint64_t* nonce_lo, | 706 const char* file_url, |
687 uint64_t* nonce_hi) { | 707 uint64_t* nonce_lo, |
708 uint64_t* nonce_hi, | |
709 const std::vector<std::string>& resource_file_urls, | |
710 PP_NaClResourceFileHandle** out_resource_file_handles) { | |
688 // Fast path only works for installed file URLs. | 711 // Fast path only works for installed file URLs. |
689 GURL gurl(file_url); | 712 GURL gurl(file_url); |
690 if (!gurl.SchemeIs("chrome-extension")) | 713 if (!gurl.SchemeIs("chrome-extension")) |
691 return PP_kInvalidFileHandle; | 714 return PP_kInvalidFileHandle; |
692 | 715 |
693 content::PepperPluginInstance* plugin_instance = | 716 content::PepperPluginInstance* plugin_instance = |
694 content::PepperPluginInstance::Get(instance); | 717 content::PepperPluginInstance::Get(instance); |
695 if (!plugin_instance) | 718 if (!plugin_instance) |
696 return PP_kInvalidFileHandle; | 719 return PP_kInvalidFileHandle; |
697 // IMPORTANT: Make sure the document can request the given URL. If we don't | 720 // IMPORTANT: Make sure the document can request the given URL. If we don't |
698 // check, a malicious app could probe the extension system. This enforces a | 721 // check, a malicious app could probe the extension system. This enforces a |
699 // same-origin policy which prevents the app from requesting resources from | 722 // same-origin policy which prevents the app from requesting resources from |
700 // another app. | 723 // another app. |
701 blink::WebSecurityOrigin security_origin = | 724 blink::WebSecurityOrigin security_origin = |
702 plugin_instance->GetContainer()->element().document().securityOrigin(); | 725 plugin_instance->GetContainer()->element().document().securityOrigin(); |
703 if (!security_origin.canRequest(gurl)) | 726 if (!security_origin.canRequest(gurl)) |
704 return PP_kInvalidFileHandle; | 727 return PP_kInvalidFileHandle; |
705 | 728 |
706 IPC::PlatformFileForTransit out_fd = IPC::InvalidPlatformFileForTransit(); | 729 IPC::PlatformFileForTransit out_fd = IPC::InvalidPlatformFileForTransit(); |
707 IPC::Sender* sender = content::RenderThread::Get(); | 730 IPC::Sender* sender = content::RenderThread::Get(); |
708 DCHECK(sender); | 731 DCHECK(sender); |
709 *nonce_lo = 0; | 732 *nonce_lo = 0; |
710 *nonce_hi = 0; | 733 *nonce_hi = 0; |
711 base::FilePath file_path; | 734 base::FilePath file_path; |
712 if (!sender->Send( | 735 |
713 new NaClHostMsg_OpenNaClExecutable(GetRoutingID(instance), | 736 std::vector<GURL> resource_urls; |
714 GURL(file_url), | 737 for (size_t i = 0; i < resource_file_urls.size(); ++i) { |
715 &out_fd, | 738 GURL gurl(resource_file_urls[i]); |
716 nonce_lo, | 739 if (!gurl.SchemeIs("chrome-extension")) |
717 nonce_hi))) { | 740 return PP_kInvalidFileHandle; |
741 if (!security_origin.canRequest(gurl)) | |
742 return PP_kInvalidFileHandle; | |
743 resource_urls.push_back(gurl); | |
744 } | |
745 | |
746 nacl::NaClOpenExecutableResult open_result; | |
747 if (!sender->Send(new NaClHostMsg_OpenNaClExecutable(GetRoutingID(instance), | |
748 GURL(file_url), | |
749 resource_urls, | |
750 &open_result))) { | |
718 return PP_kInvalidFileHandle; | 751 return PP_kInvalidFileHandle; |
719 } | 752 } |
720 | 753 |
721 if (out_fd == IPC::InvalidPlatformFileForTransit()) | 754 if (open_result.file == IPC::InvalidPlatformFileForTransit()) |
722 return PP_kInvalidFileHandle; | 755 return PP_kInvalidFileHandle; |
723 | 756 |
757 for (size_t i = 0; i < open_result.resource_files.size(); ++i) { | |
758 if (open_result.resource_files[i] == IPC::InvalidPlatformFileForTransit()) | |
759 return PP_kInvalidFileHandle; | |
teravest
2014/10/24 16:18:06
There should at least be some debug logging added
Yusuke Sato
2014/11/04 22:50:22
Done.
| |
760 } | |
761 CHECK(open_result.resource_files.size() == | |
762 open_result.resource_file_tokens.size()); | |
763 | |
764 out_fd = open_result.file; | |
765 *nonce_lo = open_result.file_token_lo; | |
766 *nonce_lo = open_result.file_token_hi; | |
teravest
2014/10/24 16:18:06
Shouldn't this be nonce_hi? Is the behavior for fi
Yusuke Sato
2014/11/04 22:50:22
Good catch. Fixed. This will be used in the next C
| |
767 | |
768 if (out_resource_file_handles && !open_result.resource_files.empty()) { | |
769 *out_resource_file_handles = | |
770 new PP_NaClResourceFileHandle[open_result.resource_files.size() + 1]; | |
771 for (size_t i = 0; i < open_result.resource_files.size(); ++i) { | |
772 PP_NaClResourceFileHandle& entry = (*out_resource_file_handles)[i]; | |
773 entry.handle = IPC::PlatformFileForTransitToPlatformFile( | |
774 open_result.resource_files[i]); | |
775 entry.token_lo = open_result.resource_file_tokens[i].first; | |
776 entry.token_hi = open_result.resource_file_tokens[i].second; | |
777 entry.key = NULL; // DownloadNexe fills this later. | |
778 } | |
779 PP_NaClResourceFileHandle& sentinel = | |
780 (*out_resource_file_handles)[open_result.resource_files.size()]; | |
teravest
2014/10/24 16:18:06
So, out_resource_file_handles is always guaranteed
Yusuke Sato
2014/11/04 22:50:22
Done.
| |
781 sentinel.handle = PP_kInvalidFileHandle; | |
782 sentinel.token_lo = 0; | |
783 sentinel.token_hi = 0; | |
784 sentinel.key = NULL; | |
785 } | |
786 | |
724 return IPC::PlatformFileForTransitToPlatformFile(out_fd); | 787 return IPC::PlatformFileForTransitToPlatformFile(out_fd); |
725 } | 788 } |
726 | 789 |
727 void DispatchEvent(PP_Instance instance, | 790 void DispatchEvent(PP_Instance instance, |
728 PP_NaClEventType event_type, | 791 PP_NaClEventType event_type, |
729 const char *resource_url, | 792 const char *resource_url, |
730 PP_Bool length_is_computable, | 793 PP_Bool length_is_computable, |
731 uint64_t loaded_bytes, | 794 uint64_t loaded_bytes, |
732 uint64_t total_bytes) { | 795 uint64_t total_bytes) { |
733 ProgressEvent event(event_type, | 796 ProgressEvent event(event_type, |
(...skipping 473 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1207 }; | 1270 }; |
1208 | 1271 |
1209 void DownloadNexeCompletion(const DownloadNexeRequest& request, | 1272 void DownloadNexeCompletion(const DownloadNexeRequest& request, |
1210 PP_NaClFileInfo* out_file_info, | 1273 PP_NaClFileInfo* out_file_info, |
1211 FileDownloader::Status status, | 1274 FileDownloader::Status status, |
1212 base::File target_file, | 1275 base::File target_file, |
1213 int http_status); | 1276 int http_status); |
1214 | 1277 |
1215 void DownloadNexe(PP_Instance instance, | 1278 void DownloadNexe(PP_Instance instance, |
1216 const char* url, | 1279 const char* url, |
1280 PP_Bool download_resource_files, | |
1217 PP_NaClFileInfo* out_file_info, | 1281 PP_NaClFileInfo* out_file_info, |
1282 PP_NaClResourceFileHandle** out_resource_file_handles, | |
1218 PP_CompletionCallback callback) { | 1283 PP_CompletionCallback callback) { |
1219 CHECK(url); | 1284 CHECK(url); |
1220 CHECK(out_file_info); | 1285 CHECK(out_file_info); |
1286 CHECK(!download_resource_files || out_resource_file_handles); | |
1287 | |
1221 DownloadNexeRequest request; | 1288 DownloadNexeRequest request; |
1222 request.instance = instance; | 1289 request.instance = instance; |
1223 request.url = url; | 1290 request.url = url; |
1224 request.callback = callback; | 1291 request.callback = callback; |
1225 request.start_time = base::Time::Now(); | 1292 request.start_time = base::Time::Now(); |
1226 | 1293 |
1294 std::vector<std::string> resource_file_urls; | |
1295 std::vector<std::string> resource_file_keys; | |
1296 if (download_resource_files) { | |
1297 JsonManifest* manifest = GetJsonManifest(instance); | |
1298 if (manifest) | |
1299 manifest->GetFilesUrl(&resource_file_urls, &resource_file_keys); | |
1300 CHECK(resource_file_urls.size() == resource_file_keys.size()); | |
1301 | |
1302 // TODO(yusukes): Increase kMaxDescriptorsPerMessage in | |
1303 // ipc/file_descriptor_set_posix.h, NACL_ABI_IMC_USER_DESC_MAX in | |
1304 // native_client/src/public/imc_types.h, and NACL_HANDLE_COUNT_MAX in | |
1305 // native_client/src/shared/imc/nacl_imc_c.h, and remove the resize() | |
1306 // calls. | |
1307 if (resource_file_urls.size() > 2) { | |
teravest
2014/10/24 16:18:06
So what happens if more than two resource file url
Yusuke Sato
2014/11/04 22:50:22
Yes.
Yusuke Sato
2014/11/05 07:03:23
It turned out that removing the restriction does n
| |
1308 resource_file_urls.resize(2); | |
1309 resource_file_keys.resize(2); | |
1310 } | |
1311 } | |
1312 | |
1227 // Try the fast path for retrieving the file first. | 1313 // Try the fast path for retrieving the file first. |
1228 PP_FileHandle handle = OpenNaClExecutable(instance, | 1314 PP_FileHandle handle = OpenNaClExecutable(instance, |
1229 url, | 1315 url, |
1230 &out_file_info->token_lo, | 1316 &out_file_info->token_lo, |
1231 &out_file_info->token_hi); | 1317 &out_file_info->token_hi, |
1318 resource_file_urls, | |
1319 out_resource_file_handles); | |
1232 if (handle != PP_kInvalidFileHandle) { | 1320 if (handle != PP_kInvalidFileHandle) { |
1321 if (!resource_file_urls.empty()) { | |
1322 for (size_t i = 0; i < resource_file_urls.size(); ++i) { | |
1323 PP_NaClResourceFileHandle& entry = (*out_resource_file_handles)[i]; | |
1324 CHECK(entry.handle != PP_kInvalidFileHandle) << i; | |
1325 entry.key = strdup(resource_file_keys[i].c_str()); | |
1326 } | |
1327 } | |
1233 DownloadNexeCompletion(request, | 1328 DownloadNexeCompletion(request, |
1234 out_file_info, | 1329 out_file_info, |
1235 FileDownloader::SUCCESS, | 1330 FileDownloader::SUCCESS, |
1236 base::File(handle), | 1331 base::File(handle), |
1237 200); | 1332 200); |
1238 return; | 1333 return; |
1239 } | 1334 } |
1240 | 1335 |
1241 // The fast path didn't work, we'll fetch the file using URLLoader and write | 1336 // The fast path didn't work, we'll fetch the file using URLLoader and write |
1242 // it to local storage. | 1337 // it to local storage. |
1243 base::File target_file(CreateTemporaryFile(instance)); | 1338 base::File target_file(CreateTemporaryFile(instance)); |
1244 GURL gurl(url); | 1339 GURL gurl(url); |
1245 | 1340 |
1341 // On the slow path, do not retry to pre-open the resource files. | |
1342 if (out_resource_file_handles) | |
1343 *out_resource_file_handles = NULL; | |
1344 | |
1246 content::PepperPluginInstance* plugin_instance = | 1345 content::PepperPluginInstance* plugin_instance = |
1247 content::PepperPluginInstance::Get(instance); | 1346 content::PepperPluginInstance::Get(instance); |
1248 if (!plugin_instance) { | 1347 if (!plugin_instance) { |
1249 ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask( | 1348 ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask( |
1250 FROM_HERE, | 1349 FROM_HERE, |
1251 base::Bind(callback.func, callback.user_data, | 1350 base::Bind(callback.func, callback.user_data, |
1252 static_cast<int32_t>(PP_ERROR_FAILED))); | 1351 static_cast<int32_t>(PP_ERROR_FAILED))); |
1253 } | 1352 } |
1254 const blink::WebDocument& document = | 1353 const blink::WebDocument& document = |
1255 plugin_instance->GetContainer()->element().document(); | 1354 plugin_instance->GetContainer()->element().document(); |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1376 kInvalidNaClFileInfo)); | 1475 kInvalidNaClFileInfo)); |
1377 return; | 1476 return; |
1378 } | 1477 } |
1379 | 1478 |
1380 // Try the fast path for retrieving the file first. | 1479 // Try the fast path for retrieving the file first. |
1381 uint64_t file_token_lo = 0; | 1480 uint64_t file_token_lo = 0; |
1382 uint64_t file_token_hi = 0; | 1481 uint64_t file_token_hi = 0; |
1383 PP_FileHandle file_handle = OpenNaClExecutable(instance, | 1482 PP_FileHandle file_handle = OpenNaClExecutable(instance, |
1384 url.c_str(), | 1483 url.c_str(), |
1385 &file_token_lo, | 1484 &file_token_lo, |
1386 &file_token_hi); | 1485 &file_token_hi, |
1486 std::vector<std::string>(), | |
1487 NULL); | |
1387 if (file_handle != PP_kInvalidFileHandle) { | 1488 if (file_handle != PP_kInvalidFileHandle) { |
1388 PP_NaClFileInfo file_info; | 1489 PP_NaClFileInfo file_info; |
1389 file_info.handle = file_handle; | 1490 file_info.handle = file_handle; |
1390 file_info.token_lo = file_token_lo; | 1491 file_info.token_lo = file_token_lo; |
1391 file_info.token_hi = file_token_hi; | 1492 file_info.token_hi = file_token_hi; |
1392 base::MessageLoop::current()->PostTask( | 1493 base::MessageLoop::current()->PostTask( |
1393 FROM_HERE, | 1494 FROM_HERE, |
1394 base::Bind(callback, static_cast<int32_t>(PP_OK), file_info)); | 1495 base::Bind(callback, static_cast<int32_t>(PP_OK), file_info)); |
1395 return; | 1496 return; |
1396 } | 1497 } |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1698 &StreamPexe | 1799 &StreamPexe |
1699 }; | 1800 }; |
1700 | 1801 |
1701 } // namespace | 1802 } // namespace |
1702 | 1803 |
1703 const PPB_NaCl_Private* GetNaClPrivateInterface() { | 1804 const PPB_NaCl_Private* GetNaClPrivateInterface() { |
1704 return &nacl_interface; | 1805 return &nacl_interface; |
1705 } | 1806 } |
1706 | 1807 |
1707 } // namespace nacl | 1808 } // namespace nacl |
OLD | NEW |