diff options
author | michaeln@chromium.org <michaeln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-18 23:27:27 +0000 |
---|---|---|
committer | michaeln@chromium.org <michaeln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-01-18 23:27:27 +0000 |
commit | 1ededee8107fd0e40e6371a5d35f7d2b451ca433 (patch) | |
tree | e180d5419e246f0f3bb69ba274d7abcf409741f9 /webkit/appcache | |
parent | 5510cff445f38b167c8ca9c734e9311fd0505212 (diff) | |
download | chromium_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.cc | 30 | ||||
-rw-r--r-- | webkit/appcache/appcache_database.h | 5 | ||||
-rw-r--r-- | webkit/appcache/appcache_response.cc | 4 | ||||
-rw-r--r-- | webkit/appcache/appcache_storage_impl.cc | 135 | ||||
-rw-r--r-- | webkit/appcache/appcache_storage_impl.h | 7 | ||||
-rw-r--r-- | webkit/appcache/appcache_working_set.cc | 16 | ||||
-rw-r--r-- | webkit/appcache/appcache_working_set.h | 5 |
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 |