| Index: chrome/browser/nacl_host/pnacl_translation_cache.cc
|
| diff --git a/chrome/browser/nacl_host/pnacl_translation_cache.cc b/chrome/browser/nacl_host/pnacl_translation_cache.cc
|
| deleted file mode 100644
|
| index 56354792ebb6bf4ffe854927401c8781a44ceac4..0000000000000000000000000000000000000000
|
| --- a/chrome/browser/nacl_host/pnacl_translation_cache.cc
|
| +++ /dev/null
|
| @@ -1,440 +0,0 @@
|
| -// Copyright 2013 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "chrome/browser/nacl_host/pnacl_translation_cache.h"
|
| -
|
| -#include <string>
|
| -
|
| -#include "base/callback.h"
|
| -#include "base/files/file_path.h"
|
| -#include "base/logging.h"
|
| -#include "base/strings/string_number_conversions.h"
|
| -#include "base/threading/thread_checker.h"
|
| -#include "components/nacl/common/pnacl_types.h"
|
| -#include "content/public/browser/browser_thread.h"
|
| -#include "net/base/io_buffer.h"
|
| -#include "net/base/net_errors.h"
|
| -#include "net/disk_cache/disk_cache.h"
|
| -
|
| -using base::IntToString;
|
| -using content::BrowserThread;
|
| -
|
| -namespace {
|
| -
|
| -void CloseDiskCacheEntry(disk_cache::Entry* entry) { entry->Close(); }
|
| -
|
| -} // namespace
|
| -
|
| -namespace pnacl {
|
| -// This is in pnacl namespace instead of static so they can be used
|
| -// by the unit test.
|
| -const int kMaxMemCacheSize = 100 * 1024 * 1024;
|
| -
|
| -//////////////////////////////////////////////////////////////////////
|
| -// Handle Reading/Writing to Cache.
|
| -
|
| -// PnaclTranslationCacheEntry is a shim that provides storage for the
|
| -// 'key' and 'data' strings as the disk_cache is performing various async
|
| -// operations. It also tracks the open disk_cache::Entry
|
| -// and ensures that the entry is closed.
|
| -class PnaclTranslationCacheEntry
|
| - : public base::RefCounted<PnaclTranslationCacheEntry> {
|
| - public:
|
| - static PnaclTranslationCacheEntry* GetReadEntry(
|
| - base::WeakPtr<PnaclTranslationCache> cache,
|
| - const std::string& key,
|
| - const GetNexeCallback& callback);
|
| - static PnaclTranslationCacheEntry* GetWriteEntry(
|
| - base::WeakPtr<PnaclTranslationCache> cache,
|
| - const std::string& key,
|
| - net::DrainableIOBuffer* write_nexe,
|
| - const CompletionCallback& callback);
|
| -
|
| - void Start();
|
| -
|
| - // Writes: ---
|
| - // v |
|
| - // Start -> Open Existing --------------> Write ---> Close
|
| - // \ ^
|
| - // \ /
|
| - // --> Create --
|
| - // Reads:
|
| - // Start -> Open --------Read ----> Close
|
| - // | ^
|
| - // |__|
|
| - enum CacheStep {
|
| - UNINITIALIZED,
|
| - OPEN_ENTRY,
|
| - CREATE_ENTRY,
|
| - TRANSFER_ENTRY,
|
| - CLOSE_ENTRY,
|
| - FINISHED
|
| - };
|
| -
|
| - private:
|
| - friend class base::RefCounted<PnaclTranslationCacheEntry>;
|
| - PnaclTranslationCacheEntry(base::WeakPtr<PnaclTranslationCache> cache,
|
| - const std::string& key,
|
| - bool is_read);
|
| - ~PnaclTranslationCacheEntry();
|
| -
|
| - // Try to open an existing entry in the backend
|
| - void OpenEntry();
|
| - // Create a new entry in the backend (for writes)
|
| - void CreateEntry();
|
| - // Write |len| bytes to the backend, starting at |offset|
|
| - void WriteEntry(int offset, int len);
|
| - // Read |len| bytes from the backend, starting at |offset|
|
| - void ReadEntry(int offset, int len);
|
| - // If there was an error, doom the entry. Then post a task to the IO
|
| - // thread to close (and delete) it.
|
| - void CloseEntry(int rv);
|
| - // Call the user callback, and signal to the cache to delete this.
|
| - void Finish(int rv);
|
| - // Used as the callback for all operations to the backend. Handle state
|
| - // transitions, track bytes transferred, and call the other helper methods.
|
| - void DispatchNext(int rv);
|
| -
|
| - base::WeakPtr<PnaclTranslationCache> cache_;
|
| - std::string key_;
|
| - disk_cache::Entry* entry_;
|
| - CacheStep step_;
|
| - bool is_read_;
|
| - GetNexeCallback read_callback_;
|
| - CompletionCallback write_callback_;
|
| - scoped_refptr<net::DrainableIOBuffer> io_buf_;
|
| - base::ThreadChecker thread_checker_;
|
| - DISALLOW_COPY_AND_ASSIGN(PnaclTranslationCacheEntry);
|
| -};
|
| -
|
| -// static
|
| -PnaclTranslationCacheEntry* PnaclTranslationCacheEntry::GetReadEntry(
|
| - base::WeakPtr<PnaclTranslationCache> cache,
|
| - const std::string& key,
|
| - const GetNexeCallback& callback) {
|
| - PnaclTranslationCacheEntry* entry(
|
| - new PnaclTranslationCacheEntry(cache, key, true));
|
| - entry->read_callback_ = callback;
|
| - return entry;
|
| -}
|
| -
|
| -// static
|
| -PnaclTranslationCacheEntry* PnaclTranslationCacheEntry::GetWriteEntry(
|
| - base::WeakPtr<PnaclTranslationCache> cache,
|
| - const std::string& key,
|
| - net::DrainableIOBuffer* write_nexe,
|
| - const CompletionCallback& callback) {
|
| - PnaclTranslationCacheEntry* entry(
|
| - new PnaclTranslationCacheEntry(cache, key, false));
|
| - entry->io_buf_ = write_nexe;
|
| - entry->write_callback_ = callback;
|
| - return entry;
|
| -}
|
| -
|
| -PnaclTranslationCacheEntry::PnaclTranslationCacheEntry(
|
| - base::WeakPtr<PnaclTranslationCache> cache,
|
| - const std::string& key,
|
| - bool is_read)
|
| - : cache_(cache),
|
| - key_(key),
|
| - entry_(NULL),
|
| - step_(UNINITIALIZED),
|
| - is_read_(is_read) {}
|
| -
|
| -PnaclTranslationCacheEntry::~PnaclTranslationCacheEntry() {
|
| - // Ensure we have called the user's callback
|
| - if (step_ != FINISHED) {
|
| - if (!read_callback_.is_null()) {
|
| - BrowserThread::PostTask(
|
| - BrowserThread::IO,
|
| - FROM_HERE,
|
| - base::Bind(read_callback_,
|
| - net::ERR_ABORTED,
|
| - scoped_refptr<net::DrainableIOBuffer>()));
|
| - }
|
| - if (!write_callback_.is_null()) {
|
| - BrowserThread::PostTask(BrowserThread::IO,
|
| - FROM_HERE,
|
| - base::Bind(write_callback_, net::ERR_ABORTED));
|
| - }
|
| - }
|
| -}
|
| -
|
| -void PnaclTranslationCacheEntry::Start() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - step_ = OPEN_ENTRY;
|
| - OpenEntry();
|
| -}
|
| -
|
| -// OpenEntry, CreateEntry, WriteEntry, ReadEntry and CloseEntry are only called
|
| -// from DispatchNext, so they know that cache_ is still valid.
|
| -void PnaclTranslationCacheEntry::OpenEntry() {
|
| - int rv = cache_->backend()->OpenEntry(
|
| - key_,
|
| - &entry_,
|
| - base::Bind(&PnaclTranslationCacheEntry::DispatchNext, this));
|
| - if (rv != net::ERR_IO_PENDING)
|
| - DispatchNext(rv);
|
| -}
|
| -
|
| -void PnaclTranslationCacheEntry::CreateEntry() {
|
| - int rv = cache_->backend()->CreateEntry(
|
| - key_,
|
| - &entry_,
|
| - base::Bind(&PnaclTranslationCacheEntry::DispatchNext, this));
|
| - if (rv != net::ERR_IO_PENDING)
|
| - DispatchNext(rv);
|
| -}
|
| -
|
| -void PnaclTranslationCacheEntry::WriteEntry(int offset, int len) {
|
| - DCHECK(io_buf_->BytesRemaining() == len);
|
| - int rv = entry_->WriteData(
|
| - 1,
|
| - offset,
|
| - io_buf_.get(),
|
| - len,
|
| - base::Bind(&PnaclTranslationCacheEntry::DispatchNext, this),
|
| - false);
|
| - if (rv != net::ERR_IO_PENDING)
|
| - DispatchNext(rv);
|
| -}
|
| -
|
| -void PnaclTranslationCacheEntry::ReadEntry(int offset, int len) {
|
| - int rv = entry_->ReadData(
|
| - 1,
|
| - offset,
|
| - io_buf_.get(),
|
| - len,
|
| - base::Bind(&PnaclTranslationCacheEntry::DispatchNext, this));
|
| - if (rv != net::ERR_IO_PENDING)
|
| - DispatchNext(rv);
|
| -}
|
| -
|
| -void PnaclTranslationCacheEntry::CloseEntry(int rv) {
|
| - DCHECK(entry_);
|
| - if (rv < 0) {
|
| - LOG(ERROR) << "Failed to close entry: " << net::ErrorToString(rv);
|
| - entry_->Doom();
|
| - }
|
| - BrowserThread::PostTask(
|
| - BrowserThread::IO, FROM_HERE, base::Bind(&CloseDiskCacheEntry, entry_));
|
| - Finish(rv);
|
| -}
|
| -
|
| -void PnaclTranslationCacheEntry::Finish(int rv) {
|
| - step_ = FINISHED;
|
| - if (is_read_) {
|
| - if (!read_callback_.is_null()) {
|
| - BrowserThread::PostTask(BrowserThread::IO,
|
| - FROM_HERE,
|
| - base::Bind(read_callback_, rv, io_buf_));
|
| - }
|
| - } else {
|
| - if (!write_callback_.is_null()) {
|
| - BrowserThread::PostTask(
|
| - BrowserThread::IO, FROM_HERE, base::Bind(write_callback_, rv));
|
| - }
|
| - }
|
| - cache_->OpComplete(this);
|
| -}
|
| -
|
| -void PnaclTranslationCacheEntry::DispatchNext(int rv) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - if (!cache_)
|
| - return;
|
| -
|
| - switch (step_) {
|
| - case UNINITIALIZED:
|
| - case FINISHED:
|
| - LOG(ERROR) << "DispatchNext called uninitialized";
|
| - break;
|
| -
|
| - case OPEN_ENTRY:
|
| - if (rv == net::OK) {
|
| - step_ = TRANSFER_ENTRY;
|
| - if (is_read_) {
|
| - int bytes_to_transfer = entry_->GetDataSize(1);
|
| - io_buf_ = new net::DrainableIOBuffer(
|
| - new net::IOBuffer(bytes_to_transfer), bytes_to_transfer);
|
| - ReadEntry(0, bytes_to_transfer);
|
| - } else {
|
| - WriteEntry(0, io_buf_->size());
|
| - }
|
| - } else {
|
| - if (rv != net::ERR_FAILED) {
|
| - // ERROR_FAILED is what we expect if the entry doesn't exist.
|
| - LOG(ERROR) << "OpenEntry failed: " << net::ErrorToString(rv);
|
| - }
|
| - if (is_read_) {
|
| - // Just a cache miss, not necessarily an error.
|
| - entry_ = NULL;
|
| - Finish(rv);
|
| - } else {
|
| - step_ = CREATE_ENTRY;
|
| - CreateEntry();
|
| - }
|
| - }
|
| - break;
|
| -
|
| - case CREATE_ENTRY:
|
| - if (rv == net::OK) {
|
| - step_ = TRANSFER_ENTRY;
|
| - WriteEntry(io_buf_->BytesConsumed(), io_buf_->BytesRemaining());
|
| - } else {
|
| - LOG(ERROR) << "Failed to Create Entry: " << net::ErrorToString(rv);
|
| - Finish(rv);
|
| - }
|
| - break;
|
| -
|
| - case TRANSFER_ENTRY:
|
| - if (rv < 0) {
|
| - // We do not call DispatchNext directly if WriteEntry/ReadEntry returns
|
| - // ERR_IO_PENDING, and the callback should not return that value either.
|
| - LOG(ERROR) << "Failed to complete write to entry: "
|
| - << net::ErrorToString(rv);
|
| - step_ = CLOSE_ENTRY;
|
| - CloseEntry(rv);
|
| - break;
|
| - } else if (rv > 0) {
|
| - io_buf_->DidConsume(rv);
|
| - if (io_buf_->BytesRemaining() > 0) {
|
| - is_read_
|
| - ? ReadEntry(io_buf_->BytesConsumed(), io_buf_->BytesRemaining())
|
| - : WriteEntry(io_buf_->BytesConsumed(), io_buf_->BytesRemaining());
|
| - break;
|
| - }
|
| - }
|
| - // rv == 0 or we fell through (i.e. we have transferred all the bytes)
|
| - step_ = CLOSE_ENTRY;
|
| - DCHECK(io_buf_->BytesConsumed() == io_buf_->size());
|
| - if (is_read_)
|
| - io_buf_->SetOffset(0);
|
| - CloseEntry(0);
|
| - break;
|
| -
|
| - case CLOSE_ENTRY:
|
| - step_ = UNINITIALIZED;
|
| - break;
|
| - }
|
| -}
|
| -
|
| -//////////////////////////////////////////////////////////////////////
|
| -void PnaclTranslationCache::OpComplete(PnaclTranslationCacheEntry* entry) {
|
| - open_entries_.erase(entry);
|
| -}
|
| -
|
| -//////////////////////////////////////////////////////////////////////
|
| -// Construction and cache backend initialization
|
| -PnaclTranslationCache::PnaclTranslationCache() : in_memory_(false) {}
|
| -
|
| -PnaclTranslationCache::~PnaclTranslationCache() {}
|
| -
|
| -int PnaclTranslationCache::Init(net::CacheType cache_type,
|
| - const base::FilePath& cache_dir,
|
| - int cache_size,
|
| - const CompletionCallback& callback) {
|
| - int rv = disk_cache::CreateCacheBackend(
|
| - cache_type,
|
| - net::CACHE_BACKEND_DEFAULT,
|
| - cache_dir,
|
| - cache_size,
|
| - true /* force_initialize */,
|
| - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE).get(),
|
| - NULL, /* dummy net log */
|
| - &disk_cache_,
|
| - base::Bind(&PnaclTranslationCache::OnCreateBackendComplete, AsWeakPtr()));
|
| - if (rv == net::ERR_IO_PENDING) {
|
| - init_callback_ = callback;
|
| - }
|
| - return rv;
|
| -}
|
| -
|
| -void PnaclTranslationCache::OnCreateBackendComplete(int rv) {
|
| - if (rv < 0) {
|
| - LOG(ERROR) << "Backend init failed:" << net::ErrorToString(rv);
|
| - }
|
| - // Invoke our client's callback function.
|
| - if (!init_callback_.is_null()) {
|
| - BrowserThread::PostTask(
|
| - BrowserThread::IO, FROM_HERE, base::Bind(init_callback_, rv));
|
| - }
|
| -}
|
| -
|
| -//////////////////////////////////////////////////////////////////////
|
| -// High-level API
|
| -
|
| -void PnaclTranslationCache::StoreNexe(const std::string& key,
|
| - net::DrainableIOBuffer* nexe_data,
|
| - const CompletionCallback& callback) {
|
| - PnaclTranslationCacheEntry* entry = PnaclTranslationCacheEntry::GetWriteEntry(
|
| - AsWeakPtr(), key, nexe_data, callback);
|
| - open_entries_[entry] = entry;
|
| - entry->Start();
|
| -}
|
| -
|
| -void PnaclTranslationCache::GetNexe(const std::string& key,
|
| - const GetNexeCallback& callback) {
|
| - PnaclTranslationCacheEntry* entry =
|
| - PnaclTranslationCacheEntry::GetReadEntry(AsWeakPtr(), key, callback);
|
| - open_entries_[entry] = entry;
|
| - entry->Start();
|
| -}
|
| -
|
| -int PnaclTranslationCache::InitOnDisk(const base::FilePath& cache_directory,
|
| - const CompletionCallback& callback) {
|
| - in_memory_ = false;
|
| - return Init(net::PNACL_CACHE, cache_directory, 0 /* auto size */, callback);
|
| -}
|
| -
|
| -int PnaclTranslationCache::InitInMemory(const CompletionCallback& callback) {
|
| - in_memory_ = true;
|
| - return Init(net::MEMORY_CACHE, base::FilePath(), kMaxMemCacheSize, callback);
|
| -}
|
| -
|
| -int PnaclTranslationCache::Size() {
|
| - if (!disk_cache_)
|
| - return -1;
|
| - return disk_cache_->GetEntryCount();
|
| -}
|
| -
|
| -// static
|
| -std::string PnaclTranslationCache::GetKey(const nacl::PnaclCacheInfo& info) {
|
| - if (!info.pexe_url.is_valid() || info.abi_version < 0 || info.opt_level < 0)
|
| - return std::string();
|
| - std::string retval("ABI:");
|
| - retval += IntToString(info.abi_version) + ";" + "opt:" +
|
| - IntToString(info.opt_level) + ";" + "URL:";
|
| - // Filter the username, password, and ref components from the URL
|
| - GURL::Replacements replacements;
|
| - replacements.ClearUsername();
|
| - replacements.ClearPassword();
|
| - replacements.ClearRef();
|
| - GURL key_url(info.pexe_url.ReplaceComponents(replacements));
|
| - retval += key_url.spec() + ";";
|
| - // You would think that there is already code to format base::Time values
|
| - // somewhere, but I haven't found it yet. In any case, doing it ourselves
|
| - // here means we can keep the format stable.
|
| - base::Time::Exploded exploded;
|
| - info.last_modified.UTCExplode(&exploded);
|
| - if (info.last_modified.is_null() || !exploded.HasValidValues()) {
|
| - memset(&exploded, 0, sizeof(exploded));
|
| - }
|
| - retval += "modified:" + IntToString(exploded.year) + ":" +
|
| - IntToString(exploded.month) + ":" +
|
| - IntToString(exploded.day_of_month) + ":" +
|
| - IntToString(exploded.hour) + ":" + IntToString(exploded.minute) +
|
| - ":" + IntToString(exploded.second) + ":" +
|
| - IntToString(exploded.millisecond) + ":UTC;";
|
| - retval += "etag:" + info.etag;
|
| - return retval;
|
| -}
|
| -
|
| -int PnaclTranslationCache::DoomEntriesBetween(
|
| - base::Time initial,
|
| - base::Time end,
|
| - const CompletionCallback& callback) {
|
| - return disk_cache_->DoomEntriesBetween(initial, end, callback);
|
| -}
|
| -
|
| -} // namespace pnacl
|
|
|