Commit 9a80715b authored by jvoung@google.com's avatar jvoung@google.com

Add an interface for nacl to create delete-on-close temp files,

to be used by pnacl for scratch files during compilation and linking.

This is in-lieu of the current use of pepper temp files, which are not
allowed in incognito mode, and are more cumbersome to clean up on surfaway.

Use this interface for the .o file in pnacl coordinator.  The .nexe still uses
pepper temp files, since we haven't moved that over for caching yet.
We will clean that up later.

Also do some crude quota enforcement for these files, using the
existing reverse service interface.

BUG= http://code.google.com/p/nativeclient/issues/detail?id=2683
TEST= none -- pnacl compilation still works

Review URL: https://chromiumcodereview.appspot.com/10815080

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@148964 0039d316-1c4b-4281-b951-d872f2087c98
parent b1186477
......@@ -76,6 +76,46 @@ void DoOpenPnaclFile(
chrome_render_message_filter->Send(reply_msg);
}
void DoCreateTemporaryFile(
ChromeRenderMessageFilter* chrome_render_message_filter,
IPC::Message* reply_msg) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
FilePath file_path;
if (!file_util::CreateTemporaryFile(&file_path)) {
NotifyRendererOfError(chrome_render_message_filter, reply_msg);
return;
}
base::PlatformFileError error;
base::PlatformFile file_handle = base::CreatePlatformFile(
file_path,
base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_READ |
base::PLATFORM_FILE_WRITE | base::PLATFORM_FILE_TEMPORARY |
base::PLATFORM_FILE_DELETE_ON_CLOSE,
NULL, &error);
if (error != base::PLATFORM_FILE_OK) {
NotifyRendererOfError(chrome_render_message_filter, reply_msg);
return;
}
// Send the reply!
// Do any DuplicateHandle magic that is necessary first.
IPC::PlatformFileForTransit target_desc =
IPC::GetFileHandleForProcess(file_handle,
chrome_render_message_filter->peer_handle(),
true);
if (target_desc == IPC::InvalidPlatformFileForTransit()) {
NotifyRendererOfError(chrome_render_message_filter, reply_msg);
return;
}
ChromeViewHostMsg_NaClCreateTemporaryFile::WriteReplyParams(
reply_msg, target_desc);
chrome_render_message_filter->Send(reply_msg);
}
} // namespace
namespace pnacl_file_host {
......@@ -135,4 +175,16 @@ bool PnaclCanOpenFile(const std::string& filename,
return true;
}
void CreateTemporaryFile(
ChromeRenderMessageFilter* chrome_render_message_filter,
IPC::Message* reply_msg) {
if (!BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
base::Bind(&DoCreateTemporaryFile,
make_scoped_refptr(chrome_render_message_filter),
reply_msg))) {
NotifyRendererOfError(chrome_render_message_filter, reply_msg);
}
}
} // namespace pnacl_file_host
......@@ -28,6 +28,12 @@ void GetReadonlyPnaclFd(ChromeRenderMessageFilter* chrome_render_message_filter,
bool PnaclCanOpenFile(const std::string& filename,
FilePath* file_to_open);
// Creates a temporary file that will be deleted when the last handle
// is closed, or earlier.
void CreateTemporaryFile(
ChromeRenderMessageFilter* chrome_render_message_filter,
IPC::Message* reply_msg);
} // namespace pnacl_file_host
#endif // CHROME_BROWSER_NACL_HOST_PNACL_FILE_HOST_H_
......@@ -76,6 +76,8 @@ bool ChromeRenderMessageFilter::OnMessageReceived(const IPC::Message& message,
IPC_MESSAGE_HANDLER_DELAY_REPLY(ChromeViewHostMsg_LaunchNaCl, OnLaunchNaCl)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ChromeViewHostMsg_GetReadonlyPnaclFD,
OnGetReadonlyPnaclFd)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ChromeViewHostMsg_NaClCreateTemporaryFile,
OnNaClCreateTemporaryFile)
#endif
IPC_MESSAGE_HANDLER(ChromeViewHostMsg_DnsPrefetch, OnDnsPrefetch)
IPC_MESSAGE_HANDLER(ChromeViewHostMsg_ResourceTypeStats,
......@@ -179,6 +181,11 @@ void ChromeRenderMessageFilter::OnGetReadonlyPnaclFd(
// block until the reply is sent.
pnacl_file_host::GetReadonlyPnaclFd(this, filename, reply_msg);
}
void ChromeRenderMessageFilter::OnNaClCreateTemporaryFile(
IPC::Message* reply_msg) {
pnacl_file_host::CreateTemporaryFile(this, reply_msg);
}
#endif
void ChromeRenderMessageFilter::OnDnsPrefetch(
......
......@@ -78,6 +78,7 @@ class ChromeRenderMessageFilter : public content::BrowserMessageFilter {
IPC::Message* reply_msg);
void OnGetReadonlyPnaclFd(const std::string& filename,
IPC::Message* reply_msg);
void OnNaClCreateTemporaryFile(IPC::Message* reply_msg);
#endif
void OnDnsPrefetch(const std::vector<std::string>& hostnames);
void OnResourceTypeStats(const WebKit::WebCache::ResourceTypeStats& stats);
......
......@@ -495,12 +495,17 @@ IPC_SYNC_MESSAGE_CONTROL2_2(ChromeViewHostMsg_LaunchNaCl,
/* imc channel handles */,
IPC::ChannelHandle /* ipc_channel_handle */)
// A renderer sends this to the browser process when it wants to start
// A renderer sends this to the browser process when it wants to
// open a file for from the Pnacl component directory.
IPC_SYNC_MESSAGE_CONTROL1_1(ChromeViewHostMsg_GetReadonlyPnaclFD,
std::string /* name of requested PNaCl file */,
IPC::PlatformFileForTransit /* output file */)
// A renderer sends this to the browser process when it wants to
// create a temporary file.
IPC_SYNC_MESSAGE_CONTROL0_1(ChromeViewHostMsg_NaClCreateTemporaryFile,
IPC::PlatformFileForTransit /* out file */)
// Notification that the page has an OpenSearch description document
// associated with it.
IPC_MESSAGE_ROUTED3(ChromeViewHostMsg_PageHasOSDD,
......
......@@ -6,11 +6,6 @@
#ifndef DISABLE_NACL
#if defined(OS_WIN)
#include <fcntl.h>
#include <io.h>
#endif
#include "base/command_line.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
......@@ -24,6 +19,7 @@
#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/render_view.h"
#include "ipc/ipc_sync_message_filter.h"
#include "ppapi/c/private/pp_file_handle.h"
#include "ppapi/c/private/ppb_nacl_private.h"
#include "ppapi/native_client/src/trusted/plugin/nacl_entry_points.h"
#include "ppapi/proxy/host_dispatcher.h"
......@@ -265,7 +261,7 @@ int BrokerDuplicateHandle(void* source_handle,
#endif
}
int GetReadonlyPnaclFD(const char* filename) {
PP_FileHandle GetReadonlyPnaclFD(const char* filename) {
IPC::PlatformFileForTransit out_fd = IPC::InvalidPlatformFileForTransit();
IPC::Sender* sender = content::RenderThread::Get();
if (sender == NULL)
......@@ -274,29 +270,36 @@ int GetReadonlyPnaclFD(const char* filename) {
if (!sender->Send(new ChromeViewHostMsg_GetReadonlyPnaclFD(
std::string(filename),
&out_fd))) {
return -1;
return base::kInvalidPlatformFileValue;
}
if (out_fd == IPC::InvalidPlatformFileForTransit()) {
return -1;
return base::kInvalidPlatformFileValue;
}
base::PlatformFile handle =
IPC::PlatformFileForTransitToPlatformFile(out_fd);
#if defined(OS_WIN)
int posix_desc = _open_osfhandle(reinterpret_cast<intptr_t>(handle),
_O_RDONLY | _O_BINARY);
if (posix_desc == -1) {
// Close the Windows HANDLE if it can't be converted.
CloseHandle(handle);
return -1;
return handle;
}
PP_FileHandle CreateTemporaryFile(PP_Instance instance) {
IPC::PlatformFileForTransit transit_fd = IPC::InvalidPlatformFileForTransit();
IPC::Sender* sender = content::RenderThread::Get();
if (sender == NULL)
sender = g_background_thread_sender.Pointer()->get();
if (!sender->Send(new ChromeViewHostMsg_NaClCreateTemporaryFile(
&transit_fd))) {
return base::kInvalidPlatformFileValue;
}
if (transit_fd == IPC::InvalidPlatformFileForTransit()) {
return base::kInvalidPlatformFileValue;
}
return posix_desc;
#elif defined(OS_POSIX)
base::PlatformFile handle = IPC::PlatformFileForTransitToPlatformFile(
transit_fd);
return handle;
#else
#error "GetReadonlyPnaclFD: Don't know how to convert FileDescriptor to native."
#endif
}
const PPB_NaCl_Private nacl_interface = {
......@@ -306,7 +309,8 @@ const PPB_NaCl_Private nacl_interface = {
&Are3DInterfacesDisabled,
&EnableBackgroundSelLdrLaunch,
&BrokerDuplicateHandle,
&GetReadonlyPnaclFD
&GetReadonlyPnaclFD,
&CreateTemporaryFile
};
} // namespace
......
......@@ -5,8 +5,10 @@
/* This file contains NaCl private interfaces. */
#include "ppapi/c/private/pp_file_handle.h"
/* PPB_NaCl_Private */
interface PPB_NaCl_Private_0_6 {
interface PPB_NaCl_Private_0_7 {
/* This function launches NaCl's sel_ldr process. On success, the function
* returns true, otherwise it returns false. When it returns true, it will
* write |socket_count| nacl::Handles to imc_handles.
......@@ -37,5 +39,11 @@ interface PPB_NaCl_Private_0_6 {
* Do we want this to take a completion callback and be async, or
* could we make this happen on another thread?
*/
int32_t GetReadonlyPnaclFd([in] str_t filename);
PP_FileHandle GetReadonlyPnaclFd([in] str_t filename);
/* This creates a temporary file that will be deleted by the time
* the last handle is closed (or earlier on POSIX systems), and
* returns a posix handle to that temporary file.
*/
PP_FileHandle CreateTemporaryFile([in] PP_Instance instance);
};
......@@ -3,7 +3,7 @@
* found in the LICENSE file.
*/
/* From private/pp_file_handle.idl modified Thu Jul 26 10:46:37 2012. */
/* From private/pp_file_handle.idl modified Fri Jul 27 17:01:41 2012. */
#ifndef PPAPI_C_PRIVATE_PP_FILE_HANDLE_H_
#define PPAPI_C_PRIVATE_PP_FILE_HANDLE_H_
......
......@@ -9,8 +9,9 @@
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_resource.h"
#include "ppapi/c/pp_stdint.h"
#include "ppapi/c/private/pp_file_handle.h"
#define PPB_NACL_PRIVATE_INTERFACE "PPB_NaCl(Private);0.6"
#define PPB_NACL_PRIVATE_INTERFACE "PPB_NaCl(Private);0.7"
struct PPB_NaCl_Private {
// This function launches NaCl's sel_ldr process. On success, the function
......@@ -59,7 +60,12 @@ struct PPB_NaCl_Private {
// component directory, or -1 on error.
// Do we want this to take a completion callback and be async, or
// or could we make this happen on another thread?
int (*GetReadonlyPnaclFd)(const char* filename);
PP_FileHandle (*GetReadonlyPnaclFd)(const char* filename);
// This creates a temporary file that will be deleted by the time
// the last handle is closed (or earlier on POSIX systems), and
// returns a posix handle to that temporary file.
PP_FileHandle (*CreateTemporaryFile)(PP_Instance instance);
};
#endif // PPAPI_C_PRIVATE_PPB_NACL_PRIVATE_H_
# -*- python -*-
# Copyright (c) 2011 The Native Client Authors. All rights reserved.
# Copyright (c) 2012 The Native Client Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
......@@ -72,6 +72,7 @@ common_inputs = [
'service_runtime.cc',
'srpc_client.cc',
'srpc_params.cc',
'temporary_file.cc',
'utility.cc',
]
......
......@@ -239,4 +239,4 @@ void LocalTempFile::FinishRename() {
old_ref_.reset(NULL);
}
} // namespace plugin
} // namespace plugin
......@@ -128,6 +128,6 @@ class LocalTempFile {
static uint32_t next_identifier;
};
} // namespace plugin
} // namespace plugin
#endif // NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_LOCAL_TEMP_FILE_H_
......@@ -22,6 +22,7 @@
'service_runtime.cc',
'srpc_client.cc',
'srpc_params.cc',
'temporary_file.cc',
'utility.cc',
],
# Append the arch-specific ISA code to common_sources.
......
......@@ -319,6 +319,8 @@ class Plugin : public pp::InstancePrivate {
return main_service_runtime()->exit_status();
}
const PPB_NaCl_Private* nacl_interface() { return nacl_interface_; }
private:
NACL_DISALLOW_COPY_AND_ASSIGN(Plugin);
// Prevent construction and destruction from outside the class:
......
......@@ -16,6 +16,7 @@
#include "native_client/src/trusted/plugin/pnacl_streaming_translate_thread.h"
#include "native_client/src/trusted/plugin/pnacl_translate_thread.h"
#include "native_client/src/trusted/plugin/service_runtime.h"
#include "native_client/src/trusted/plugin/temporary_file.h"
#include "native_client/src/trusted/service_runtime/include/sys/stat.h"
#include "ppapi/c/pp_errors.h"
......@@ -304,32 +305,6 @@ void PnaclCoordinator::TranslateFinished(int32_t pp_error) {
// the one from the compiler, (which is always just PP_ERROR_FAILED)
if (translate_finish_error_ == PP_OK) translate_finish_error_ = pp_error;
// Close the object temporary file (regardless of error code).
pp::CompletionCallback cb =
callback_factory_.NewCallback(&PnaclCoordinator::ObjectFileWasClosed);
obj_file_->Close(cb);
}
void PnaclCoordinator::ObjectFileWasClosed(int32_t pp_error) {
PLUGIN_PRINTF(("PnaclCoordinator::ObjectFileWasClosed (pp_error=%"
NACL_PRId32")\n", pp_error));
if (pp_error != PP_OK) {
ReportPpapiError(pp_error);
return;
}
// Delete the object temporary file.
pp::CompletionCallback cb =
callback_factory_.NewCallback(&PnaclCoordinator::ObjectFileWasDeleted);
obj_file_->Delete(cb);
}
void PnaclCoordinator::ObjectFileWasDeleted(int32_t pp_error) {
PLUGIN_PRINTF(("PnaclCoordinator::ObjectFileWasDeleted (pp_error=%"
NACL_PRId32")\n", pp_error));
if (pp_error != PP_OK) {
ReportPpapiError(pp_error);
return;
}
// Close the nexe temporary file.
if (nexe_file_ != NULL) {
pp::CompletionCallback cb =
......@@ -474,11 +449,10 @@ void PnaclCoordinator::CachedFileDidOpen(int32_t pp_error) {
// translator can start writing to it during streaming translation.
// In the non-streaming case this can wait until the bitcode download is
// finished.
obj_file_.reset(new LocalTempFile(plugin_, file_system_.get(),
nacl::string(kPnaclTempDir)));
obj_file_.reset(new TempFile(plugin_));
pp::CompletionCallback obj_cb =
callback_factory_.NewCallback(&PnaclCoordinator::ObjectWriteDidOpen);
obj_file_->OpenWrite(obj_cb);
callback_factory_.NewCallback(&PnaclCoordinator::ObjectFileDidOpen);
obj_file_->Open(obj_cb);
streaming_downloader_.reset(new FileDownloader());
streaming_downloader_->Initialize(plugin_);
......@@ -521,20 +495,8 @@ StreamCallback PnaclCoordinator::GetCallback() {
&PnaclCoordinator::BitcodeStreamGotData);
}
void PnaclCoordinator::ObjectWriteDidOpen(int32_t pp_error) {
PLUGIN_PRINTF(("PnaclCoordinator::ObjectWriteDidOpen (pp_error=%"
NACL_PRId32")\n", pp_error));
if (pp_error != PP_OK) {
ReportPpapiError(pp_error);
return;
}
pp::CompletionCallback cb =
callback_factory_.NewCallback(&PnaclCoordinator::ObjectReadDidOpen);
obj_file_->OpenRead(cb);
}
void PnaclCoordinator::ObjectReadDidOpen(int32_t pp_error) {
PLUGIN_PRINTF(("PnaclCoordinator::ObjectReadDidOpen (pp_error=%"
void PnaclCoordinator::ObjectFileDidOpen(int32_t pp_error) {
PLUGIN_PRINTF(("PnaclCoordinator::ObjectFileDidOpen (pp_error=%"
NACL_PRId32")\n", pp_error));
if (pp_error != PP_OK) {
ReportPpapiError(pp_error);
......
......@@ -38,6 +38,7 @@ class Manifest;
class Plugin;
class PnaclCoordinator;
class PnaclTranslateThread;
class TempFile;
// A class invoked by Plugin to handle PNaCl client-side translation.
// Usage:
......@@ -153,13 +154,7 @@ class PnaclCoordinator: public CallbackSource<FileStreamData> {
// Invoked when the pexe download finishes (using streaming translation)
void BitcodeStreamDidFinish(int32_t pp_error);
// Invoked when the write descriptor for obj_file_ is created.
void ObjectWriteDidOpen(int32_t pp_error);
// Invoked when the read descriptor for obj_file_ is created.
void ObjectReadDidOpen(int32_t pp_error);
// Invoked when the descriptors for obj_file_ have been closed.
void ObjectFileWasClosed(int32_t pp_error);
// Invoked when the obj_file_ temporary has been deleted.
void ObjectFileWasDeleted(int32_t pp_error);
void ObjectFileDidOpen(int32_t pp_error);
// Invoked when the descriptors for nexe_file_ have been closed.
void NexeFileWasClosed(int32_t pp_error);
// Invoked when the nexe_file_ temporary has been renamed to the nexe name.
......@@ -213,7 +208,7 @@ class PnaclCoordinator: public CallbackSource<FileStreamData> {
// Optional cache identity for translation caching.
nacl::string cache_identity_;
// Object file, produced by the translator and consumed by the linker.
nacl::scoped_ptr<LocalTempFile> obj_file_;
nacl::scoped_ptr<TempFile> obj_file_;
// Translated nexe file, produced by the linker and consumed by sel_ldr.
nacl::scoped_ptr<LocalTempFile> nexe_file_;
......
......@@ -8,6 +8,7 @@
#include "native_client/src/trusted/plugin/plugin.h"
#include "native_client/src/trusted/plugin/pnacl_resources.h"
#include "native_client/src/trusted/plugin/srpc_params.h"
#include "native_client/src/trusted/plugin/temporary_file.h"
namespace plugin {
......@@ -22,7 +23,7 @@ void PnaclStreamingTranslateThread::RunTranslate(
const pp::CompletionCallback& finish_callback,
const Manifest* manifest,
const Manifest* ld_manifest,
LocalTempFile* obj_file,
TempFile* obj_file,
LocalTempFile* nexe_file,
ErrorInfo* error_info,
PnaclResources* resources,
......@@ -98,11 +99,10 @@ void PnaclStreamingTranslateThread::DoTranslate() {
}
// Run LLC.
SrpcParams params;
nacl::DescWrapper* llc_out_file = obj_file_->write_wrapper();
nacl::DescWrapper* llc_out_file = obj_file_->get_wrapper();
PluginReverseInterface* llc_reverse =
llc_subprocess->service_runtime()->rev_interface();
llc_reverse->AddQuotaManagedFile(obj_file_->identifier(),
obj_file_->write_file_io());
llc_reverse->AddTempQuotaManagedFile(obj_file_->identifier());
if (!llc_subprocess->InvokeSrpcMethod("StreamInit",
"h",
......
......@@ -24,7 +24,7 @@ class PnaclStreamingTranslateThread : public PnaclTranslateThread {
virtual void RunTranslate(const pp::CompletionCallback& finish_callback,
const Manifest* manifest,
const Manifest* ld_manifest,
LocalTempFile* obj_file,
TempFile* obj_file,
LocalTempFile* nexe_file,
ErrorInfo* error_info,
PnaclResources* resources,
......
......@@ -8,6 +8,7 @@
#include "native_client/src/trusted/plugin/plugin.h"
#include "native_client/src/trusted/plugin/pnacl_resources.h"
#include "native_client/src/trusted/plugin/srpc_params.h"
#include "native_client/src/trusted/plugin/temporary_file.h"
#include "native_client/src/trusted/plugin/utility.h"
namespace plugin {
......@@ -60,7 +61,13 @@ bool PnaclTranslateThread::RunLdSubprocess(int is_shared_library,
}
// Run LD.
SrpcParams params;
nacl::DescWrapper* ld_in_file = obj_file_->read_wrapper();
// Reset object file for reading first.
if (!obj_file_->Reset()) {
TranslateFailed("Link process could not reset object file");
return false;
}
nacl::DescWrapper* ld_in_file = obj_file_->get_wrapper();
nacl::DescWrapper* ld_out_file = nexe_file_->write_wrapper();
PluginReverseInterface* ld_reverse =
ld_subprocess->service_runtime()->rev_interface();
......
......@@ -26,6 +26,7 @@ class Manifest;
class NaClSubprocess;
class Plugin;
class PnaclResources;
class TempFile;
class PnaclTranslateThread {
public:
......@@ -36,7 +37,7 @@ class PnaclTranslateThread {
virtual void RunTranslate(const pp::CompletionCallback& finish_callback,
const Manifest* manifest,
const Manifest* ld_manifest,
LocalTempFile* obj_file,
TempFile* obj_file,
LocalTempFile* nexe_file,
ErrorInfo* error_info,
PnaclResources* resources,
......@@ -75,7 +76,7 @@ class PnaclTranslateThread {
// Data about the translation files, owned by the coordinator
const Manifest* manifest_;
const Manifest* ld_manifest_;
LocalTempFile* obj_file_;
TempFile* obj_file_;
LocalTempFile* nexe_file_;
ErrorInfo* coordinator_error_info_;
PnaclResources* resources_;
......
......@@ -59,6 +59,14 @@
#include "ppapi/cpp/completion_callback.h"
#include "ppapi/cpp/file_io.h"
namespace {
// For doing crude quota enforcement on writes to temp files.
// We do not allow a temp file bigger than 512 MB for now.
const uint64_t kMaxTempQuota = 0x20000000;
} // namespace
namespace plugin {
PluginReverseInterface::PluginReverseInterface(
......@@ -433,23 +441,44 @@ void PluginReverseInterface::QuotaRequest_MainThreadContinuation(
if (err != PP_OK) {
return;
}
const PPB_FileIOTrusted* file_io_trusted =
static_cast<const PPB_FileIOTrusted*>(
pp::Module::Get()->GetBrowserInterface(PPB_FILEIOTRUSTED_INTERFACE));
// Copy the request object because this one will be deleted on return.
QuotaRequest* cont_for_response = new QuotaRequest(*request); // copy ctor!
pp::CompletionCallback quota_cc = WeakRefNewCallback(
anchor_,
this,
&PluginReverseInterface::QuotaRequest_MainThreadResponse,
cont_for_response);
file_io_trusted->WillWrite(request->resource,
request->offset,
// TODO(sehr): remove need for cast.
// Unify WillWrite interface vs Quota request.
nacl::assert_cast<int32_t>(
request->bytes_requested),
quota_cc.pp_completion_callback());
switch (request->data.type) {
case plugin::PepperQuotaType: {
const PPB_FileIOTrusted* file_io_trusted =
static_cast<const PPB_FileIOTrusted*>(
pp::Module::Get()->GetBrowserInterface(
PPB_FILEIOTRUSTED_INTERFACE));
// Copy the request object because this one will be deleted on return.
// copy ctor!
QuotaRequest* cont_for_response = new QuotaRequest(*request);
pp::CompletionCallback quota_cc = WeakRefNewCallback(
anchor_,
this,
&PluginReverseInterface::QuotaRequest_MainThreadResponse,
cont_for_response);
file_io_trusted->WillWrite(request->data.resource,
request->offset,
// TODO(sehr): remove need for cast.
// Unify WillWrite interface vs Quota request.
nacl::assert_cast<int32_t>(
request->bytes_requested),
quota_cc.pp_completion_callback());
break;
}
case plugin::TempQuotaType: {
uint64_t len = request->offset + request->bytes_requested;
nacl::MutexLocker take(&mu_);
// Do some crude quota enforcement.
if (len > kMaxTempQuota) {
*request->bytes_granted = 0;
} else {
*request->bytes_granted = request->bytes_requested;
}
*request->op_complete_ptr = true;
NaClXCondVarBroadcast(&cv_);
break;
}
}
// request automatically deleted
}
......@@ -460,7 +489,8 @@ void PluginReverseInterface::QuotaRequest_MainThreadResponse(
"PluginReverseInterface::QuotaRequest_MainThreadResponse:"
" (resource=%"NACL_PRIx32", offset=%"NACL_PRId64", requested=%"
NACL_PRId64", err=%"NACL_PRId32")\n",
request->resource, request->offset, request->bytes_requested, err);
request->data.resource,
request->offset, request->bytes_requested, err);
nacl::MutexLocker take(&mu_);
if (err >= PP_OK) {
*request->bytes_granted = err;
......@@ -478,7 +508,7 @@ int64_t PluginReverseInterface::RequestQuotaForWrite(
"PluginReverseInterface::RequestQuotaForWrite:"
" (file_id='%s', offset=%"NACL_PRId64", bytes_to_write=%"
NACL_PRId64")\n", file_id.c_str(), offset, bytes_to_write);
PP_Resource resource;
QuotaData quota_data;
{
nacl::MutexLocker take(&mu_);
uint64_t file_key = STRTOULL(file_id.c_str(), NULL, 10);
......@@ -487,13 +517,13 @@ int64_t PluginReverseInterface::RequestQuotaForWrite(
NaClLog(4, "PluginReverseInterface::RequestQuotaForWrite: failed...\n");
return 0;
}
resource = quota_map_[file_key];
quota_data = quota_map_[file_key];
}
// Variables set by requesting quota.
int64_t quota_granted = 0;
bool op_complete = false;
QuotaRequest* continuation =
new QuotaRequest(resource, offset, bytes_to_write, &quota_granted,
new QuotaRequest(quota_data, offset, bytes_to_write, &quota_granted,
&op_complete);
// The reverse service is running on a background thread and the PPAPI quota
// methods must be invoked only from the main thread.
......@@ -529,7 +559,18 @@ void PluginReverseInterface::AddQuotaManagedFile(const nacl::string& file_id,
file_id.c_str(), resource);
nacl::MutexLocker take(&mu_);
uint64_t file_key = STRTOULL(file_id.c_str(), NULL, 10);
quota_map_[file_key] = resource;
QuotaData data(plugin::PepperQuotaType, resource);
quota_map_[file_key] = data;
}
void PluginReverseInterface::AddTempQuotaManagedFile(
const nacl::string& file_id) {
PLUGIN_PRINTF(("PluginReverseInterface::AddTempQuotaManagedFile: "
"(file_id='%s')\n", file_id.c_str()));
nacl::MutexLocker take(&mu_);
uint64_t file_key = STRTOULL(file_id.c_str(), NULL, 10);
QuotaData data(plugin::TempQuotaType, 0);
quota_map_[file_key] = data;
}
ServiceRuntime::ServiceRuntime(Plugin* plugin,
......
......@@ -11,6 +11,8 @@
#ifndef NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_SERVICE_RUNTIME_H_
#define NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_SERVICE_RUNTIME_H_
#include <map>
#include "native_client/src/include/nacl_macros.h"
#include "native_client/src/include/nacl_scoped_ptr.h"
#include "native_client/src/include/nacl_string.h"
......@@ -90,20 +92,35 @@ struct CloseManifestEntryResource {
bool* op_result_ptr;
};
enum QuotaDataType {
PepperQuotaType,
TempQuotaType
};
struct QuotaData {
QuotaData(QuotaDataType type_, PP_Resource resource_)
: type(type_), resource(resource_) {}
QuotaData()
: type(PepperQuotaType), resource(0) {}
QuotaDataType type;
PP_Resource resource;
};
struct QuotaRequest {
public:
QuotaRequest(PP_Resource file_resource,
QuotaRequest(QuotaData quota_data,
int64_t start_offset,
int64_t quota_bytes_requested,
int64_t* quota_bytes_granted,
bool* op_complete)
: resource(file_resource),
: data(quota_data),
offset(start_offset),
bytes_requested(quota_bytes_requested),
bytes_granted(quota_bytes_granted),
op_complete_ptr(op_complete) { }
PP_Resource resource;
QuotaData data;
int64_t offset;
int64_t bytes_requested;
int64_t* bytes_granted;
......@@ -151,6 +168,7 @@ class PluginReverseInterface: public nacl::ReverseInterface {
void AddQuotaManagedFile(const nacl::string& file_id,
const pp::FileIO& file_io);
void AddTempQuotaManagedFile(const nacl::string& file_id);
protected:
virtual void Log_MainThreadContinuation(LogToJavaScriptConsoleResource* p,
......@@ -191,7 +209,7 @@ class PluginReverseInterface: public nacl::ReverseInterface {
ServiceRuntime* service_runtime_;
NaClMutex mu_;
NaClCondVar cv_;
std::map<int64_t, PP_Resource> quota_map_;
std::map<int64_t, QuotaData> quota_map_;
bool shutting_down_;
nacl::scoped_ptr<PnaclCoordinator> pnacl_coordinator_;
......
// 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 "native_client/src/trusted/plugin/temporary_file.h"
#include "native_client/src/include/portability_io.h"
#include "native_client/src/shared/platform/nacl_check.h"
#include "native_client/src/trusted/plugin/plugin.h"
#include "native_client/src/trusted/plugin/utility.h"
#include "native_client/src/trusted/service_runtime/include/sys/stat.h"
#include "ppapi/cpp/core.h"
#include "ppapi/cpp/instance.h"
#include "ppapi/cpp/module.h"
#include "ppapi/c/private/pp_file_handle.h"
//////////////////////////////////////////////////////////////////////
// Temporary file access.
//////////////////////////////////////////////////////////////////////
namespace plugin {
uint32_t TempFile::next_identifier = 0;
TempFile::TempFile(Plugin* plugin) : plugin_(plugin) {
PLUGIN_PRINTF(("TempFile::TempFile\n"));
++next_identifier;
SNPRINTF(reinterpret_cast<char *>(identifier_), sizeof identifier_,
"%"NACL_PRIu32, next_identifier);
}
TempFile::~TempFile() {
PLUGIN_PRINTF(("TempFile::~TempFile\n"));
}
void TempFile::Open(const pp::CompletionCallback& cb) {
PLUGIN_PRINTF(("TempFile::Open\n"));
PP_FileHandle file_handle =
plugin_->nacl_interface()->CreateTemporaryFile(plugin_->pp_instance());
pp::Core* core = pp::Module::Get()->core();
if (file_handle == PP_kInvalidFileHandle) {
PLUGIN_PRINTF(("TempFile::Open failed w/ PP_kInvalidFileHandle\n"));
core->CallOnMainThread(0, cb, PP_ERROR_FAILED);
}
#if NACL_WINDOWS
HANDLE handle = file_handle;
//////// Now try the posix view.
int32_t posix_desc = _open_osfhandle(reinterpret_cast<intptr_t>(handle),
_O_RDWR | _O_BINARY
| _O_TEMPORARY | _O_SHORT_LIVED );
if (posix_desc == -1) {
PLUGIN_PRINTF(("TempFile::Open failed to convert HANDLE to posix\n"));
// Close the Windows HANDLE if it can't be converted.
CloseHandle(handle);
}
int32_t fd = posix_desc;
#else
int32_t fd = file_handle;
#endif
if (fd < 0) {
PLUGIN_PRINTF(("TempFile::Open failed\n"));
core->CallOnMainThread(0, cb, PP_ERROR_FAILED);
return;
}
// The descriptor for a writeable file needs to have quota management.
wrapper_.reset(
plugin_->wrapper_factory()->MakeFileDescQuota(fd, O_RDWR, identifier_));
core->CallOnMainThread(0, cb, PP_OK);
}
bool TempFile::Reset() {
PLUGIN_PRINTF(("TempFile::Reset\n"));
CHECK(wrapper_.get() != NULL);
nacl_off64_t newpos = wrapper_->Seek(0, SEEK_SET);
return newpos >= 0;
}
} // namespace plugin
// 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.
#ifndef NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_TEMPORARY_FILE_H_
#define NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_TEMPORARY_FILE_H_
#include "native_client/src/include/nacl_macros.h"
#include "native_client/src/include/nacl_string.h"
#include "native_client/src/trusted/desc/nacl_desc_wrapper.h"
#include "ppapi/cpp/completion_callback.h"
namespace plugin {
class Plugin;
// Translation creates two temporary files. The first temporary file holds
// the object file created by llc. The second holds the nexe produced by
// the linker. Both of these temporary files are used to both write and
// read according to the following matrix:
//
// PnaclCoordinator::obj_file_:
// written by: llc (passed in explicitly through SRPC)
// read by: ld (returned via lookup service from SRPC)
// PnaclCoordinator::nexe_file_:
// written by: ld (passed in explicitly through SRPC)
// read by: sel_ldr (passed in explicitly to command channel)
//
// TempFile represents a file used as a temporary between stages in
// translation. It is automatically deleted when all handles are closed
// (or earlier -- immediately unlinked on POSIX systems). The file is only
// opened, once, but because both reading and writing are necessary (and in
// different processes), the user should reset / seek back to the beginning
// of the file between sessions.
class TempFile {
public:
// Create a TempFile.
explicit TempFile(Plugin* plugin);
~TempFile();
// Opens a writeable file IO object and descriptor referring to the file.
void Open(const pp::CompletionCallback& cb);
// Resets file position of the handle, for reuse.
bool Reset();
// Accessors.
// The nacl::DescWrapper* for the writeable version of the file.
nacl::DescWrapper* get_wrapper() { return wrapper_.get(); }
nacl::DescWrapper* release_wrapper() {
return wrapper_.release();
}
// For quota management.
const nacl::string identifier() const {
return nacl::string(reinterpret_cast<const char*>(identifier_));
}
private:
NACL_DISALLOW_COPY_AND_ASSIGN(TempFile);
Plugin* plugin_;
nacl::scoped_ptr<nacl::DescWrapper> wrapper_;
// An identifier string used for quota request processing. The quota
// interface needs a string that is unique per sel_ldr instance only, so
// the identifiers can be reused between runs of the translator, start-ups of
// the browser, etc.
uint8_t identifier_[16];
// A counter to dole out unique identifiers.
static uint32_t next_identifier;
};
} // namespace plugin
#endif // NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_TEMPORARY_FILE_H_
......@@ -90,6 +90,7 @@
'c/dev/ppp_zoom_dev.h',
# Private interfaces.
'c/private/pp_file_handle.h',
'c/private/ppb_flash.h',
'c/private/ppb_flash_clipboard.h',
'c/private/ppb_flash_file.h',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment