Index: components/nacl/browser/pnacl_host.cc |
diff --git a/components/nacl/browser/pnacl_host.cc b/components/nacl/browser/pnacl_host.cc |
index 0bb7962fb6c0c4dbfe0ff6e72fa17b9892d7a520..8db0231d520715a2648861c76b6f2223dcad5cd0 100644 |
--- a/components/nacl/browser/pnacl_host.cc |
+++ b/components/nacl/browser/pnacl_host.cc |
@@ -26,15 +26,50 @@ static const base::FilePath::CharType kTranslationCacheDirectoryName[] = |
// Delay to wait for initialization of the cache backend |
static const int kTranslationCacheInitializationDelayMs = 20; |
-void CloseBaseFile(base::File file) { |
- // Not really needed because the file will go out of scope here. |
- file.Close(); |
+void CloseBaseFile(base::File auto_file_closer) { |
} |
+void CloseScopedFile(scoped_ptr<base::File> auto_file_closer) { |
} |
+} // namespace |
+ |
namespace pnacl { |
+class FileProxy { |
+ public: |
+ FileProxy(scoped_ptr<base::File> file, base::WeakPtr<pnacl::PnaclHost> host); |
+ int Write(scoped_refptr<net::DrainableIOBuffer> buffer); |
+ void WriteDone(const PnaclHost::TranslationID& id, int result); |
+ |
+ private: |
+ scoped_ptr<base::File> file_; |
+ base::WeakPtr<pnacl::PnaclHost> host_; |
+}; |
+ |
+FileProxy::FileProxy(scoped_ptr<base::File> file, |
+ base::WeakPtr<pnacl::PnaclHost> host) |
+ : file_(file.Pass()), |
+ host_(host) { |
+} |
+ |
+int FileProxy::Write(scoped_refptr<net::DrainableIOBuffer> buffer) { |
+ int rv = file_->Write(0, buffer->data(), buffer->size()); |
+ if (rv == -1) |
+ PLOG(ERROR) << "FileProxy::Write error"; |
+ return rv; |
+} |
+ |
+void FileProxy::WriteDone(const PnaclHost::TranslationID& id, int result) { |
+ if (host_) { |
+ host_->OnBufferCopiedToTempFile(id, file_.Pass(), result); |
+ } else { |
+ BrowserThread::PostBlockingPoolTask( |
+ FROM_HERE, |
+ base::Bind(CloseScopedFile, Passed(&file_))); |
+ } |
+} |
+ |
PnaclHost::PnaclHost() |
: pending_backend_operations_(0), |
cache_state_(CacheUninitialized), |
@@ -47,19 +82,26 @@ PnaclHost::~PnaclHost() { |
(void)cache; |
} |
-PnaclHost* PnaclHost::GetInstance() { return Singleton<PnaclHost>::get(); } |
+PnaclHost* PnaclHost::GetInstance() { |
+ return Singleton<PnaclHost>::get(); |
+} |
PnaclHost::PendingTranslation::PendingTranslation() |
: process_handle(base::kNullProcessHandle), |
render_view_id(0), |
- nexe_fd(base::kInvalidPlatformFileValue), |
+ nexe_fd(NULL), |
got_nexe_fd(false), |
got_cache_reply(false), |
got_cache_hit(false), |
is_incognito(false), |
callback(NexeFdCallback()), |
- cache_info(nacl::PnaclCacheInfo()) {} |
-PnaclHost::PendingTranslation::~PendingTranslation() {} |
+ cache_info(nacl::PnaclCacheInfo()) { |
+} |
+ |
+PnaclHost::PendingTranslation::~PendingTranslation() { |
+ if (nexe_fd) |
+ delete nexe_fd; |
+} |
bool PnaclHost::TranslationMayBeCached( |
const PendingTranslationMap::iterator& entry) { |
@@ -219,7 +261,7 @@ void PnaclHost::GetNexeFd(int render_process_id, |
std::string cache_key(disk_cache_->GetKey(cache_info)); |
if (cache_key.empty()) { |
LOG(ERROR) << "GetNexeFd: Invalid cache info"; |
- cb.Run(base::kInvalidPlatformFileValue, false); |
+ cb.Run(base::File(), false); |
return; |
} |
@@ -296,7 +338,7 @@ void PnaclHost::OnTempFileReturn(const TranslationID& id, |
// waiting for its result. |
LOG(ERROR) << "OnTempFileReturn: temp file creation failed"; |
std::string key(entry->second.cache_key); |
- entry->second.callback.Run(base::kInvalidPlatformFileValue, false); |
+ entry->second.callback.Run(base::File(), false); |
bool may_be_cached = TranslationMayBeCached(entry); |
pending_translations_.erase(entry); |
// No translations will be waiting for entries that will not be stored. |
@@ -306,7 +348,7 @@ void PnaclHost::OnTempFileReturn(const TranslationID& id, |
} |
PendingTranslation* pt = &entry->second; |
pt->got_nexe_fd = true; |
- pt->nexe_fd = file.TakePlatformFile(); |
+ pt->nexe_fd = new base::File(file.Pass()); |
CheckCacheQueryReady(entry); |
} |
@@ -339,15 +381,19 @@ void PnaclHost::CheckCacheQueryReady( |
return; |
} |
+ scoped_ptr<base::File> file(pt->nexe_fd); |
+ pt->nexe_fd = NULL; |
+ pt->got_nexe_fd = false; |
+ FileProxy* proxy(new FileProxy(file.Pass(), weak_factory_.GetWeakPtr())); |
+ |
if (!base::PostTaskAndReplyWithResult( |
BrowserThread::GetBlockingPool(), |
FROM_HERE, |
- base::Bind( |
- &PnaclHost::CopyBufferToFile, pt->nexe_fd, pt->nexe_read_buffer), |
- base::Bind(&PnaclHost::OnBufferCopiedToTempFile, |
- weak_factory_.GetWeakPtr(), |
+ base::Bind(&FileProxy::Write, base::Unretained(proxy), |
+ pt->nexe_read_buffer), |
+ base::Bind(&FileProxy::WriteDone, base::Owned(proxy), |
entry->first))) { |
- pt->callback.Run(base::kInvalidPlatformFileValue, false); |
+ pt->callback.Run(base::File(), false); |
} |
} |
@@ -357,29 +403,28 @@ void PnaclHost::ReturnMiss(const PendingTranslationMap::iterator& entry) { |
// Return the fd |
PendingTranslation* pt = &entry->second; |
NexeFdCallback cb(pt->callback); |
- if (pt->nexe_fd == base::kInvalidPlatformFileValue) { |
- // Bad FD is unrecoverable, so clear out the entry |
+ cb.Run(*pt->nexe_fd, false); |
+ if (!pt->nexe_fd->IsValid()) { |
+ // Bad FD is unrecoverable, so clear out the entry. |
pending_translations_.erase(entry); |
} |
- cb.Run(pt->nexe_fd, false); |
} |
// On error, just return a null refptr. |
// static |
scoped_refptr<net::DrainableIOBuffer> PnaclHost::CopyFileToBuffer( |
- base::PlatformFile fd) { |
- base::PlatformFileInfo info; |
+ scoped_ptr<base::File> file) { |
+ base::File::Info info; |
scoped_refptr<net::DrainableIOBuffer> buffer; |
bool error = false; |
- if (!base::GetPlatformFileInfo(fd, &info) || |
+ if (!file->GetInfo(&info) || |
info.size >= std::numeric_limits<int>::max()) { |
- PLOG(ERROR) << "GetPlatformFileInfo failed"; |
+ PLOG(ERROR) << "File::GetInfo failed"; |
error = true; |
} else { |
buffer = new net::DrainableIOBuffer( |
new net::IOBuffer(static_cast<int>(info.size)), info.size); |
- if (base::ReadPlatformFile(fd, 0, buffer->data(), buffer->size()) != |
- info.size) { |
+ if (file->Read(0, buffer->data(), buffer->size()) != info.size) { |
PLOG(ERROR) << "CopyFileToBuffer file read failed"; |
error = true; |
} |
@@ -387,7 +432,6 @@ scoped_refptr<net::DrainableIOBuffer> PnaclHost::CopyFileToBuffer( |
if (error) { |
buffer = NULL; |
} |
- base::ClosePlatformFile(fd); |
return buffer; |
} |
@@ -414,24 +458,30 @@ void PnaclHost::TranslationFinished(int render_process_id, |
if (!entry->second.got_nexe_fd || !entry->second.got_cache_reply || |
!success || !TranslationMayBeCached(entry)) { |
store_nexe = false; |
- } else if (!base::PostTaskAndReplyWithResult( |
- BrowserThread::GetBlockingPool(), |
- FROM_HERE, |
- base::Bind(&PnaclHost::CopyFileToBuffer, |
- entry->second.nexe_fd), |
- base::Bind(&PnaclHost::StoreTranslatedNexe, |
- weak_factory_.GetWeakPtr(), |
- id))) { |
- store_nexe = false; |
+ } else { |
+ scoped_ptr<base::File> file(entry->second.nexe_fd); |
+ entry->second.nexe_fd = NULL; |
+ entry->second.got_nexe_fd = false; |
+ |
+ if (!base::PostTaskAndReplyWithResult( |
+ BrowserThread::GetBlockingPool(), |
+ FROM_HERE, |
+ base::Bind(&PnaclHost::CopyFileToBuffer, Passed(&file)), |
+ base::Bind(&PnaclHost::StoreTranslatedNexe, |
+ weak_factory_.GetWeakPtr(), |
+ id))) { |
+ store_nexe = false; |
+ } |
} |
if (!store_nexe) { |
// If store_nexe is true, the fd will be closed by CopyFileToBuffer. |
if (entry->second.got_nexe_fd) { |
+ scoped_ptr<base::File> file(entry->second.nexe_fd); |
+ entry->second.nexe_fd = NULL; |
BrowserThread::PostBlockingPoolTask( |
FROM_HERE, |
- base::Bind(base::IgnoreResult(base::ClosePlatformFile), |
- entry->second.nexe_fd)); |
+ base::Bind(CloseScopedFile, Passed(&file))); |
} |
pending_translations_.erase(entry); |
} |
@@ -507,38 +557,31 @@ void PnaclHost::RequeryMatchingTranslations(const std::string& key) { |
//////////////////// GetNexeFd hit path |
-// static |
-int PnaclHost::CopyBufferToFile(base::PlatformFile fd, |
- scoped_refptr<net::DrainableIOBuffer> buffer) { |
- int rv = base::WritePlatformFile(fd, 0, buffer->data(), buffer->size()); |
- if (rv == -1) |
- PLOG(ERROR) << "CopyBufferToFile write error"; |
- return rv; |
-} |
- |
void PnaclHost::OnBufferCopiedToTempFile(const TranslationID& id, |
+ scoped_ptr<base::File> file, |
int file_error) { |
DCHECK(thread_checker_.CalledOnValidThread()); |
PendingTranslationMap::iterator entry(pending_translations_.find(id)); |
if (entry == pending_translations_.end()) { |
+ BrowserThread::PostBlockingPoolTask( |
+ FROM_HERE, |
+ base::Bind(CloseScopedFile, Passed(&file))); |
return; |
} |
if (file_error == -1) { |
// Write error on the temp file. Request a new file and start over. |
BrowserThread::PostBlockingPoolTask( |
FROM_HERE, |
- base::Bind(base::IgnoreResult(base::ClosePlatformFile), |
- entry->second.nexe_fd)); |
- entry->second.got_nexe_fd = false; |
+ base::Bind(CloseScopedFile, Passed(&file))); |
CreateTemporaryFile(base::Bind(&PnaclHost::OnTempFileReturn, |
weak_factory_.GetWeakPtr(), |
entry->first)); |
return; |
} |
- base::PlatformFile fd = entry->second.nexe_fd; |
- entry->second.callback.Run(fd, true); |
+ entry->second.callback.Run(*file.get(), true); |
BrowserThread::PostBlockingPoolTask( |
- FROM_HERE, base::Bind(base::IgnoreResult(base::ClosePlatformFile), fd)); |
+ FROM_HERE, |
+ base::Bind(CloseScopedFile, Passed(&file))); |
pending_translations_.erase(entry); |
} |
@@ -553,10 +596,11 @@ void PnaclHost::RendererClosing(int render_process_id) { |
PendingTranslationMap::iterator to_erase(it++); |
if (to_erase->first.first == render_process_id) { |
// Clean up the open files. |
+ scoped_ptr<base::File> file(to_erase->second.nexe_fd); |
+ to_erase->second.nexe_fd = NULL; |
BrowserThread::PostBlockingPoolTask( |
FROM_HERE, |
- base::Bind(base::IgnoreResult(base::ClosePlatformFile), |
- to_erase->second.nexe_fd)); |
+ base::Bind(CloseScopedFile, Passed(&file))); |
std::string key(to_erase->second.cache_key); |
bool may_be_cached = TranslationMayBeCached(to_erase); |
pending_translations_.erase(to_erase); |