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 |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/bind_helpers.h" | 12 #include "base/bind_helpers.h" |
13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
14 #include "base/containers/scoped_ptr_hash_map.h" | 14 #include "base/containers/scoped_ptr_hash_map.h" |
15 #include "base/cpu.h" | 15 #include "base/cpu.h" |
16 #include "base/files/file.h" | 16 #include "base/files/file.h" |
17 #include "base/lazy_instance.h" | 17 #include "base/lazy_instance.h" |
18 #include "base/logging.h" | 18 #include "base/logging.h" |
19 #include "base/macros.h" | |
19 #include "base/rand_util.h" | 20 #include "base/rand_util.h" |
20 #include "base/strings/string_split.h" | 21 #include "base/strings/string_split.h" |
21 #include "base/strings/string_util.h" | 22 #include "base/strings/string_util.h" |
22 #include "components/nacl/common/nacl_host_messages.h" | 23 #include "components/nacl/common/nacl_host_messages.h" |
23 #include "components/nacl/common/nacl_messages.h" | 24 #include "components/nacl/common/nacl_messages.h" |
24 #include "components/nacl/common/nacl_nonsfi_util.h" | 25 #include "components/nacl/common/nacl_nonsfi_util.h" |
25 #include "components/nacl/common/nacl_switches.h" | 26 #include "components/nacl/common/nacl_switches.h" |
26 #include "components/nacl/common/nacl_types.h" | 27 #include "components/nacl/common/nacl_types.h" |
27 #include "components/nacl/renderer/file_downloader.h" | 28 #include "components/nacl/renderer/file_downloader.h" |
28 #include "components/nacl/renderer/histogram.h" | 29 #include "components/nacl/renderer/histogram.h" |
29 #include "components/nacl/renderer/json_manifest.h" | 30 #include "components/nacl/renderer/json_manifest.h" |
30 #include "components/nacl/renderer/manifest_downloader.h" | 31 #include "components/nacl/renderer/manifest_downloader.h" |
31 #include "components/nacl/renderer/manifest_service_channel.h" | 32 #include "components/nacl/renderer/manifest_service_channel.h" |
32 #include "components/nacl/renderer/nexe_load_manager.h" | 33 #include "components/nacl/renderer/nexe_load_manager.h" |
33 #include "components/nacl/renderer/platform_info.h" | 34 #include "components/nacl/renderer/platform_info.h" |
34 #include "components/nacl/renderer/pnacl_translation_resource_host.h" | 35 #include "components/nacl/renderer/pnacl_translation_resource_host.h" |
35 #include "components/nacl/renderer/progress_event.h" | 36 #include "components/nacl/renderer/progress_event.h" |
36 #include "components/nacl/renderer/trusted_plugin_channel.h" | 37 #include "components/nacl/renderer/trusted_plugin_channel.h" |
37 #include "content/public/common/content_client.h" | 38 #include "content/public/common/content_client.h" |
38 #include "content/public/common/content_switches.h" | 39 #include "content/public/common/content_switches.h" |
39 #include "content/public/common/sandbox_init.h" | 40 #include "content/public/common/sandbox_init.h" |
40 #include "content/public/renderer/pepper_plugin_instance.h" | 41 #include "content/public/renderer/pepper_plugin_instance.h" |
41 #include "content/public/renderer/render_thread.h" | 42 #include "content/public/renderer/render_thread.h" |
42 #include "content/public/renderer/render_view.h" | 43 #include "content/public/renderer/render_view.h" |
43 #include "content/public/renderer/renderer_ppapi_host.h" | 44 #include "content/public/renderer/renderer_ppapi_host.h" |
45 #include "ipc/ipc_message_attachment_set.h" | |
44 #include "native_client/src/public/imc_types.h" | 46 #include "native_client/src/public/imc_types.h" |
45 #include "net/base/data_url.h" | 47 #include "net/base/data_url.h" |
46 #include "net/base/net_errors.h" | 48 #include "net/base/net_errors.h" |
47 #include "net/http/http_util.h" | 49 #include "net/http/http_util.h" |
48 #include "ppapi/c/pp_bool.h" | 50 #include "ppapi/c/pp_bool.h" |
49 #include "ppapi/c/private/pp_file_handle.h" | 51 #include "ppapi/c/private/pp_file_handle.h" |
50 #include "ppapi/shared_impl/ppapi_globals.h" | 52 #include "ppapi/shared_impl/ppapi_globals.h" |
51 #include "ppapi/shared_impl/ppapi_permissions.h" | 53 #include "ppapi/shared_impl/ppapi_permissions.h" |
52 #include "ppapi/shared_impl/ppapi_preferences.h" | 54 #include "ppapi/shared_impl/ppapi_preferences.h" |
53 #include "ppapi/shared_impl/var.h" | 55 #include "ppapi/shared_impl/var.h" |
(...skipping 12 matching lines...) Expand all Loading... | |
66 | 68 |
67 namespace nacl { | 69 namespace nacl { |
68 namespace { | 70 namespace { |
69 | 71 |
70 // The pseudo-architecture used to indicate portable native client. | 72 // The pseudo-architecture used to indicate portable native client. |
71 const char* const kPortableArch = "portable"; | 73 const char* const kPortableArch = "portable"; |
72 | 74 |
73 // The base URL for resources used by the PNaCl translator processes. | 75 // The base URL for resources used by the PNaCl translator processes. |
74 const char* kPNaClTranslatorBaseUrl = "chrome://pnacl-translator/"; | 76 const char* kPNaClTranslatorBaseUrl = "chrome://pnacl-translator/"; |
75 | 77 |
78 // The maximum number of resource files DownloadNexe() can open. | |
79 const size_t kMaxPreOpenResourceFiles = 2; | |
Mark Seaborn
2015/02/12 03:57:34
How about adding a TODO to increase this, to docum
Yusuke Sato
2015/02/13 23:01:17
Done. Moved to nacl_host_message_filter.cc.
| |
80 | |
81 #if defined(OS_POSIX) | |
82 // On POSIX platforms, the maximum number of files a process can pass to | |
83 // another is limited to kMaxDescriptorsPerMessage. Since the browser process | |
84 // may use up to 5 descriptors for passing non-resource files when creating | |
85 // the NaCl plugin process, kMaxPreOpenResourceFiles must be smaller than or | |
86 // equal to (IPC::MessageAttachmentSet::kMaxDescriptorsPerMessage - 5). | |
87 COMPILE_ASSERT(kMaxPreOpenResourceFiles <= | |
Mark Seaborn
2015/02/12 03:57:34
What would happen if we didn't have this check?
I
Yusuke Sato
2015/02/13 23:01:17
Ok, dropped.
| |
88 IPC::MessageAttachmentSet::kMaxDescriptorsPerMessage - 5, | |
89 k_max_pre_open_resource_files_too_large); | |
90 #endif | |
91 | |
76 base::LazyInstance<scoped_refptr<PnaclTranslationResourceHost> > | 92 base::LazyInstance<scoped_refptr<PnaclTranslationResourceHost> > |
77 g_pnacl_resource_host = LAZY_INSTANCE_INITIALIZER; | 93 g_pnacl_resource_host = LAZY_INSTANCE_INITIALIZER; |
78 | 94 |
79 bool InitializePnaclResourceHost() { | 95 bool InitializePnaclResourceHost() { |
80 // Must run on the main thread. | 96 // Must run on the main thread. |
81 content::RenderThread* render_thread = content::RenderThread::Get(); | 97 content::RenderThread* render_thread = content::RenderThread::Get(); |
82 if (!render_thread) | 98 if (!render_thread) |
83 return false; | 99 return false; |
84 if (!g_pnacl_resource_host.Get().get()) { | 100 if (!g_pnacl_resource_host.Get().get()) { |
85 g_pnacl_resource_host.Get() = new PnaclTranslationResourceHost( | 101 g_pnacl_resource_host.Get() = new PnaclTranslationResourceHost( |
(...skipping 11 matching lines...) Expand all Loading... | |
97 ppapi::PpapiPermissions permissions; | 113 ppapi::PpapiPermissions permissions; |
98 base::ProcessId plugin_pid; | 114 base::ProcessId plugin_pid; |
99 int plugin_child_id; | 115 int plugin_child_id; |
100 IPC::ChannelHandle channel_handle; | 116 IPC::ChannelHandle channel_handle; |
101 }; | 117 }; |
102 | 118 |
103 class NaClPluginInstance { | 119 class NaClPluginInstance { |
104 public: | 120 public: |
105 NaClPluginInstance(PP_Instance instance): | 121 NaClPluginInstance(PP_Instance instance): |
106 nexe_load_manager(instance), pexe_size(0) {} | 122 nexe_load_manager(instance), pexe_size(0) {} |
123 ~NaClPluginInstance(); | |
107 | 124 |
108 NexeLoadManager nexe_load_manager; | 125 NexeLoadManager nexe_load_manager; |
109 scoped_ptr<JsonManifest> json_manifest; | 126 scoped_ptr<JsonManifest> json_manifest; |
110 scoped_ptr<InstanceInfo> instance_info; | 127 scoped_ptr<InstanceInfo> instance_info; |
128 std::vector<NaClResourceFileInfo> resource_files_info; | |
111 | 129 |
112 // When translation is complete, this records the size of the pexe in | 130 // When translation is complete, this records the size of the pexe in |
113 // bytes so that it can be reported in a later load event. | 131 // bytes so that it can be reported in a later load event. |
114 uint64_t pexe_size; | 132 uint64_t pexe_size; |
115 }; | 133 }; |
116 | 134 |
117 typedef base::ScopedPtrHashMap<PP_Instance, NaClPluginInstance> InstanceMap; | 135 typedef base::ScopedPtrHashMap<PP_Instance, NaClPluginInstance> InstanceMap; |
118 base::LazyInstance<InstanceMap> g_instance_map = LAZY_INSTANCE_INITIALIZER; | 136 base::LazyInstance<InstanceMap> g_instance_map = LAZY_INSTANCE_INITIALIZER; |
119 | 137 |
138 NaClPluginInstance::~NaClPluginInstance() { | |
139 for (size_t i = 0; i < resource_files_info.size(); ++i) { | |
140 #if defined(OS_POSIX) | |
141 base::FileDescriptor fd(resource_files_info[i].file); | |
142 if (fd.auto_close) { | |
143 base::ScopedFD closer(ToNativeHandle(fd)); | |
144 } | |
145 #elif defined(OS_WIN) | |
146 // TOOD(yusukes): Implement once OS_WIN supports pre-opening resources. | |
147 #endif | |
148 } | |
149 } | |
150 | |
120 NaClPluginInstance* GetNaClPluginInstance(PP_Instance instance) { | 151 NaClPluginInstance* GetNaClPluginInstance(PP_Instance instance) { |
121 InstanceMap& map = g_instance_map.Get(); | 152 InstanceMap& map = g_instance_map.Get(); |
122 InstanceMap::iterator iter = map.find(instance); | 153 InstanceMap::iterator iter = map.find(instance); |
123 if (iter == map.end()) | 154 if (iter == map.end()) |
124 return NULL; | 155 return NULL; |
125 return iter->second; | 156 return iter->second; |
126 } | 157 } |
127 | 158 |
128 NexeLoadManager* GetNexeLoadManager(PP_Instance instance) { | 159 NexeLoadManager* GetNexeLoadManager(PP_Instance instance) { |
129 NaClPluginInstance* nacl_plugin_instance = GetNaClPluginInstance(instance); | 160 NaClPluginInstance* nacl_plugin_instance = GetNaClPluginInstance(instance); |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
394 // must also check on the trusted side of the proxy. | 425 // must also check on the trusted side of the proxy. |
395 if (load_manager->DevInterfacesEnabled()) | 426 if (load_manager->DevInterfacesEnabled()) |
396 perm_bits |= ppapi::PERMISSION_DEV; | 427 perm_bits |= ppapi::PERMISSION_DEV; |
397 instance_info.permissions = | 428 instance_info.permissions = |
398 ppapi::PpapiPermissions::GetForCommandLine(perm_bits); | 429 ppapi::PpapiPermissions::GetForCommandLine(perm_bits); |
399 std::string error_message_string; | 430 std::string error_message_string; |
400 NaClLaunchResult launch_result; | 431 NaClLaunchResult launch_result; |
401 | 432 |
402 IPC::PlatformFileForTransit nexe_for_transit = | 433 IPC::PlatformFileForTransit nexe_for_transit = |
403 IPC::InvalidPlatformFileForTransit(); | 434 IPC::InvalidPlatformFileForTransit(); |
435 | |
436 NaClPluginInstance* nacl_plugin_instance = GetNaClPluginInstance(instance); | |
404 #if defined(OS_POSIX) | 437 #if defined(OS_POSIX) |
405 if (nexe_file_info->handle != PP_kInvalidFileHandle) | 438 if (nexe_file_info->handle != PP_kInvalidFileHandle) |
406 nexe_for_transit = base::FileDescriptor(nexe_file_info->handle, true); | 439 nexe_for_transit = base::FileDescriptor(nexe_file_info->handle, true); |
407 #elif defined(OS_WIN) | 440 #elif defined(OS_WIN) |
408 // Duplicate the handle on the browser side instead of the renderer. | 441 // Duplicate the handle on the browser side instead of the renderer. |
409 // This is because BrokerGetFileForProcess isn't part of content/public, and | 442 // This is because BrokerGetFileForProcess isn't part of content/public, and |
410 // it's simpler to do the duplication in the browser anyway. | 443 // it's simpler to do the duplication in the browser anyway. |
411 nexe_for_transit = nexe_file_info->handle; | 444 nexe_for_transit = nexe_file_info->handle; |
445 // TODO(yusukes): Support pre-opening resource files on Windows. | |
412 #else | 446 #else |
413 #error Unsupported target platform. | 447 #error Unsupported target platform. |
414 #endif | 448 #endif |
415 if (!sender->Send(new NaClHostMsg_LaunchNaCl( | 449 if (!sender->Send(new NaClHostMsg_LaunchNaCl( |
416 NaClLaunchParams( | 450 NaClLaunchParams( |
417 instance_info.url.spec(), | 451 instance_info.url.spec(), |
418 nexe_for_transit, | 452 nexe_for_transit, |
419 nexe_file_info->token_lo, | 453 nexe_file_info->token_lo, |
420 nexe_file_info->token_hi, | 454 nexe_file_info->token_hi, |
455 nacl_plugin_instance->resource_files_info, | |
421 routing_id, | 456 routing_id, |
422 perm_bits, | 457 perm_bits, |
423 PP_ToBool(uses_nonsfi_mode), | 458 PP_ToBool(uses_nonsfi_mode), |
424 process_type), | 459 process_type), |
425 &launch_result, | 460 &launch_result, |
426 &error_message_string))) { | 461 &error_message_string))) { |
427 ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask( | 462 ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask( |
428 FROM_HERE, | 463 FROM_HERE, |
429 base::Bind(callback.func, callback.user_data, | 464 base::Bind(callback.func, callback.user_data, |
430 static_cast<int32_t>(PP_ERROR_FAILED))); | 465 static_cast<int32_t>(PP_ERROR_FAILED))); |
466 nacl_plugin_instance->resource_files_info.clear(); | |
431 return; | 467 return; |
432 } | 468 } |
433 | 469 |
470 nacl_plugin_instance->resource_files_info.clear(); | |
434 load_manager->set_nonsfi(PP_ToBool(uses_nonsfi_mode)); | 471 load_manager->set_nonsfi(PP_ToBool(uses_nonsfi_mode)); |
435 | 472 |
436 if (!error_message_string.empty()) { | 473 if (!error_message_string.empty()) { |
437 if (PP_ToBool(main_service_runtime)) { | 474 if (PP_ToBool(main_service_runtime)) { |
438 load_manager->ReportLoadError(PP_NACL_ERROR_SEL_LDR_LAUNCH, | 475 load_manager->ReportLoadError(PP_NACL_ERROR_SEL_LDR_LAUNCH, |
439 "ServiceRuntime: failed to start", | 476 "ServiceRuntime: failed to start", |
440 error_message_string); | 477 error_message_string); |
441 } | 478 } |
442 ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask( | 479 ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask( |
443 FROM_HERE, | 480 FROM_HERE, |
444 base::Bind(callback.func, callback.user_data, | 481 base::Bind(callback.func, callback.user_data, |
445 static_cast<int32_t>(PP_ERROR_FAILED))); | 482 static_cast<int32_t>(PP_ERROR_FAILED))); |
446 return; | 483 return; |
447 } | 484 } |
448 result_socket = launch_result.imc_channel_handle; | 485 result_socket = launch_result.imc_channel_handle; |
449 instance_info.channel_handle = launch_result.ppapi_ipc_channel_handle; | 486 instance_info.channel_handle = launch_result.ppapi_ipc_channel_handle; |
450 instance_info.plugin_pid = launch_result.plugin_pid; | 487 instance_info.plugin_pid = launch_result.plugin_pid; |
451 instance_info.plugin_child_id = launch_result.plugin_child_id; | 488 instance_info.plugin_child_id = launch_result.plugin_child_id; |
452 | 489 |
453 // Don't save instance_info if channel handle is invalid. | 490 // Don't save instance_info if channel handle is invalid. |
454 if (IsValidChannelHandle(instance_info.channel_handle)) { | 491 if (IsValidChannelHandle(instance_info.channel_handle)) |
455 NaClPluginInstance* nacl_plugin_instance = GetNaClPluginInstance(instance); | |
456 nacl_plugin_instance->instance_info.reset(new InstanceInfo(instance_info)); | 492 nacl_plugin_instance->instance_info.reset(new InstanceInfo(instance_info)); |
457 } | |
458 | 493 |
459 *(static_cast<NaClHandle*>(imc_handle)) = ToNativeHandle(result_socket); | 494 *(static_cast<NaClHandle*>(imc_handle)) = ToNativeHandle(result_socket); |
460 | 495 |
461 // Store the crash information shared memory handle. | 496 // Store the crash information shared memory handle. |
462 load_manager->set_crash_info_shmem_handle( | 497 load_manager->set_crash_info_shmem_handle( |
463 launch_result.crash_info_shmem_handle); | 498 launch_result.crash_info_shmem_handle); |
464 | 499 |
465 // Create the trusted plugin channel. | 500 // Create the trusted plugin channel. |
466 if (IsValidChannelHandle(launch_result.trusted_ipc_channel_handle)) { | 501 if (IsValidChannelHandle(launch_result.trusted_ipc_channel_handle)) { |
467 bool report_exit_status = PP_ToBool(main_service_runtime); | 502 bool report_exit_status = PP_ToBool(main_service_runtime); |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
576 replace_pos = r.find_first_not_of(white_list); | 611 replace_pos = r.find_first_not_of(white_list); |
577 } | 612 } |
578 return r; | 613 return r; |
579 } | 614 } |
580 | 615 |
581 PP_FileHandle GetReadonlyPnaclFd(const char* url, | 616 PP_FileHandle GetReadonlyPnaclFd(const char* url, |
582 bool is_executable, | 617 bool is_executable, |
583 uint64_t* nonce_lo, | 618 uint64_t* nonce_lo, |
584 uint64_t* nonce_hi) { | 619 uint64_t* nonce_hi) { |
585 std::string filename = PnaclComponentURLToFilename(url); | 620 std::string filename = PnaclComponentURLToFilename(url); |
586 IPC::PlatformFileForTransit out_fd = IPC::InvalidPlatformFileForTransit(); | 621 IPC::PlatformFileForTransit out_fd = IPC::InvalidPlatformFileForTransit(); |
Yusuke Sato
2015/02/11 05:54:21
reverted to the original code.
| |
587 IPC::Sender* sender = content::RenderThread::Get(); | 622 IPC::Sender* sender = content::RenderThread::Get(); |
623 NaClResourceFileInfo file_info; | |
Mark Seaborn
2015/02/12 03:57:34
Not used now?
Yusuke Sato
2015/02/13 23:01:17
Done.
| |
588 DCHECK(sender); | 624 DCHECK(sender); |
589 if (!sender->Send(new NaClHostMsg_GetReadonlyPnaclFD( | 625 if (!sender->Send(new NaClHostMsg_GetReadonlyPnaclFD( |
590 std::string(filename), is_executable, | 626 std::string(filename), is_executable, |
591 &out_fd, nonce_lo, nonce_hi))) { | 627 &out_fd, nonce_lo, nonce_hi))) { |
592 return PP_kInvalidFileHandle; | 628 return PP_kInvalidFileHandle; |
593 } | 629 } |
594 if (out_fd == IPC::InvalidPlatformFileForTransit()) { | 630 if (out_fd == IPC::InvalidPlatformFileForTransit()) { |
595 return PP_kInvalidFileHandle; | 631 return PP_kInvalidFileHandle; |
596 } | 632 } |
597 return IPC::PlatformFileForTransitToPlatformFile(out_fd); | 633 return IPC::PlatformFileForTransitToPlatformFile(out_fd); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
700 return; | 736 return; |
701 g_pnacl_resource_host.Get()->ReportTranslationFinished(instance, success); | 737 g_pnacl_resource_host.Get()->ReportTranslationFinished(instance, success); |
702 | 738 |
703 // Record the pexe size for reporting in a later load event. | 739 // Record the pexe size for reporting in a later load event. |
704 NaClPluginInstance* nacl_plugin_instance = GetNaClPluginInstance(instance); | 740 NaClPluginInstance* nacl_plugin_instance = GetNaClPluginInstance(instance); |
705 if (nacl_plugin_instance) { | 741 if (nacl_plugin_instance) { |
706 nacl_plugin_instance->pexe_size = pexe_size; | 742 nacl_plugin_instance->pexe_size = pexe_size; |
707 } | 743 } |
708 } | 744 } |
709 | 745 |
710 PP_FileHandle OpenNaClExecutable(PP_Instance instance, | 746 bool OpenNaClResources( |
711 const char* file_url, | 747 PP_Instance instance, |
712 uint64_t* nonce_lo, | 748 const std::vector<std::string>& resource_file_urls, |
713 uint64_t* nonce_hi) { | 749 std::vector<NaClResourceFileInfo>* out_resource_file_handles) { |
714 // Fast path only works for installed file URLs. | 750 DCHECK(out_resource_file_handles); |
715 GURL gurl(file_url); | 751 if (resource_file_urls.empty()) |
716 if (!gurl.SchemeIs("chrome-extension")) | 752 return false; |
717 return PP_kInvalidFileHandle; | |
718 | 753 |
719 NexeLoadManager* load_manager = GetNexeLoadManager(instance); | 754 NexeLoadManager* load_manager = GetNexeLoadManager(instance); |
720 DCHECK(load_manager); | 755 DCHECK(load_manager); |
721 if (!load_manager) | 756 if (!load_manager) |
722 return PP_kInvalidFileHandle; | 757 return PP_kInvalidFileHandle; |
723 | 758 |
724 content::PepperPluginInstance* plugin_instance = | 759 content::PepperPluginInstance* plugin_instance = |
725 content::PepperPluginInstance::Get(instance); | 760 content::PepperPluginInstance::Get(instance); |
726 if (!plugin_instance) | 761 if (!plugin_instance) |
727 return PP_kInvalidFileHandle; | 762 return false; |
728 // IMPORTANT: Make sure the document can request the given URL. If we don't | |
729 // check, a malicious app could probe the extension system. This enforces a | |
730 // same-origin policy which prevents the app from requesting resources from | |
731 // another app. | |
732 blink::WebSecurityOrigin security_origin = | 763 blink::WebSecurityOrigin security_origin = |
733 plugin_instance->GetContainer()->element().document().securityOrigin(); | 764 plugin_instance->GetContainer()->element().document().securityOrigin(); |
734 if (!security_origin.canRequest(gurl)) | |
735 return PP_kInvalidFileHandle; | |
736 | |
737 IPC::PlatformFileForTransit out_fd = IPC::InvalidPlatformFileForTransit(); | |
738 IPC::Sender* sender = content::RenderThread::Get(); | 765 IPC::Sender* sender = content::RenderThread::Get(); |
739 DCHECK(sender); | 766 DCHECK(sender); |
740 *nonce_lo = 0; | 767 |
741 *nonce_hi = 0; | 768 std::vector<GURL> resource_gurls; |
742 base::FilePath file_path; | 769 for (size_t i = 0; i < resource_file_urls.size(); ++i) { |
743 if (!sender->Send( | 770 const GURL gurl(resource_file_urls[i]); |
744 new NaClHostMsg_OpenNaClExecutable(GetRoutingID(instance), | 771 // Fast path only works for installed file URLs. |
745 GURL(file_url), | 772 if (!gurl.SchemeIs("chrome-extension")) |
746 !load_manager->nonsfi(), | 773 return false; |
747 &out_fd, | 774 // IMPORTANT: Make sure the document can request the given URL. If we don't |
748 nonce_lo, | 775 // check, a malicious app could probe the extension system. This enforces a |
749 nonce_hi))) { | 776 // same-origin policy which prevents the app from requesting resources from |
750 return PP_kInvalidFileHandle; | 777 // another app. |
778 if (!security_origin.canRequest(gurl)) | |
779 return false; | |
780 resource_gurls.push_back(gurl); | |
751 } | 781 } |
752 | 782 |
753 if (out_fd == IPC::InvalidPlatformFileForTransit()) | 783 if (!sender->Send(new NaClHostMsg_OpenNaClResources( |
754 return PP_kInvalidFileHandle; | 784 GetRoutingID(instance), |
785 resource_gurls, | |
786 !load_manager->nonsfi(), | |
787 out_resource_file_handles))) { | |
788 return false; | |
789 } | |
755 | 790 |
756 return IPC::PlatformFileForTransitToPlatformFile(out_fd); | 791 if (out_resource_file_handles->empty() || |
792 (out_resource_file_handles->at(0).file == | |
793 IPC::InvalidPlatformFileForTransit())) { | |
794 DLOG(ERROR) << "Could not open the main nexe: " << resource_gurls[0]; | |
Mark Seaborn
2015/02/12 03:57:34
I don't think you need this special-cased check.
Yusuke Sato
2015/02/13 23:01:17
Done, removed
| |
795 return false; | |
796 } | |
797 return true; | |
757 } | 798 } |
758 | 799 |
759 void DispatchEvent(PP_Instance instance, | 800 void DispatchEvent(PP_Instance instance, |
760 PP_NaClEventType event_type, | 801 PP_NaClEventType event_type, |
761 const char* resource_url, | 802 const char* resource_url, |
762 PP_Bool length_is_computable, | 803 PP_Bool length_is_computable, |
763 uint64_t loaded_bytes, | 804 uint64_t loaded_bytes, |
764 uint64_t total_bytes) { | 805 uint64_t total_bytes) { |
765 ProgressEvent event(event_type, | 806 ProgressEvent event(event_type, |
766 resource_url, | 807 resource_url, |
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1204 }; | 1245 }; |
1205 | 1246 |
1206 void DownloadNexeCompletion(const DownloadNexeRequest& request, | 1247 void DownloadNexeCompletion(const DownloadNexeRequest& request, |
1207 PP_NaClFileInfo* out_file_info, | 1248 PP_NaClFileInfo* out_file_info, |
1208 FileDownloader::Status status, | 1249 FileDownloader::Status status, |
1209 base::File target_file, | 1250 base::File target_file, |
1210 int http_status); | 1251 int http_status); |
1211 | 1252 |
1212 void DownloadNexe(PP_Instance instance, | 1253 void DownloadNexe(PP_Instance instance, |
1213 const char* url, | 1254 const char* url, |
1255 PP_Bool download_resource_files, | |
1214 PP_NaClFileInfo* out_file_info, | 1256 PP_NaClFileInfo* out_file_info, |
1215 PP_CompletionCallback callback) { | 1257 PP_CompletionCallback callback) { |
1216 CHECK(url); | 1258 CHECK(url); |
1217 CHECK(out_file_info); | 1259 CHECK(out_file_info); |
1218 DownloadNexeRequest request; | 1260 DownloadNexeRequest request; |
1219 request.instance = instance; | 1261 request.instance = instance; |
1220 request.url = url; | 1262 request.url = url; |
1221 request.callback = callback; | 1263 request.callback = callback; |
1222 request.start_time = base::Time::Now(); | 1264 request.start_time = base::Time::Now(); |
1223 | 1265 |
1266 std::vector<std::string> file_urls; | |
1267 file_urls.push_back(url); // the main nexe must be the first element. | |
1268 | |
1269 std::vector< | |
1270 std::pair<std::string /*url*/, std::string /*key*/> > resource_files; | |
1271 if (download_resource_files) { | |
1272 JsonManifest* manifest = GetJsonManifest(instance); | |
1273 if (manifest) | |
1274 manifest->GetFiles(&resource_files, "chrome-extension"); | |
1275 if (resource_files.size() > kMaxPreOpenResourceFiles) | |
1276 resource_files.resize(kMaxPreOpenResourceFiles); | |
1277 for (size_t i = 0; i < resource_files.size(); ++i) { | |
1278 file_urls.push_back(resource_files[i].first); | |
1279 } | |
1280 } | |
1281 | |
1224 // Try the fast path for retrieving the file first. | 1282 // Try the fast path for retrieving the file first. |
1225 PP_FileHandle handle = OpenNaClExecutable(instance, | 1283 std::vector<NaClResourceFileInfo> file_handles; |
1226 url, | 1284 if (OpenNaClResources(instance, file_urls, &file_handles)) { |
1227 &out_file_info->token_lo, | 1285 DCHECK(!file_handles.empty()); |
1228 &out_file_info->token_hi); | 1286 out_file_info->handle = |
1229 if (handle != PP_kInvalidFileHandle) { | 1287 IPC::PlatformFileForTransitToPlatformFile(file_handles[0].file); |
1288 out_file_info->token_lo = file_handles[0].file_token_lo; | |
1289 out_file_info->token_hi = file_handles[0].file_token_hi; | |
1290 NaClPluginInstance* nacl_plugin_instance = GetNaClPluginInstance(instance); | |
1291 for (size_t i = 1; i < file_handles.size(); ++i) { | |
1292 std::string key = resource_files[i - 1].second; | |
1293 nacl_plugin_instance->resource_files_info.push_back( | |
1294 NaClResourceFileInfo(file_handles[i].file, | |
1295 file_handles[i].file_token_lo, | |
1296 file_handles[i].file_token_hi, | |
1297 key)); | |
1298 } | |
1230 DownloadNexeCompletion(request, | 1299 DownloadNexeCompletion(request, |
1231 out_file_info, | 1300 out_file_info, |
1232 FileDownloader::SUCCESS, | 1301 FileDownloader::SUCCESS, |
1233 base::File(handle), | 1302 base::File(out_file_info->handle), |
1234 200); | 1303 200); |
1235 return; | 1304 return; |
1236 } | 1305 } |
1237 | 1306 |
1238 // The fast path didn't work, we'll fetch the file using URLLoader and write | 1307 // The fast path didn't work, we'll fetch the file using URLLoader and write |
1239 // it to local storage. | 1308 // it to local storage. |
1240 base::File target_file(CreateTemporaryFile(instance)); | 1309 base::File target_file(CreateTemporaryFile(instance)); |
1241 GURL gurl(url); | 1310 GURL gurl(url); |
1242 | 1311 |
1312 // On the slow path, do not retry to pre-open the resource files. | |
1243 content::PepperPluginInstance* plugin_instance = | 1313 content::PepperPluginInstance* plugin_instance = |
1244 content::PepperPluginInstance::Get(instance); | 1314 content::PepperPluginInstance::Get(instance); |
1245 if (!plugin_instance) { | 1315 if (!plugin_instance) { |
1246 ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask( | 1316 ppapi::PpapiGlobals::Get()->GetMainThreadMessageLoop()->PostTask( |
1247 FROM_HERE, | 1317 FROM_HERE, |
1248 base::Bind(callback.func, callback.user_data, | 1318 base::Bind(callback.func, callback.user_data, |
1249 static_cast<int32_t>(PP_ERROR_FAILED))); | 1319 static_cast<int32_t>(PP_ERROR_FAILED))); |
1250 } | 1320 } |
1251 const blink::WebDocument& document = | 1321 const blink::WebDocument& document = |
1252 plugin_instance->GetContainer()->element().document(); | 1322 plugin_instance->GetContainer()->element().document(); |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1368 if (!test_gurl.is_valid()) { | 1438 if (!test_gurl.is_valid()) { |
1369 base::MessageLoop::current()->PostTask( | 1439 base::MessageLoop::current()->PostTask( |
1370 FROM_HERE, | 1440 FROM_HERE, |
1371 base::Bind(callback, | 1441 base::Bind(callback, |
1372 static_cast<int32_t>(PP_ERROR_FAILED), | 1442 static_cast<int32_t>(PP_ERROR_FAILED), |
1373 kInvalidNaClFileInfo)); | 1443 kInvalidNaClFileInfo)); |
1374 return; | 1444 return; |
1375 } | 1445 } |
1376 | 1446 |
1377 // Try the fast path for retrieving the file first. | 1447 // Try the fast path for retrieving the file first. |
1378 uint64_t file_token_lo = 0; | 1448 std::vector<std::string> file_urls; |
1379 uint64_t file_token_hi = 0; | 1449 file_urls.push_back(url); |
1380 PP_FileHandle file_handle = OpenNaClExecutable(instance, | 1450 std::vector<NaClResourceFileInfo> out_handles; |
1381 url.c_str(), | 1451 if (OpenNaClResources(instance, file_urls, &out_handles)) { |
1382 &file_token_lo, | |
1383 &file_token_hi); | |
1384 if (file_handle != PP_kInvalidFileHandle) { | |
1385 PP_NaClFileInfo file_info; | 1452 PP_NaClFileInfo file_info; |
1386 file_info.handle = file_handle; | 1453 file_info.handle = |
1387 file_info.token_lo = file_token_lo; | 1454 IPC::PlatformFileForTransitToPlatformFile(out_handles[0].file); |
1388 file_info.token_hi = file_token_hi; | 1455 file_info.token_lo = out_handles[0].file_token_lo; |
1456 file_info.token_hi = out_handles[0].file_token_hi; | |
1389 base::MessageLoop::current()->PostTask( | 1457 base::MessageLoop::current()->PostTask( |
1390 FROM_HERE, | 1458 FROM_HERE, |
1391 base::Bind(callback, static_cast<int32_t>(PP_OK), file_info)); | 1459 base::Bind(callback, static_cast<int32_t>(PP_OK), file_info)); |
1392 return; | 1460 return; |
1393 } | 1461 } |
1394 | 1462 |
1395 // The fast path didn't work, we'll fetch the file using URLLoader and write | 1463 // The fast path didn't work, we'll fetch the file using URLLoader and write |
1396 // it to local storage. | 1464 // it to local storage. |
1397 base::File target_file(CreateTemporaryFile(instance)); | 1465 base::File target_file(CreateTemporaryFile(instance)); |
1398 GURL gurl(url); | 1466 GURL gurl(url); |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1651 &StreamPexe | 1719 &StreamPexe |
1652 }; | 1720 }; |
1653 | 1721 |
1654 } // namespace | 1722 } // namespace |
1655 | 1723 |
1656 const PPB_NaCl_Private* GetNaClPrivateInterface() { | 1724 const PPB_NaCl_Private* GetNaClPrivateInterface() { |
1657 return &nacl_interface; | 1725 return &nacl_interface; |
1658 } | 1726 } |
1659 | 1727 |
1660 } // namespace nacl | 1728 } // namespace nacl |
OLD | NEW |