Chromium Code Reviews| Index: chrome/browser/nacl_host/pnacl_file_host.cc |
| diff --git a/chrome/browser/nacl_host/pnacl_file_host.cc b/chrome/browser/nacl_host/pnacl_file_host.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..a42e8d85056a0a19d0b8ab00da65920d4cfa253a |
| --- /dev/null |
| +++ b/chrome/browser/nacl_host/pnacl_file_host.cc |
| @@ -0,0 +1,154 @@ |
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "chrome/browser/nacl_host/pnacl_file_host.h" |
| + |
| +#include <stdio.h> |
| + |
| +#include "base/bind.h" |
| +#include "base/memory/ref_counted.h" |
| +#include "base/path_service.h" |
| +#include "chrome/common/chrome_paths.h" |
| +#include "chrome/common/render_messages.h" |
| +#include "chrome/browser/renderer_host/chrome_render_message_filter.h" |
| +#include "content/public/browser/browser_thread.h" |
| +#include "native_client/src/shared/imc/nacl_imc.h" |
| + |
| +using content::BrowserThread; |
| + |
| +namespace { |
| + |
| +// Need the DuplicateHandle good to send the handle over to the |
| +// plugin process. |
| +// TODO(jvoung): share some code with nacl_process_host if possible. |
| +bool SendHandleToNaClPlugin( |
| + base::ProcessHandle target_processh, |
| + nacl::Handle sourceh, |
| + bool close_source, |
| + nacl::FileDescriptor* handle_for_plugin) { |
| +#if defined(OS_WIN) |
| + HANDLE channel; |
| + int flags = DUPLICATE_SAME_ACCESS; |
| + if (close_source) |
| + flags |= DUPLICATE_CLOSE_SOURCE; |
| + if (!DuplicateHandle(GetCurrentProcess(), |
| + reinterpret_cast<HANDLE>(sourceh), |
| + target_processh, |
| + &channel, |
| + 0, // Unused given DUPLICATE_SAME_ACCESS. |
| + FALSE, |
| + flags)) { |
| + LOG(ERROR) << "DuplicateHandle() failed"; |
| + return false; |
| + } |
| + *handle_for_plugin = reinterpret_cast<nacl::FileDescriptor>(channel); |
| +#else |
| + nacl::FileDescriptor channel; |
| + channel.fd = sourceh; |
| + channel.auto_close = close_source; |
| + *handle_for_plugin = channel; |
| +#endif |
| + return true; |
| +} |
| + |
| +void NotifyRendererOfError( |
| + ChromeRenderMessageFilter* chrome_render_message_filter, |
| + IPC::Message* reply_msg) { |
| + reply_msg->set_reply_error(); |
| + chrome_render_message_filter->Send(reply_msg); |
| +} |
| + |
| +} // namespace |
| + |
| +namespace pnacl_file_host { |
| + |
| +// This only ever runs on the BrowserThread::FILE thread. |
| +void DoOpenPnaclFile(ChromeRenderMessageFilter* chrome_render_message_filter, |
| + const std::string& filename, |
| + IPC::Message* reply_msg); |
| + |
| + |
| +void GetReadonlyPnaclFd( |
| + ChromeRenderMessageFilter* chrome_render_message_filter, |
| + const std::string& filename, |
| + IPC::Message* reply_msg) { |
| + fprintf(stderr, "In GetReadonlyPnaclFd: %s\n", filename.c_str()); |
| + |
| + if (!BrowserThread::PostTask( |
| + BrowserThread::FILE, FROM_HERE, |
| + base::Bind(&DoOpenPnaclFile, |
| + make_scoped_refptr(chrome_render_message_filter), |
| + filename, |
| + reply_msg))) { |
| + NotifyRendererOfError(chrome_render_message_filter, reply_msg); |
| + } |
| +} |
| + |
| +void DoOpenPnaclFile( |
| + ChromeRenderMessageFilter* chrome_render_message_filter, |
| + const std::string& filename, |
| + IPC::Message* reply_msg) { |
| + FilePath filepath; |
| + FilePath pnacl_dir; |
| + base::PlatformFile file_to_open; |
| + |
| + // Do some validation. |
| + // The file must use only ASCII characters. |
| + if (!IsStringASCII(filename)) { |
| + LOG(ERROR) << "Cannot open non-ASCII pnacl files."; |
| + NotifyRendererOfError(chrome_render_message_filter, reply_msg); |
| + return; |
| + } |
| + |
| +#if defined(OS_WIN) |
| + FilePath file_to_find(ASCIIToUTF16(filename)); |
| +#elif defined(OS_POSIX) |
| + FilePath file_to_find(filename); |
| +#endif |
| + |
| + // Disallow peeking outside of the pnacl component directory. |
| + if (file_to_find.ReferencesParent() || file_to_find.IsAbsolute()) { |
| + LOG(ERROR) << "Cannot open a pnacl file referencing a parent dir, etc."; |
| + NotifyRendererOfError(chrome_render_message_filter, reply_msg); |
| + return; |
| + } |
| + |
| + if (!PathService::Get(chrome::DIR_PNACL_COMPONENT, &pnacl_dir)) { |
| + LOG(ERROR) << "Failed to locate the pnacl install directory"; |
| + NotifyRendererOfError(chrome_render_message_filter, reply_msg); |
| + return; |
| + } |
| + |
| + filepath = pnacl_dir.Append(file_to_find); |
| + |
| + fprintf(stderr, "In DoOpenPnaclFile: %s\n", filepath.MaybeAsASCII().c_str()); |
| + |
| + base::PlatformFileError error_code; |
| + file_to_open = base::CreatePlatformFile(filepath, |
|
Mark Seaborn
2012/02/26 21:02:44
I would expect that won't work properly with autou
|
| + base::PLATFORM_FILE_OPEN | |
| + base::PLATFORM_FILE_READ | |
| + base::PLATFORM_FILE_SHARE_DELETE, |
| + NULL, |
| + &error_code); |
| + if (error_code != base::PLATFORM_FILE_OK) { |
| + LOG(ERROR) << "Failed to open Pnacl file \"" |
| + << filepath.LossyDisplayName() |
| + << "\": " << error_code; |
| + NotifyRendererOfError(chrome_render_message_filter, reply_msg); |
| + return; |
| + } |
| + |
| + // Send the reply! |
| + // Do any DuplicateHandle magic that is necessary first. |
| + nacl::FileDescriptor target_desc; |
| + SendHandleToNaClPlugin(chrome_render_message_filter->peer_handle(), |
| + file_to_open, |
| + true /* Close source */, |
| + &target_desc); |
| + ChromeViewHostMsg_GetReadonlyPnaclFD::WriteReplyParams( |
| + reply_msg, target_desc); |
| + chrome_render_message_filter->Send(reply_msg); |
| +} |
| + |
| +} |