Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(353)

Unified Diff: components/nacl/renderer/ppb_nacl_private_impl.cc

Issue 649603004: Non-SFI NaCl: Batch-open resource files (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: code review Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 3c84afe5d1ee4a16187fef0b715342f5b239acf4..f3b1aef5d5569c3cafbe8b8dfd7d0944a4ff2c5f 100644
--- a/components/nacl/renderer/ppb_nacl_private_impl.cc
+++ b/components/nacl/renderer/ppb_nacl_private_impl.cc
@@ -16,6 +16,7 @@
#include "base/files/file.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
+#include "base/macros.h"
#include "base/rand_util.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
@@ -41,6 +42,7 @@
#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/render_view.h"
#include "content/public/renderer/renderer_ppapi_host.h"
+#include "ipc/ipc_message_attachment_set.h"
#include "native_client/src/public/imc_types.h"
#include "net/base/data_url.h"
#include "net/base/net_errors.h"
@@ -73,6 +75,20 @@ const char* const kPortableArch = "portable";
// The base URL for resources used by the PNaCl translator processes.
const char* kPNaClTranslatorBaseUrl = "chrome://pnacl-translator/";
+// The maximum number of resource files DownloadNexe() can open.
+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.
+
+#if defined(OS_POSIX)
+// On POSIX platforms, the maximum number of files a process can pass to
+// another is limited to kMaxDescriptorsPerMessage. Since the browser process
+// may use up to 5 descriptors for passing non-resource files when creating
+// the NaCl plugin process, kMaxPreOpenResourceFiles must be smaller than or
+// equal to (IPC::MessageAttachmentSet::kMaxDescriptorsPerMessage - 5).
+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.
+ IPC::MessageAttachmentSet::kMaxDescriptorsPerMessage - 5,
+ k_max_pre_open_resource_files_too_large);
+#endif
+
base::LazyInstance<scoped_refptr<PnaclTranslationResourceHost> >
g_pnacl_resource_host = LAZY_INSTANCE_INITIALIZER;
@@ -104,10 +120,12 @@ class NaClPluginInstance {
public:
NaClPluginInstance(PP_Instance instance):
nexe_load_manager(instance), pexe_size(0) {}
+ ~NaClPluginInstance();
NexeLoadManager nexe_load_manager;
scoped_ptr<JsonManifest> json_manifest;
scoped_ptr<InstanceInfo> instance_info;
+ std::vector<NaClResourceFileInfo> resource_files_info;
// When translation is complete, this records the size of the pexe in
// bytes so that it can be reported in a later load event.
@@ -117,6 +135,19 @@ class NaClPluginInstance {
typedef base::ScopedPtrHashMap<PP_Instance, NaClPluginInstance> InstanceMap;
base::LazyInstance<InstanceMap> g_instance_map = LAZY_INSTANCE_INITIALIZER;
+NaClPluginInstance::~NaClPluginInstance() {
+ for (size_t i = 0; i < resource_files_info.size(); ++i) {
+#if defined(OS_POSIX)
+ base::FileDescriptor fd(resource_files_info[i].file);
+ if (fd.auto_close) {
+ base::ScopedFD closer(ToNativeHandle(fd));
+ }
+#elif defined(OS_WIN)
+ // TOOD(yusukes): Implement once OS_WIN supports pre-opening resources.
+#endif
+ }
+}
+
NaClPluginInstance* GetNaClPluginInstance(PP_Instance instance) {
InstanceMap& map = g_instance_map.Get();
InstanceMap::iterator iter = map.find(instance);
@@ -401,6 +432,8 @@ void LaunchSelLdr(PP_Instance instance,
IPC::PlatformFileForTransit nexe_for_transit =
IPC::InvalidPlatformFileForTransit();
+
+ NaClPluginInstance* nacl_plugin_instance = GetNaClPluginInstance(instance);
#if defined(OS_POSIX)
if (nexe_file_info->handle != PP_kInvalidFileHandle)
nexe_for_transit = base::FileDescriptor(nexe_file_info->handle, true);
@@ -409,6 +442,7 @@ void LaunchSelLdr(PP_Instance instance,
// This is because BrokerGetFileForProcess isn't part of content/public, and
// it's simpler to do the duplication in the browser anyway.
nexe_for_transit = nexe_file_info->handle;
+ // TODO(yusukes): Support pre-opening resource files on Windows.
#else
#error Unsupported target platform.
#endif
@@ -418,6 +452,7 @@ void LaunchSelLdr(PP_Instance instance,
nexe_for_transit,
nexe_file_info->token_lo,
nexe_file_info->token_hi,
+ nacl_plugin_instance->resource_files_info,
routing_id,
perm_bits,
PP_ToBool(uses_nonsfi_mode),
@@ -428,9 +463,11 @@ void LaunchSelLdr(PP_Instance instance,
FROM_HERE,
base::Bind(callback.func, callback.user_data,
static_cast<int32_t>(PP_ERROR_FAILED)));
+ nacl_plugin_instance->resource_files_info.clear();
return;
}
+ nacl_plugin_instance->resource_files_info.clear();
load_manager->set_nonsfi(PP_ToBool(uses_nonsfi_mode));
if (!error_message_string.empty()) {
@@ -451,10 +488,8 @@ void LaunchSelLdr(PP_Instance instance,
instance_info.plugin_child_id = launch_result.plugin_child_id;
// Don't save instance_info if channel handle is invalid.
- if (IsValidChannelHandle(instance_info.channel_handle)) {
- NaClPluginInstance* nacl_plugin_instance = GetNaClPluginInstance(instance);
+ if (IsValidChannelHandle(instance_info.channel_handle))
nacl_plugin_instance->instance_info.reset(new InstanceInfo(instance_info));
- }
*(static_cast<NaClHandle*>(imc_handle)) = ToNativeHandle(result_socket);
@@ -585,6 +620,7 @@ PP_FileHandle GetReadonlyPnaclFd(const char* url,
std::string filename = PnaclComponentURLToFilename(url);
IPC::PlatformFileForTransit out_fd = IPC::InvalidPlatformFileForTransit();
Yusuke Sato 2015/02/11 05:54:21 reverted to the original code.
IPC::Sender* sender = content::RenderThread::Get();
+ NaClResourceFileInfo file_info;
Mark Seaborn 2015/02/12 03:57:34 Not used now?
Yusuke Sato 2015/02/13 23:01:17 Done.
DCHECK(sender);
if (!sender->Send(new NaClHostMsg_GetReadonlyPnaclFD(
std::string(filename), is_executable,
@@ -707,14 +743,13 @@ void ReportTranslationFinished(PP_Instance instance,
}
}
-PP_FileHandle OpenNaClExecutable(PP_Instance instance,
- const char* file_url,
- uint64_t* nonce_lo,
- uint64_t* nonce_hi) {
- // Fast path only works for installed file URLs.
- GURL gurl(file_url);
- if (!gurl.SchemeIs("chrome-extension"))
- return PP_kInvalidFileHandle;
+bool OpenNaClResources(
+ PP_Instance instance,
+ const std::vector<std::string>& resource_file_urls,
+ std::vector<NaClResourceFileInfo>* out_resource_file_handles) {
+ DCHECK(out_resource_file_handles);
+ if (resource_file_urls.empty())
+ return false;
NexeLoadManager* load_manager = GetNexeLoadManager(instance);
DCHECK(load_manager);
@@ -724,36 +759,42 @@ PP_FileHandle OpenNaClExecutable(PP_Instance instance,
content::PepperPluginInstance* plugin_instance =
content::PepperPluginInstance::Get(instance);
if (!plugin_instance)
- return PP_kInvalidFileHandle;
- // IMPORTANT: Make sure the document can request the given URL. If we don't
- // check, a malicious app could probe the extension system. This enforces a
- // same-origin policy which prevents the app from requesting resources from
- // another app.
+ return false;
blink::WebSecurityOrigin security_origin =
plugin_instance->GetContainer()->element().document().securityOrigin();
- if (!security_origin.canRequest(gurl))
- return PP_kInvalidFileHandle;
-
- IPC::PlatformFileForTransit out_fd = IPC::InvalidPlatformFileForTransit();
IPC::Sender* sender = content::RenderThread::Get();
DCHECK(sender);
- *nonce_lo = 0;
- *nonce_hi = 0;
- base::FilePath file_path;
- if (!sender->Send(
- new NaClHostMsg_OpenNaClExecutable(GetRoutingID(instance),
- GURL(file_url),
- !load_manager->nonsfi(),
- &out_fd,
- nonce_lo,
- nonce_hi))) {
- return PP_kInvalidFileHandle;
+
+ std::vector<GURL> resource_gurls;
+ for (size_t i = 0; i < resource_file_urls.size(); ++i) {
+ const GURL gurl(resource_file_urls[i]);
+ // Fast path only works for installed file URLs.
+ if (!gurl.SchemeIs("chrome-extension"))
+ return false;
+ // IMPORTANT: Make sure the document can request the given URL. If we don't
+ // check, a malicious app could probe the extension system. This enforces a
+ // same-origin policy which prevents the app from requesting resources from
+ // another app.
+ if (!security_origin.canRequest(gurl))
+ return false;
+ resource_gurls.push_back(gurl);
}
- if (out_fd == IPC::InvalidPlatformFileForTransit())
- return PP_kInvalidFileHandle;
+ if (!sender->Send(new NaClHostMsg_OpenNaClResources(
+ GetRoutingID(instance),
+ resource_gurls,
+ !load_manager->nonsfi(),
+ out_resource_file_handles))) {
+ return false;
+ }
- return IPC::PlatformFileForTransitToPlatformFile(out_fd);
+ if (out_resource_file_handles->empty() ||
+ (out_resource_file_handles->at(0).file ==
+ IPC::InvalidPlatformFileForTransit())) {
+ 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
+ return false;
+ }
+ return true;
}
void DispatchEvent(PP_Instance instance,
@@ -1211,6 +1252,7 @@ void DownloadNexeCompletion(const DownloadNexeRequest& request,
void DownloadNexe(PP_Instance instance,
const char* url,
+ PP_Bool download_resource_files,
PP_NaClFileInfo* out_file_info,
PP_CompletionCallback callback) {
CHECK(url);
@@ -1221,16 +1263,43 @@ void DownloadNexe(PP_Instance instance,
request.callback = callback;
request.start_time = base::Time::Now();
+ std::vector<std::string> file_urls;
+ file_urls.push_back(url); // the main nexe must be the first element.
+
+ std::vector<
+ std::pair<std::string /*url*/, std::string /*key*/> > resource_files;
+ if (download_resource_files) {
+ JsonManifest* manifest = GetJsonManifest(instance);
+ if (manifest)
+ manifest->GetFiles(&resource_files, "chrome-extension");
+ if (resource_files.size() > kMaxPreOpenResourceFiles)
+ resource_files.resize(kMaxPreOpenResourceFiles);
+ for (size_t i = 0; i < resource_files.size(); ++i) {
+ file_urls.push_back(resource_files[i].first);
+ }
+ }
+
// Try the fast path for retrieving the file first.
- PP_FileHandle handle = OpenNaClExecutable(instance,
- url,
- &out_file_info->token_lo,
- &out_file_info->token_hi);
- if (handle != PP_kInvalidFileHandle) {
+ std::vector<NaClResourceFileInfo> file_handles;
+ if (OpenNaClResources(instance, file_urls, &file_handles)) {
+ DCHECK(!file_handles.empty());
+ out_file_info->handle =
+ IPC::PlatformFileForTransitToPlatformFile(file_handles[0].file);
+ out_file_info->token_lo = file_handles[0].file_token_lo;
+ out_file_info->token_hi = file_handles[0].file_token_hi;
+ NaClPluginInstance* nacl_plugin_instance = GetNaClPluginInstance(instance);
+ for (size_t i = 1; i < file_handles.size(); ++i) {
+ std::string key = resource_files[i - 1].second;
+ nacl_plugin_instance->resource_files_info.push_back(
+ NaClResourceFileInfo(file_handles[i].file,
+ file_handles[i].file_token_lo,
+ file_handles[i].file_token_hi,
+ key));
+ }
DownloadNexeCompletion(request,
out_file_info,
FileDownloader::SUCCESS,
- base::File(handle),
+ base::File(out_file_info->handle),
200);
return;
}
@@ -1240,6 +1309,7 @@ void DownloadNexe(PP_Instance instance,
base::File target_file(CreateTemporaryFile(instance));
GURL gurl(url);
+ // On the slow path, do not retry to pre-open the resource files.
content::PepperPluginInstance* plugin_instance =
content::PepperPluginInstance::Get(instance);
if (!plugin_instance) {
@@ -1375,17 +1445,15 @@ void DownloadFile(PP_Instance instance,
}
// Try the fast path for retrieving the file first.
- uint64_t file_token_lo = 0;
- uint64_t file_token_hi = 0;
- PP_FileHandle file_handle = OpenNaClExecutable(instance,
- url.c_str(),
- &file_token_lo,
- &file_token_hi);
- if (file_handle != PP_kInvalidFileHandle) {
+ std::vector<std::string> file_urls;
+ file_urls.push_back(url);
+ std::vector<NaClResourceFileInfo> out_handles;
+ if (OpenNaClResources(instance, file_urls, &out_handles)) {
PP_NaClFileInfo file_info;
- file_info.handle = file_handle;
- file_info.token_lo = file_token_lo;
- file_info.token_hi = file_token_hi;
+ file_info.handle =
+ IPC::PlatformFileForTransitToPlatformFile(out_handles[0].file);
+ file_info.token_lo = out_handles[0].file_token_lo;
+ file_info.token_hi = out_handles[0].file_token_hi;
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(callback, static_cast<int32_t>(PP_OK), file_info));

Powered by Google App Engine
This is Rietveld 408576698