1ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved. 2ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// found in the LICENSE file. 4ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/nacl/browser/pnacl_host.h" 6ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 7ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/bind.h" 8ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/bind_helpers.h" 9ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/files/file_path.h" 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 11ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/logging.h" 12ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/task_runner_util.h" 13ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/threading/sequenced_worker_pool.h" 140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "components/nacl/browser/nacl_browser.h" 15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/nacl/browser/pnacl_translation_cache.h" 16ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "content/public/browser/browser_thread.h" 17ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "net/base/io_buffer.h" 18ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "net/base/net_errors.h" 19ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 20ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochusing content::BrowserThread; 21ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 22ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace { 23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 24ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic const base::FilePath::CharType kTranslationCacheDirectoryName[] = 25ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch FILE_PATH_LITERAL("PnaclTranslationCache"); 26ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Delay to wait for initialization of the cache backend 27ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochstatic const int kTranslationCacheInitializationDelayMs = 20; 28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void CloseBaseFile(base::File auto_file_closer) { 30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 3246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void CloseScopedFile(scoped_ptr<base::File> auto_file_closer) { 33ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 34ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} // namespace 3646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace pnacl { 38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 3946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class FileProxy { 4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) public: 4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) FileProxy(scoped_ptr<base::File> file, base::WeakPtr<pnacl::PnaclHost> host); 4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) int Write(scoped_refptr<net::DrainableIOBuffer> buffer); 4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) void WriteDone(const PnaclHost::TranslationID& id, int result); 4446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 4546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) private: 4646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<base::File> file_; 4746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::WeakPtr<pnacl::PnaclHost> host_; 4846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}; 4946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 5046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)FileProxy::FileProxy(scoped_ptr<base::File> file, 5146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::WeakPtr<pnacl::PnaclHost> host) 5246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) : file_(file.Pass()), 5346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) host_(host) { 5446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 5546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 5646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)int FileProxy::Write(scoped_refptr<net::DrainableIOBuffer> buffer) { 5746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) int rv = file_->Write(0, buffer->data(), buffer->size()); 5846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (rv == -1) 5946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) PLOG(ERROR) << "FileProxy::Write error"; 6046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return rv; 6146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 6246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 6346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void FileProxy::WriteDone(const PnaclHost::TranslationID& id, int result) { 6446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (host_) { 6546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) host_->OnBufferCopiedToTempFile(id, file_.Pass(), result); 6646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } else { 6746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) BrowserThread::PostBlockingPoolTask( 6846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) FROM_HERE, 6946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(CloseScopedFile, Passed(&file_))); 7046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 7146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 7246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 73ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochPnaclHost::PnaclHost() 741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) : pending_backend_operations_(0), 751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) cache_state_(CacheUninitialized), 761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) weak_factory_(this) {} 771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)PnaclHost::~PnaclHost() { 791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // When PnaclHost is destroyed, it's too late to post anything to the cache 801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // thread (it will hang shutdown). So just leak the cache backend. 811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) pnacl::PnaclTranslationCache* cache = disk_cache_.release(); 821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) (void)cache; 831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 84ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 8546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)PnaclHost* PnaclHost::GetInstance() { 8646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return Singleton<PnaclHost>::get(); 8746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 88ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 89ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochPnaclHost::PendingTranslation::PendingTranslation() 90ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch : process_handle(base::kNullProcessHandle), 91ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch render_view_id(0), 9246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) nexe_fd(NULL), 93ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch got_nexe_fd(false), 94ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch got_cache_reply(false), 95ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch got_cache_hit(false), 96ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch is_incognito(false), 97ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch callback(NexeFdCallback()), 9846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) cache_info(nacl::PnaclCacheInfo()) { 9946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 10046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 10146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)PnaclHost::PendingTranslation::~PendingTranslation() { 10246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (nexe_fd) 10346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) delete nexe_fd; 10446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 105ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool PnaclHost::TranslationMayBeCached( 10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const PendingTranslationMap::iterator& entry) { 10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return !entry->second.is_incognito && 10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) !entry->second.cache_info.has_no_store_header; 11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 112ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch/////////////////////////////////////// Initialization 113ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 114ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic base::FilePath GetCachePath() { 1150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) NaClBrowserDelegate* browser_delegate = nacl::NaClBrowser::GetDelegate(); 116ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Determine where the translation cache resides in the file system. It 117ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // exists in Chrome's cache directory and is not tied to any specific 118ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // profile. If we fail, return an empty path. 119ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Start by finding the user data directory. 120ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::FilePath user_data_dir; 121ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!browser_delegate || 122ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch !browser_delegate->GetUserDirectory(&user_data_dir)) { 123ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return base::FilePath(); 124ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 125ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // The cache directory may or may not be the user data directory. 126ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::FilePath cache_file_path; 127ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch browser_delegate->GetCacheDirectory(&cache_file_path); 128ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 129ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Append the base file name to the cache directory. 130ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return cache_file_path.Append(kTranslationCacheDirectoryName); 131ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 132ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 133ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid PnaclHost::OnCacheInitialized(int net_error) { 134ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 135ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // If the cache was cleared before the load completed, ignore. 136ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (cache_state_ == CacheReady) 137ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 138ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (net_error != net::OK) { 139ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // This will cause the cache to attempt to re-init on the next call to 140ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // GetNexeFd. 141ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch cache_state_ = CacheUninitialized; 142ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } else { 143ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch cache_state_ = CacheReady; 144ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 145ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 146ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 147ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid PnaclHost::Init() { 148ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Extra check that we're on the real IO thread since this version of 149ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Init isn't used in unit tests. 150ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 151ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 152ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::FilePath cache_path(GetCachePath()); 153ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (cache_path.empty() || cache_state_ != CacheUninitialized) 154ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 155ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch disk_cache_.reset(new pnacl::PnaclTranslationCache()); 156ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch cache_state_ = CacheInitializing; 1571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) int rv = disk_cache_->InitOnDisk( 158ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch cache_path, 159ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::Bind(&PnaclHost::OnCacheInitialized, weak_factory_.GetWeakPtr())); 1601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (rv != net::ERR_IO_PENDING) 1611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) OnCacheInitialized(rv); 162ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 163ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Initialize for testing, optionally using the in-memory backend, and manually 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// setting the temporary file directory instead of using the system directory. 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PnaclHost::InitForTest(base::FilePath temp_dir, bool in_memory) { 167ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 168ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch disk_cache_.reset(new pnacl::PnaclTranslationCache()); 169ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch cache_state_ = CacheInitializing; 170ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch temp_dir_ = temp_dir; 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int rv; 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (in_memory) { 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) rv = disk_cache_->InitInMemory( 174ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::Bind(&PnaclHost::OnCacheInitialized, weak_factory_.GetWeakPtr())); 1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } else { 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) rv = disk_cache_->InitOnDisk( 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) temp_dir, 1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Bind(&PnaclHost::OnCacheInitialized, weak_factory_.GetWeakPtr())); 1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (rv != net::ERR_IO_PENDING) 1811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) OnCacheInitialized(rv); 182ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 183ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 184ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch///////////////////////////////////////// Temp files 185ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 186ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Create a temporary file on the blocking pool 187ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// static 188424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PnaclHost::DoCreateTemporaryFile(base::FilePath temp_dir, 189424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) TempFileCallback cb) { 190ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread()); 191ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 192ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch base::FilePath file_path; 193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::File file; 194ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch bool rv = temp_dir.empty() 195a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ? base::CreateTemporaryFile(&file_path) 196a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) : base::CreateTemporaryFileInDir(temp_dir, &file_path); 197ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!rv) { 1983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) PLOG(ERROR) << "Temp file creation failed."; 199424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } else { 200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) file.Initialize( 201424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) file_path, 202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_READ | 203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::File::FLAG_WRITE | base::File::FLAG_TEMPORARY | 204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::File::FLAG_DELETE_ON_CLOSE); 205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!file.IsValid()) 207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) PLOG(ERROR) << "Temp file open failed: " << file.error_details(); 208ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 209424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) BrowserThread::PostTask( 210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) BrowserThread::IO, FROM_HERE, base::Bind(cb, Passed(file.Pass()))); 211ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 212ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 213ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid PnaclHost::CreateTemporaryFile(TempFileCallback cb) { 214424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!BrowserThread::PostBlockingPoolSequencedTask( 215424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) "PnaclHostCreateTempFile", 216424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) FROM_HERE, 217424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) base::Bind(&PnaclHost::DoCreateTemporaryFile, temp_dir_, cb))) { 218ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) cb.Run(base::File()); 220ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 221ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 222ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 223ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch///////////////////////////////////////// GetNexeFd implementation 224ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch////////////////////// Common steps 225ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 226ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid PnaclHost::GetNexeFd(int render_process_id, 227ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int render_view_id, 228ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch int pp_instance, 229ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch bool is_incognito, 230ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const nacl::PnaclCacheInfo& cache_info, 231ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const NexeFdCallback& cb) { 232ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 233ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (cache_state_ == CacheUninitialized) { 234ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch Init(); 235ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 236ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (cache_state_ != CacheReady) { 237ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // If the backend hasn't yet initialized, try the request again later. 238ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch BrowserThread::PostDelayedTask(BrowserThread::IO, 239ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch FROM_HERE, 240ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch base::Bind(&PnaclHost::GetNexeFd, 241ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch weak_factory_.GetWeakPtr(), 242ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch render_process_id, 243ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch render_view_id, 244ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch pp_instance, 245ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch is_incognito, 246ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch cache_info, 247ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch cb), 248ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch base::TimeDelta::FromMilliseconds( 249ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch kTranslationCacheInitializationDelayMs)); 250ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return; 251ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 252ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 253ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch TranslationID id(render_process_id, pp_instance); 254ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch PendingTranslationMap::iterator entry = pending_translations_.find(id); 255ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (entry != pending_translations_.end()) { 256ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Existing translation must have been abandonded. Clean it up. 2573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) LOG(ERROR) << "GetNexeFd for already-pending translation"; 258ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch pending_translations_.erase(entry); 259ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 260ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 261ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch std::string cache_key(disk_cache_->GetKey(cache_info)); 262ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (cache_key.empty()) { 2633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) LOG(ERROR) << "GetNexeFd: Invalid cache info"; 26446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) cb.Run(base::File(), false); 265ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 266ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 267ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 268ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch PendingTranslation pt; 269ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch pt.render_view_id = render_view_id; 270ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch pt.callback = cb; 271ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch pt.cache_info = cache_info; 272ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch pt.cache_key = cache_key; 273ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch pt.is_incognito = is_incognito; 274ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch pending_translations_[id] = pt; 275ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch SendCacheQueryAndTempFileRequest(cache_key, id); 276ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 277ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 278ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Dispatch the cache read request and the temp file creation request 279ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// simultaneously; currently we need a temp file regardless of whether the 280ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// request hits. 281ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid PnaclHost::SendCacheQueryAndTempFileRequest(const std::string& cache_key, 282ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const TranslationID& id) { 2831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) pending_backend_operations_++; 284ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch disk_cache_->GetNexe( 285ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch cache_key, 286ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch base::Bind( 287ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch &PnaclHost::OnCacheQueryReturn, weak_factory_.GetWeakPtr(), id)); 288ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 289ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch CreateTemporaryFile( 290ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch base::Bind(&PnaclHost::OnTempFileReturn, weak_factory_.GetWeakPtr(), id)); 291ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 292ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 293ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Callback from the translation cache query. |id| is bound from 294ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// SendCacheQueryAndTempFileRequest, |net_error| is a net::Error code (which for 295ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// our purposes means a hit if it's net::OK (i.e. 0). |buffer| is allocated 296ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// by PnaclTranslationCache and now belongs to PnaclHost. 297ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// (Bound callbacks must re-lookup the TranslationID because the translation 298ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// could be cancelled before they get called). 299ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid PnaclHost::OnCacheQueryReturn( 300ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const TranslationID& id, 301ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch int net_error, 302ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch scoped_refptr<net::DrainableIOBuffer> buffer) { 303ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 3041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) pending_backend_operations_--; 305ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch PendingTranslationMap::iterator entry(pending_translations_.find(id)); 306ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (entry == pending_translations_.end()) { 3073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) LOG(ERROR) << "OnCacheQueryReturn: id not found"; 3081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DeInitIfSafe(); 309ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return; 310ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 311ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch PendingTranslation* pt = &entry->second; 312ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch pt->got_cache_reply = true; 313ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch pt->got_cache_hit = (net_error == net::OK); 314ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (pt->got_cache_hit) 315ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch pt->nexe_read_buffer = buffer; 316ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch CheckCacheQueryReady(entry); 317ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 318ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 319ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Callback from temp file creation. |id| is bound from 320a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// SendCacheQueryAndTempFileRequest, and |file| is the created file. 321f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// If there was an error, file is invalid. 322ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// (Bound callbacks must re-lookup the TranslationID because the translation 323ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// could be cancelled before they get called). 324ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid PnaclHost::OnTempFileReturn(const TranslationID& id, 325a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::File file) { 326ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 327ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch PendingTranslationMap::iterator entry(pending_translations_.find(id)); 328ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (entry == pending_translations_.end()) { 329ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // The renderer may have signaled an error or closed while the temp 330ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // file was being created. 3313551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) LOG(ERROR) << "OnTempFileReturn: id not found"; 332ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch BrowserThread::PostBlockingPoolTask( 333a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FROM_HERE, base::Bind(CloseBaseFile, Passed(file.Pass()))); 334ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return; 335ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 336a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!file.IsValid()) { 337ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // This translation will fail, but we need to retry any translation 338ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // waiting for its result. 3393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) LOG(ERROR) << "OnTempFileReturn: temp file creation failed"; 340ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch std::string key(entry->second.cache_key); 34146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) entry->second.callback.Run(base::File(), false); 34258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bool may_be_cached = TranslationMayBeCached(entry); 343ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch pending_translations_.erase(entry); 34458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // No translations will be waiting for entries that will not be stored. 34558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (may_be_cached) 346ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch RequeryMatchingTranslations(key); 347ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return; 348ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 349ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch PendingTranslation* pt = &entry->second; 350ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch pt->got_nexe_fd = true; 35146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) pt->nexe_fd = new base::File(file.Pass()); 352ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch CheckCacheQueryReady(entry); 353ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 354ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 355ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Check whether both the cache query and the temp file have returned, and check 356ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// whether we actually got a hit or not. 357ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid PnaclHost::CheckCacheQueryReady( 358ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const PendingTranslationMap::iterator& entry) { 359ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch PendingTranslation* pt = &entry->second; 360ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!(pt->got_cache_reply && pt->got_nexe_fd)) 361ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return; 362ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!pt->got_cache_hit) { 363ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Check if there is already a pending translation for this file. If there 364ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // is, we will wait for it to come back, to avoid redundant translations. 365ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch for (PendingTranslationMap::iterator it = pending_translations_.begin(); 366ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch it != pending_translations_.end(); 367ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch ++it) { 368ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Another translation matches if it's a request for the same file, 369ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (it->second.cache_key == entry->second.cache_key && 370ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // and it's not this translation, 371ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch it->first != entry->first && 37258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // and it can be stored in the cache, 37358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) TranslationMayBeCached(it) && 37458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // and it's already gotten past this check and returned the miss. 375ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch it->second.got_cache_reply && 376ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch it->second.got_nexe_fd) { 377ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return; 378ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 379ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 380ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch ReturnMiss(entry); 381ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return; 382ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 383ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 38446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<base::File> file(pt->nexe_fd); 38546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) pt->nexe_fd = NULL; 38646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) pt->got_nexe_fd = false; 38746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) FileProxy* proxy(new FileProxy(file.Pass(), weak_factory_.GetWeakPtr())); 38846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 389ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!base::PostTaskAndReplyWithResult( 390424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) BrowserThread::GetBlockingPool(), 391424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) FROM_HERE, 39246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(&FileProxy::Write, base::Unretained(proxy), 39346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) pt->nexe_read_buffer), 39446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(&FileProxy::WriteDone, base::Owned(proxy), 395424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) entry->first))) { 39646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) pt->callback.Run(base::File(), false); 397ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 398ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 399ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 400ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//////////////////// GetNexeFd miss path 401ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Return the temp fd to the renderer, reporting a miss. 402ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid PnaclHost::ReturnMiss(const PendingTranslationMap::iterator& entry) { 403ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Return the fd 404ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch PendingTranslation* pt = &entry->second; 405ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch NexeFdCallback cb(pt->callback); 40646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) cb.Run(*pt->nexe_fd, false); 40746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!pt->nexe_fd->IsValid()) { 40846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Bad FD is unrecoverable, so clear out the entry. 409ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch pending_translations_.erase(entry); 410ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 411ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 412ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 413ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// On error, just return a null refptr. 414ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// static 415ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochscoped_refptr<net::DrainableIOBuffer> PnaclHost::CopyFileToBuffer( 41646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<base::File> file) { 41746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::File::Info info; 418ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch scoped_refptr<net::DrainableIOBuffer> buffer; 419ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch bool error = false; 42046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!file->GetInfo(&info) || 421ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch info.size >= std::numeric_limits<int>::max()) { 42246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) PLOG(ERROR) << "File::GetInfo failed"; 423ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch error = true; 424ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } else { 425ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch buffer = new net::DrainableIOBuffer( 426ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch new net::IOBuffer(static_cast<int>(info.size)), info.size); 42746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (file->Read(0, buffer->data(), buffer->size()) != info.size) { 4283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) PLOG(ERROR) << "CopyFileToBuffer file read failed"; 429ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch error = true; 430ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 431ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 432ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (error) { 433ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch buffer = NULL; 434ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 435ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return buffer; 436ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 437ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 438ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Called by the renderer in the miss path to report a finished translation 439bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochvoid PnaclHost::TranslationFinished(int render_process_id, 440bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch int pp_instance, 441bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch bool success) { 442ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 443ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (cache_state_ != CacheReady) 444ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 445ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch TranslationID id(render_process_id, pp_instance); 446ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch PendingTranslationMap::iterator entry(pending_translations_.find(id)); 447ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (entry == pending_translations_.end()) { 448ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch LOG(ERROR) << "TranslationFinished: TranslationID " << render_process_id 449ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch << "," << pp_instance << " not found."; 450ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return; 451ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 452ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch bool store_nexe = true; 453ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // If this is a premature response (i.e. we haven't returned a temp file 454ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // yet) or if it's an unsuccessful translation, or if we are incognito, 455ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // don't store in the cache. 456ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // TODO(dschuff): use a separate in-memory cache for incognito 457ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // translations. 458ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!entry->second.got_nexe_fd || !entry->second.got_cache_reply || 45958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) !success || !TranslationMayBeCached(entry)) { 460ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch store_nexe = false; 46146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } else { 46246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<base::File> file(entry->second.nexe_fd); 46346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) entry->second.nexe_fd = NULL; 46446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) entry->second.got_nexe_fd = false; 46546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 46646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!base::PostTaskAndReplyWithResult( 46746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) BrowserThread::GetBlockingPool(), 46846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) FROM_HERE, 46946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(&PnaclHost::CopyFileToBuffer, Passed(&file)), 47046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(&PnaclHost::StoreTranslatedNexe, 47146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) weak_factory_.GetWeakPtr(), 47246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) id))) { 47346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) store_nexe = false; 47446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 475ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 476ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 477ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (!store_nexe) { 478ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // If store_nexe is true, the fd will be closed by CopyFileToBuffer. 479ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (entry->second.got_nexe_fd) { 48046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<base::File> file(entry->second.nexe_fd); 48146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) entry->second.nexe_fd = NULL; 482ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch BrowserThread::PostBlockingPoolTask( 483ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch FROM_HERE, 48446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(CloseScopedFile, Passed(&file))); 485ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 486ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch pending_translations_.erase(entry); 487ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 488ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 489ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 490ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Store the translated nexe in the translation cache. Called back with the 491ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// TranslationID from the host and the result of CopyFileToBuffer. 492ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// (Bound callbacks must re-lookup the TranslationID because the translation 493ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// could be cancelled before they get called). 494ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid PnaclHost::StoreTranslatedNexe( 495ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch TranslationID id, 496ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch scoped_refptr<net::DrainableIOBuffer> buffer) { 497ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 498ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (cache_state_ != CacheReady) 499ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return; 500ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch PendingTranslationMap::iterator it(pending_translations_.find(id)); 501ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (it == pending_translations_.end()) { 502ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch LOG(ERROR) << "StoreTranslatedNexe: TranslationID " << id.first << "," 503ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch << id.second << " not found."; 504ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return; 505ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 506ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 507ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (buffer.get() == NULL) { 508ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch LOG(ERROR) << "Error reading translated nexe"; 509ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return; 510ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 5111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) pending_backend_operations_++; 512ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch disk_cache_->StoreNexe(it->second.cache_key, 5131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci buffer.get(), 514ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch base::Bind(&PnaclHost::OnTranslatedNexeStored, 515ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch weak_factory_.GetWeakPtr(), 516ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch it->first)); 517ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 518ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 519ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// After we know the nexe has been stored, we can clean up, and unblock any 520ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// outstanding requests for the same file. 521ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// (Bound callbacks must re-lookup the TranslationID because the translation 522ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// could be cancelled before they get called). 523ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid PnaclHost::OnTranslatedNexeStored(const TranslationID& id, int net_error) { 524ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch PendingTranslationMap::iterator entry(pending_translations_.find(id)); 5251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) pending_backend_operations_--; 526ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (entry == pending_translations_.end()) { 5271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // If the renderer closed while we were storing the nexe, we land here. 5281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Make sure we try to de-init. 5291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DeInitIfSafe(); 530ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return; 531ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 532ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch std::string key(entry->second.cache_key); 533ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch pending_translations_.erase(entry); 534ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch RequeryMatchingTranslations(key); 535ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 536ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 537ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Check if any pending translations match |key|. If so, re-issue the cache 538ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// query. In the overlapped miss case, we expect a hit this time, but a miss 539ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// is also possible in case of an error. 540ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid PnaclHost::RequeryMatchingTranslations(const std::string& key) { 541ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Check for outstanding misses to this same file 542ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch for (PendingTranslationMap::iterator it = pending_translations_.begin(); 543ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch it != pending_translations_.end(); 544ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch ++it) { 545ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (it->second.cache_key == key) { 546ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Re-send the cache read request. This time we expect a hit, but if 547ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // something goes wrong, it will just handle it like a miss. 548ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch it->second.got_cache_reply = false; 5491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) pending_backend_operations_++; 550ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch disk_cache_->GetNexe(key, 551ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch base::Bind(&PnaclHost::OnCacheQueryReturn, 552ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch weak_factory_.GetWeakPtr(), 553ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch it->first)); 554ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 555ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 556ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 557ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 558ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch//////////////////// GetNexeFd hit path 559ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 560ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid PnaclHost::OnBufferCopiedToTempFile(const TranslationID& id, 56146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<base::File> file, 562ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch int file_error) { 563ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 564ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch PendingTranslationMap::iterator entry(pending_translations_.find(id)); 565ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (entry == pending_translations_.end()) { 56646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) BrowserThread::PostBlockingPoolTask( 56746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) FROM_HERE, 56846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(CloseScopedFile, Passed(&file))); 569ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return; 570ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 571ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (file_error == -1) { 572ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Write error on the temp file. Request a new file and start over. 573ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch BrowserThread::PostBlockingPoolTask( 574ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch FROM_HERE, 57546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(CloseScopedFile, Passed(&file))); 576ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch CreateTemporaryFile(base::Bind(&PnaclHost::OnTempFileReturn, 577ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch weak_factory_.GetWeakPtr(), 578ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch entry->first)); 579ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return; 580ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 58146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) entry->second.callback.Run(*file.get(), true); 582ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch BrowserThread::PostBlockingPoolTask( 58346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) FROM_HERE, 58446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(CloseScopedFile, Passed(&file))); 585ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch pending_translations_.erase(entry); 586ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 587ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 588ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch/////////////////// 589ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 590ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid PnaclHost::RendererClosing(int render_process_id) { 591ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 592ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (cache_state_ != CacheReady) 593ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return; 594ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch for (PendingTranslationMap::iterator it = pending_translations_.begin(); 595ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch it != pending_translations_.end();) { 596ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch PendingTranslationMap::iterator to_erase(it++); 597ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (to_erase->first.first == render_process_id) { 598ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Clean up the open files. 59946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<base::File> file(to_erase->second.nexe_fd); 60046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) to_erase->second.nexe_fd = NULL; 601ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch BrowserThread::PostBlockingPoolTask( 602ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch FROM_HERE, 60346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) base::Bind(CloseScopedFile, Passed(&file))); 604ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch std::string key(to_erase->second.cache_key); 60558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bool may_be_cached = TranslationMayBeCached(to_erase); 606ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch pending_translations_.erase(to_erase); 60758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // No translations will be waiting for entries that will not be stored. 60858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (may_be_cached) 609ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch RequeryMatchingTranslations(key); 610ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 611ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 6121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) BrowserThread::PostTask( 6131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) BrowserThread::IO, 6141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) FROM_HERE, 6151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::Bind(&PnaclHost::DeInitIfSafe, weak_factory_.GetWeakPtr())); 616ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 617ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 618ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch////////////////// Cache data removal 619ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid PnaclHost::ClearTranslationCacheEntriesBetween( 620ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch base::Time initial_time, 621ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch base::Time end_time, 622ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch const base::Closure& callback) { 623ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch DCHECK(thread_checker_.CalledOnValidThread()); 624ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (cache_state_ == CacheUninitialized) { 625ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch Init(); 626ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 627ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (cache_state_ == CacheInitializing) { 628ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // If the backend hasn't yet initialized, try the request again later. 629ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch BrowserThread::PostDelayedTask( 630ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch BrowserThread::IO, 631ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch FROM_HERE, 632ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch base::Bind(&PnaclHost::ClearTranslationCacheEntriesBetween, 633ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch weak_factory_.GetWeakPtr(), 634ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch initial_time, 635ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch end_time, 636ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch callback), 637ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch base::TimeDelta::FromMilliseconds( 638ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch kTranslationCacheInitializationDelayMs)); 639ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return; 640ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 6411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) pending_backend_operations_++; 642ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch int rv = disk_cache_->DoomEntriesBetween( 643ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch initial_time, 644ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch end_time, 6451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::Bind( 6461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) &PnaclHost::OnEntriesDoomed, weak_factory_.GetWeakPtr(), callback)); 647ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (rv != net::ERR_IO_PENDING) 648ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch OnEntriesDoomed(callback, rv); 649ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 650ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 651ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid PnaclHost::OnEntriesDoomed(const base::Closure& callback, int net_error) { 6521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DCHECK(thread_checker_.CalledOnValidThread()); 653ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, callback); 6541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) pending_backend_operations_--; 6551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // When clearing the cache, the UI is blocked on all the cache-clearing 6561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // operations, and freeing the backend actually blocks the IO thread. So 6571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // instead of calling DeInitIfSafe directly, post it for later. 6581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) BrowserThread::PostTask( 6591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) BrowserThread::IO, 6601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) FROM_HERE, 6611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::Bind(&PnaclHost::DeInitIfSafe, weak_factory_.GetWeakPtr())); 6621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 6631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 6641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Destroying the cache backend causes it to post tasks to the cache thread to 6651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// flush to disk. Because PnaclHost is a singleton, it does not get destroyed 6661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// until all the browser threads have gone away and it's too late to post 6671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// anything (attempting to do so hangs shutdown). So we make sure to destroy it 6681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// when we no longer have any outstanding operations that need it. These include 6691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// pending translations, cache clear requests, and requests to read or write 6701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// translated nexes. We check when renderers close, when cache clear requests 6711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// finish, and when backend operations complete. 6721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 6731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// It is not safe to delete the backend while it is initializing, nor if it has 6741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// outstanding entry open requests; it is in theory safe to delete it with 6751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// outstanding read/write requests, but because that distinction is hidden 6761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// inside PnaclTranslationCache, we do not delete the backend if there are any 6771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// backend requests in flight. As a last resort in the destructor, we just leak 6781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// the backend to avoid hanging shutdown. 6791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void PnaclHost::DeInitIfSafe() { 6801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DCHECK(pending_backend_operations_ >= 0); 6815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (pending_translations_.empty() && 6825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pending_backend_operations_ <= 0 && 6835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) cache_state_ == CacheReady) { 6841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) cache_state_ = CacheUninitialized; 6851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) disk_cache_.reset(); 6861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 687ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 688f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 689f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} // namespace pnacl 690