summaryrefslogtreecommitdiffstats
path: root/webkit/appcache
diff options
context:
space:
mode:
authormichaeln@chromium.org <michaeln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-18 23:27:27 +0000
committermichaeln@chromium.org <michaeln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-01-18 23:27:27 +0000
commit1ededee8107fd0e40e6371a5d35f7d2b451ca433 (patch)
treee180d5419e246f0f3bb69ba274d7abcf409741f9 /webkit/appcache
parent5510cff445f38b167c8ca9c734e9311fd0505212 (diff)
downloadchromium_src-1ededee8107fd0e40e6371a5d35f7d2b451ca433.zip
chromium_src-1ededee8107fd0e40e6371a5d35f7d2b451ca433.tar.gz
chromium_src-1ededee8107fd0e40e6371a5d35f7d2b451ca433.tar.bz2
Put appcache storage on disk and add a means of disabling the appcache system when certain error conditions arise.
TEST=existing tests apply BUG=none Review URL: http://codereview.chromium.org/542071 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@36499 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/appcache')
-rw-r--r--webkit/appcache/appcache_database.cc30
-rw-r--r--webkit/appcache/appcache_database.h5
-rw-r--r--webkit/appcache/appcache_response.cc4
-rw-r--r--webkit/appcache/appcache_storage_impl.cc135
-rw-r--r--webkit/appcache/appcache_storage_impl.h7
-rw-r--r--webkit/appcache/appcache_working_set.cc16
-rw-r--r--webkit/appcache/appcache_working_set.h5
7 files changed, 153 insertions, 49 deletions
diff --git a/webkit/appcache/appcache_database.cc b/webkit/appcache/appcache_database.cc
index 8b9da0a..7182141 100644
--- a/webkit/appcache/appcache_database.cc
+++ b/webkit/appcache/appcache_database.cc
@@ -135,7 +135,7 @@ const int kIndexCount = ARRAYSIZE_UNSAFE(kIndexes);
namespace appcache {
AppCacheDatabase::AppCacheDatabase(const FilePath& path)
- : db_file_path_(path), has_open_error_(false), is_recreating_(false) {
+ : db_file_path_(path), is_disabled_(false), is_recreating_(false) {
}
AppCacheDatabase::~AppCacheDatabase() {
@@ -150,6 +150,13 @@ void AppCacheDatabase::CloseConnection() {
}
}
+void AppCacheDatabase::Disable() {
+ LOG(INFO) << "Disabling appcache database.";
+ is_disabled_ = true;
+ meta_table_.reset();
+ db_.reset();
+}
+
bool AppCacheDatabase::FindOriginsWithGroups(std::set<GURL>* origins) {
DCHECK(origins && origins->empty());
if (!LazyOpen(false))
@@ -902,7 +909,7 @@ bool AppCacheDatabase::LazyOpen(bool create_if_needed) {
// If we tried and failed once, don't try again in the same session
// to avoid creating an incoherent mess on disk.
- if (has_open_error_)
+ if (is_disabled_)
return false;
// Avoid creating a database at all if we can.
@@ -915,14 +922,19 @@ bool AppCacheDatabase::LazyOpen(bool create_if_needed) {
db_.reset(new sql::Connection);
meta_table_.reset(new sql::MetaTable);
- bool opened = use_in_memory_db ? db_->OpenInMemory()
- : db_->Open(db_file_path_);
- if (opened)
- db_->Preload();
+ bool opened = false;
+ if (use_in_memory_db) {
+ opened = db_->OpenInMemory();
+ } else if (!file_util::CreateDirectory(db_file_path_.DirName())) {
+ LOG(ERROR) << "Failed to create appcache directory.";
+ } else {
+ opened = db_->Open(db_file_path_);
+ if (opened)
+ db_->Preload();
+ }
+
if (!opened || !EnsureDatabaseVersion()) {
- has_open_error_ = true;
- meta_table_.reset();
- db_.reset();
+ Disable();
return false;
}
diff --git a/webkit/appcache/appcache_database.h b/webkit/appcache/appcache_database.h
index 0b9d1ac..89fc330 100644
--- a/webkit/appcache/appcache_database.h
+++ b/webkit/appcache/appcache_database.h
@@ -70,6 +70,9 @@ class AppCacheDatabase {
~AppCacheDatabase();
void CloseConnection();
+ void Disable();
+ bool is_disabled() const { return is_disabled_; }
+
bool FindOriginsWithGroups(std::set<GURL>* origins);
bool FindLastStorageIds(
int64* last_group_id, int64* last_cache_id, int64* last_response_id,
@@ -172,7 +175,7 @@ class AppCacheDatabase {
FilePath db_file_path_;
scoped_ptr<sql::Connection> db_;
scoped_ptr<sql::MetaTable> meta_table_;
- bool has_open_error_;
+ bool is_disabled_;
bool is_recreating_;
FRIEND_TEST(AppCacheDatabaseTest, CacheRecords);
diff --git a/webkit/appcache/appcache_response.cc b/webkit/appcache/appcache_response.cc
index c16bd5c..f9af38e 100644
--- a/webkit/appcache/appcache_response.cc
+++ b/webkit/appcache/appcache_response.cc
@@ -202,7 +202,7 @@ void AppCacheResponseReader::OnIOComplete(int result) {
}
bool AppCacheResponseReader::OpenEntryIfNeeded() {
- if (!entry_)
+ if (!entry_ && disk_cache_)
disk_cache_->OpenEntry(response_key(response_id_), &entry_);
return entry_ ? true : false;
}
@@ -265,6 +265,8 @@ void AppCacheResponseWriter::OnIOComplete(int result) {
bool AppCacheResponseWriter::CreateEntryIfNeeded() {
if (entry_)
return true;
+ if (!disk_cache_)
+ return false;
std::string key(response_key(response_id_));
if (!disk_cache_->CreateEntry(key, &entry_)) {
// We may try to overrite existing entries.
diff --git a/webkit/appcache/appcache_storage_impl.cc b/webkit/appcache/appcache_storage_impl.cc
index 58f64cc..6e91892 100644
--- a/webkit/appcache/appcache_storage_impl.cc
+++ b/webkit/appcache/appcache_storage_impl.cc
@@ -6,10 +6,12 @@
#include "app/sql/connection.h"
#include "app/sql/transaction.h"
+#include "base/file_util.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/stl_util-inl.h"
#include "base/string_util.h"
+#include "net/base/cache_type.h"
#include "webkit/appcache/appcache.h"
#include "webkit/appcache/appcache_database.h"
#include "webkit/appcache/appcache_entry.h"
@@ -21,7 +23,8 @@ namespace appcache {
static const char kAppCacheDatabaseName[] = "Index";
static const char kDiskCacheDirectoryName[] = "Cache";
-static const int kMaxDiskCacheSize = 10 * 1024 * 1024;
+static const int kMaxDiskCacheSize = 250 * 1024 * 1024;
+static const int kMaxMemDiskCacheSize = 10 * 1024 * 1024;
// DatabaseTask -----------------------------------------
@@ -65,6 +68,7 @@ class AppCacheStorageImpl::DatabaseTask
private:
void CallRun();
void CallRunCompleted();
+ void CallDisableStorage();
};
void AppCacheStorageImpl::DatabaseTask::Schedule() {
@@ -86,7 +90,13 @@ void AppCacheStorageImpl::DatabaseTask::CancelCompletion() {
void AppCacheStorageImpl::DatabaseTask::CallRun() {
DCHECK(AppCacheThread::CurrentlyOn(AppCacheThread::db()));
- Run();
+ if (!database_->is_disabled()) {
+ Run();
+ if (database_->is_disabled()) {
+ AppCacheThread::PostTask(AppCacheThread::io(), FROM_HERE,
+ NewRunnableMethod(this, &DatabaseTask::CallDisableStorage));
+ }
+ }
AppCacheThread::PostTask(AppCacheThread::io(), FROM_HERE,
NewRunnableMethod(this, &DatabaseTask::CallRunCompleted));
}
@@ -100,6 +110,13 @@ void AppCacheStorageImpl::DatabaseTask::CallRunCompleted() {
}
}
+void AppCacheStorageImpl::DatabaseTask::CallDisableStorage() {
+ if (storage_) {
+ DCHECK(AppCacheThread::CurrentlyOn(AppCacheThread::io()));
+ storage_->Disable();
+ }
+}
+
// InitTask -------
class AppCacheStorageImpl::InitTask : public DatabaseTask {
@@ -131,13 +148,16 @@ void AppCacheStorageImpl::InitTask::RunCompleted() {
storage_->last_cache_id_ = last_cache_id_;
storage_->last_response_id_ = last_response_id_;
storage_->last_deletable_response_rowid_ = last_deletable_response_rowid_;
- storage_->origins_with_groups_.swap(origins_with_groups_);
- const int kDelayMillis = 5 * 60 * 1000; // Five minutes.
- MessageLoop::current()->PostDelayedTask(FROM_HERE,
- storage_->method_factory_.NewRunnableMethod(
- &AppCacheStorageImpl::DelayedStartDeletingUnusedResponses),
- kDelayMillis);
+ if (!storage_->is_disabled()) {
+ storage_->origins_with_groups_.swap(origins_with_groups_);
+
+ const int kDelayMillis = 5 * 60 * 1000; // Five minutes.
+ MessageLoop::current()->PostDelayedTask(FROM_HERE,
+ storage_->method_factory_.NewRunnableMethod(
+ &AppCacheStorageImpl::DelayedStartDeletingUnusedResponses),
+ kDelayMillis);
+ }
}
// CloseConnectionTask -------
@@ -150,6 +170,16 @@ class AppCacheStorageImpl::CloseConnectionTask : public DatabaseTask {
virtual void Run() { database_->CloseConnection(); }
};
+// DisableDatabaseTask -------
+
+class AppCacheStorageImpl::DisableDatabaseTask : public DatabaseTask {
+ public:
+ explicit DisableDatabaseTask(AppCacheStorageImpl* storage)
+ : DatabaseTask(storage) {}
+
+ virtual void Run() { database_->Disable(); }
+};
+
// StoreOrLoadTask -------
class AppCacheStorageImpl::StoreOrLoadTask : public DatabaseTask {
@@ -210,6 +240,9 @@ void AppCacheStorageImpl::StoreOrLoadTask::CreateCacheAndGroupFromRecords(
DCHECK(cache->get()->GetEntry(*iter));
cache->get()->GetEntry(*iter)->add_types(AppCacheEntry::FOREIGN);
}
+
+ // TODO(michaeln): Maybe verify that the responses we expect to exist
+ // do actually exist in the disk_cache (and if not then what?)
}
// CacheLoadTask -------
@@ -238,7 +271,7 @@ void AppCacheStorageImpl::CacheLoadTask::RunCompleted() {
storage_->pending_cache_loads_.erase(cache_id_);
scoped_refptr<AppCache> cache;
scoped_refptr<AppCacheGroup> group;
- if (success_) {
+ if (success_ && !storage_->is_disabled()) {
DCHECK(cache_record_.cache_id == cache_id_);
DCHECK(!storage_->working_set_.GetCache(cache_record_.cache_id));
CreateCacheAndGroupFromRecords(&cache, &group);
@@ -272,15 +305,17 @@ void AppCacheStorageImpl::GroupLoadTask::RunCompleted() {
storage_->pending_group_loads_.erase(manifest_url_);
scoped_refptr<AppCacheGroup> group;
scoped_refptr<AppCache> cache;
- if (success_) {
- DCHECK(group_record_.manifest_url == manifest_url_);
- DCHECK(!storage_->working_set_.GetGroup(manifest_url_));
- DCHECK(!storage_->working_set_.GetCache(cache_record_.cache_id));
- CreateCacheAndGroupFromRecords(&cache, &group);
- } else {
- group = new AppCacheGroup(
- storage_->service_, manifest_url_,
- storage_->NewGroupId());
+ if (!storage_->is_disabled()) {
+ if (success_) {
+ DCHECK(group_record_.manifest_url == manifest_url_);
+ DCHECK(!storage_->working_set_.GetGroup(manifest_url_));
+ DCHECK(!storage_->working_set_.GetCache(cache_record_.cache_id));
+ CreateCacheAndGroupFromRecords(&cache, &group);
+ } else {
+ group = new AppCacheGroup(
+ storage_->service_, manifest_url_,
+ storage_->NewGroupId());
+ }
}
FOR_EACH_DELEGATE(delegates_, OnGroupLoaded(group, manifest_url_));
}
@@ -615,14 +650,16 @@ void AppCacheStorageImpl::MakeGroupObsoleteTask::Run() {
void AppCacheStorageImpl::MakeGroupObsoleteTask::RunCompleted() {
if (success_) {
- storage_->origins_with_groups_.swap(origins_with_groups_);
group_->set_obsolete(true);
- group_->AddNewlyDeletableResponseIds(&newly_deletable_response_ids_);
-
- // Also remove from the working set, caches for an 'obsolete' group
- // may linger in use, but the group itself cannot be looked up by
- // 'manifest_url' in the working set any longer.
- storage_->working_set()->RemoveGroup(group_);
+ if (!storage_->is_disabled()) {
+ storage_->origins_with_groups_.swap(origins_with_groups_);
+ group_->AddNewlyDeletableResponseIds(&newly_deletable_response_ids_);
+
+ // Also remove from the working set, caches for an 'obsolete' group
+ // may linger in use, but the group itself cannot be looked up by
+ // 'manifest_url' in the working set any longer.
+ storage_->working_set()->RemoveGroup(group_);
+ }
}
FOR_EACH_DELEGATE(delegates_, OnGroupMadeObsolete(group_, success_));
group_ = NULL;
@@ -695,6 +732,7 @@ AppCacheStorageImpl::AppCacheStorageImpl(AppCacheService* service)
is_response_deletion_scheduled_(false),
did_start_deleting_responses_(false),
last_deletable_response_rowid_(0), database_(NULL),
+ is_disabled_(false),
ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
}
@@ -710,25 +748,33 @@ AppCacheStorageImpl::~AppCacheStorageImpl() {
}
void AppCacheStorageImpl::Initialize(const FilePath& cache_directory) {
- // TODO(michaeln): until purging of responses is addressed in some way,
- // always use incognito mode which doesn't put anything to disk.
- // Uncomment the following line when responses are dealt with.
- // cache_directory_ = cache_directory;
+ cache_directory_ = cache_directory;
is_incognito_ = cache_directory_.empty();
FilePath db_file_path;
if (!is_incognito_)
- db_file_path = cache_directory.AppendASCII(kAppCacheDatabaseName);
+ db_file_path = cache_directory_.AppendASCII(kAppCacheDatabaseName);
database_ = new AppCacheDatabase(db_file_path);
scoped_refptr<InitTask> task = new InitTask(this);
task->Schedule();
}
+void AppCacheStorageImpl::Disable() {
+ if (is_disabled_)
+ return;
+ LOG(INFO) << "Disabling appcache storage.";
+ is_disabled_ = true;
+ origins_with_groups_.clear();
+ working_set()->Disable();
+ scoped_refptr<DisableDatabaseTask> task = new DisableDatabaseTask(this);
+ task->Schedule();
+}
+
void AppCacheStorageImpl::LoadCache(int64 id, Delegate* delegate) {
DCHECK(delegate);
AppCache* cache = working_set_.GetCache(id);
- if (cache) {
+ if (cache || is_disabled_) {
delegate->OnCacheLoaded(cache, id);
return;
}
@@ -747,7 +793,7 @@ void AppCacheStorageImpl::LoadOrCreateGroup(
const GURL& manifest_url, Delegate* delegate) {
DCHECK(delegate);
AppCacheGroup* group = working_set_.GetGroup(manifest_url);
- if (group) {
+ if (group || is_disabled_) {
delegate->OnGroupLoaded(group, manifest_url);
return;
}
@@ -760,7 +806,7 @@ void AppCacheStorageImpl::LoadOrCreateGroup(
if (origins_with_groups_.find(manifest_url.GetOrigin()) ==
origins_with_groups_.end()) {
- // No need to query the database, return NULL immediately.
+ // No need to query the database, return a new group immediately.
scoped_refptr<AppCacheGroup> group = new AppCacheGroup(
service_, manifest_url, NewGroupId());
delegate->OnGroupLoaded(group, manifest_url);
@@ -971,9 +1017,16 @@ void AppCacheStorageImpl::DeleteOneResponse() {
is_response_deletion_scheduled_ = false;
+ if (!disk_cache()) {
+ DCHECK(is_disabled_);
+ deletable_response_ids_.clear();
+ deleted_response_ids_.clear();
+ return;
+ }
+
int64 id = deletable_response_ids_.front();
deletable_response_ids_.pop_front();
- disk_cache()->DoomEntry(Int64ToString(id));
+ disk_cache_->DoomEntry(Int64ToString(id));
deleted_response_ids_.push_back(id);
const size_t kBatchSize = 50U;
@@ -1037,15 +1090,21 @@ void AppCacheStorageImpl::RunOnePendingSimpleTask() {
}
disk_cache::Backend* AppCacheStorageImpl::disk_cache() {
+ if (is_disabled_)
+ return NULL;
+
if (!disk_cache_.get()) {
if (is_incognito_) {
disk_cache_.reset(
- disk_cache::CreateInMemoryCacheBackend(kMaxDiskCacheSize));
+ disk_cache::CreateInMemoryCacheBackend(kMaxMemDiskCacheSize));
} else {
- // TODO(michaeln): create a disk backed backend
- disk_cache_.reset(
- disk_cache::CreateInMemoryCacheBackend(kMaxDiskCacheSize));
+ disk_cache_.reset(disk_cache::CreateCacheBackend(
+ cache_directory_.AppendASCII(kDiskCacheDirectoryName),
+ false, kMaxDiskCacheSize, net::DISK_CACHE));
}
+
+ if (!disk_cache_.get())
+ Disable();
}
return disk_cache_.get();
}
diff --git a/webkit/appcache/appcache_storage_impl.h b/webkit/appcache/appcache_storage_impl.h
index c7bae95..96fc876 100644
--- a/webkit/appcache/appcache_storage_impl.h
+++ b/webkit/appcache/appcache_storage_impl.h
@@ -23,6 +23,8 @@ class AppCacheStorageImpl : public AppCacheStorage {
virtual ~AppCacheStorageImpl();
void Initialize(const FilePath& cache_directory);
+ void Disable();
+ bool is_disabled() const { return is_disabled_; }
// AppCacheStorage methods
virtual void LoadCache(int64 id, Delegate* delegate);
@@ -55,6 +57,7 @@ class AppCacheStorageImpl : public AppCacheStorage {
class DatabaseTask;
class InitTask;
class CloseConnectionTask;
+ class DisableDatabaseTask;
class StoreOrLoadTask;
class CacheLoadTask;
class GroupLoadTask;
@@ -116,6 +119,10 @@ class AppCacheStorageImpl : public AppCacheStorage {
// Created on the IO thread, but only used on the DB thread.
AppCacheDatabase* database_;
+ // Set if we discover a fatal error like a corrupt sql database or
+ // disk cache and cannot continue.
+ bool is_disabled_;
+
// TODO(michaeln): use a disk_cache per group (manifest or group_id).
scoped_ptr<disk_cache::Backend> disk_cache_;
diff --git a/webkit/appcache/appcache_working_set.cc b/webkit/appcache/appcache_working_set.cc
index 652116c..1c3f40b 100644
--- a/webkit/appcache/appcache_working_set.cc
+++ b/webkit/appcache/appcache_working_set.cc
@@ -17,7 +17,19 @@ AppCacheWorkingSet::~AppCacheWorkingSet() {
DCHECK(groups_by_origin_.empty());
}
+void AppCacheWorkingSet::Disable() {
+ if (is_disabled_)
+ return;
+ is_disabled_ = true;
+ caches_.clear();
+ groups_.clear();
+ groups_by_origin_.clear();
+ response_infos_.clear();
+}
+
void AppCacheWorkingSet::AddCache(AppCache* cache) {
+ if (is_disabled_)
+ return;
DCHECK(cache->cache_id() != kNoCacheId);
int64 cache_id = cache->cache_id();
DCHECK(caches_.find(cache_id) == caches_.end());
@@ -29,6 +41,8 @@ void AppCacheWorkingSet::RemoveCache(AppCache* cache) {
}
void AppCacheWorkingSet::AddGroup(AppCacheGroup* group) {
+ if (is_disabled_)
+ return;
const GURL& url = group->manifest_url();
DCHECK(groups_.find(url) == groups_.end());
groups_.insert(GroupMap::value_type(url, group));
@@ -49,6 +63,8 @@ void AppCacheWorkingSet::RemoveGroup(AppCacheGroup* group) {
}
void AppCacheWorkingSet::AddResponseInfo(AppCacheResponseInfo* info) {
+ if (is_disabled_)
+ return;
DCHECK(info->response_id() != kNoResponseId);
int64 response_id = info->response_id();
DCHECK(response_infos_.find(response_id) == response_infos_.end());
diff --git a/webkit/appcache/appcache_working_set.h b/webkit/appcache/appcache_working_set.h
index 479e74d..15221d12 100644
--- a/webkit/appcache/appcache_working_set.h
+++ b/webkit/appcache/appcache_working_set.h
@@ -22,8 +22,12 @@ class AppCacheWorkingSet {
public:
typedef std::map<GURL, AppCacheGroup*> GroupMap;
+ AppCacheWorkingSet() : is_disabled_(false) {}
~AppCacheWorkingSet();
+ void Disable();
+ bool is_disabled() const { return is_disabled_; }
+
void AddCache(AppCache* cache);
void RemoveCache(AppCache* cache);
AppCache* GetCache(int64 id) {
@@ -63,6 +67,7 @@ class AppCacheWorkingSet {
GroupMap groups_;
GroupsByOriginMap groups_by_origin_; // origin -> (manifest -> group)
ResponseInfoMap response_infos_;
+ bool is_disabled_;
};
} // namespace appcache