// Copyright (c) 2010 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 "webkit/appcache/appcache_disk_cache.h" #include "base/file_path.h" #include "base/logging.h" #include "base/string_util.h" #include "net/base/net_errors.h" namespace appcache { AppCacheDiskCache::AppCacheDiskCache() : is_disabled_(false), init_callback_(NULL) { } AppCacheDiskCache::~AppCacheDiskCache() { if (create_backend_callback_) { create_backend_callback_->Cancel(); create_backend_callback_.release(); OnCreateBackendComplete(net::ERR_ABORTED); } } int AppCacheDiskCache::InitWithDiskBackend( const FilePath& disk_cache_directory, int disk_cache_size, bool force, base::MessageLoopProxy* cache_thread, net::CompletionCallback* callback) { return Init(net::APP_CACHE, disk_cache_directory, disk_cache_size, force, cache_thread, callback); } int AppCacheDiskCache::InitWithMemBackend( int mem_cache_size, net::CompletionCallback* callback) { return Init(net::MEMORY_CACHE, FilePath(), mem_cache_size, false, NULL, callback); } void AppCacheDiskCache::Disable() { if (is_disabled_) return; is_disabled_ = true; if (create_backend_callback_) { create_backend_callback_->Cancel(); create_backend_callback_.release(); OnCreateBackendComplete(net::ERR_ABORTED); } } int AppCacheDiskCache::CreateEntry(int64 key, disk_cache::Entry** entry, net::CompletionCallback* callback) { if (is_disabled_) return net::ERR_ABORTED; if (is_initializing()) { pending_calls_.push_back(PendingCall(CREATE, key, entry, callback)); return net::ERR_IO_PENDING; } if (!disk_cache_.get()) return net::ERR_FAILED; return disk_cache_->CreateEntry(Int64ToString(key), entry, callback); } int AppCacheDiskCache::OpenEntry(int64 key, disk_cache::Entry** entry, net::CompletionCallback* callback) { if (is_disabled_) return net::ERR_ABORTED; if (is_initializing()) { pending_calls_.push_back(PendingCall(OPEN, key, entry, callback)); return net::ERR_IO_PENDING; } if (!disk_cache_.get()) return net::ERR_FAILED; return disk_cache_->OpenEntry(Int64ToString(key), entry, callback); } int AppCacheDiskCache::DoomEntry(int64 key, net::CompletionCallback* callback) { if (is_disabled_) return net::ERR_ABORTED; if (is_initializing()) { pending_calls_.push_back(PendingCall(DOOM, key, NULL, callback)); return net::ERR_IO_PENDING; } if (!disk_cache_.get()) return net::ERR_FAILED; return disk_cache_->DoomEntry(Int64ToString(key), callback); } int AppCacheDiskCache::Init(net::CacheType cache_type, const FilePath& cache_directory, int cache_size, bool force, base::MessageLoopProxy* cache_thread, net::CompletionCallback* callback) { DCHECK(!is_initializing() && !disk_cache_.get()); is_disabled_ = false; create_backend_callback_ = new CreateBackendCallback( this, &AppCacheDiskCache::OnCreateBackendComplete); int rv = disk_cache::CreateCacheBackend( cache_type, cache_directory, cache_size, force, cache_thread, &(create_backend_callback_->backend_ptr_), create_backend_callback_); if (rv == net::ERR_IO_PENDING) init_callback_ = callback; else OnCreateBackendComplete(rv); return rv; } void AppCacheDiskCache::OnCreateBackendComplete(int rv) { if (rv == net::OK) { disk_cache_.reset(create_backend_callback_->backend_ptr_); create_backend_callback_->backend_ptr_ = NULL; } create_backend_callback_ = NULL; // Invoke our clients callback function. if (init_callback_) { init_callback_->Run(rv); init_callback_ = NULL; } // Service pending calls that were queued up while we were initailizating. for (PendingCalls::const_iterator iter = pending_calls_.begin(); iter < pending_calls_.end(); ++iter) { int rv = net::ERR_FAILED; switch (iter->call_type) { case CREATE: rv = CreateEntry(iter->key, iter->entry, iter->callback); break; case OPEN: rv = OpenEntry(iter->key, iter->entry, iter->callback); break; case DOOM: rv = DoomEntry(iter->key, iter->callback); break; default: NOTREACHED(); break; } if (rv != net::ERR_IO_PENDING) iter->callback->Run(rv); } pending_calls_.clear(); } } // namespace appcache