summaryrefslogtreecommitdiffstats
path: root/webkit/appcache/appcache_storage_impl.cc
diff options
context:
space:
mode:
authormichaeln@google.com <michaeln@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-29 03:37:22 +0000
committermichaeln@google.com <michaeln@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-12-29 03:37:22 +0000
commit833a4baa2ccf968616d72361a74852c57f911d96 (patch)
tree07ccc3df12e7800ef381dd14ca2bda4e8760aa81 /webkit/appcache/appcache_storage_impl.cc
parent5ac84ca4f92eea80f31b5c7a58e41e35657a69ab (diff)
downloadchromium_src-833a4baa2ccf968616d72361a74852c57f911d96.zip
chromium_src-833a4baa2ccf968616d72361a74852c57f911d96.tar.gz
chromium_src-833a4baa2ccf968616d72361a74852c57f911d96.tar.bz2
Revert 35328 - AppCacheDatabase and SQL based AppCacheStorageImpl.
Still nothing is being written to disk with this CL, inmemory SQLite and DiskCaches are being utilized. Responses are not yet being removed from the DiskCasche when the should be. Once that's done (in the next CL), we'll start saving things on disk. BUG=none TEST=appcache_database_unittest.cc, appcache_storage_impl_unittest.cc Review URL: http://codereview.chromium.org/501033 TBR=michaeln@chromium.org Review URL: http://codereview.chromium.org/519018 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@35329 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/appcache/appcache_storage_impl.cc')
-rw-r--r--webkit/appcache/appcache_storage_impl.cc856
1 files changed, 3 insertions, 853 deletions
diff --git a/webkit/appcache/appcache_storage_impl.cc b/webkit/appcache/appcache_storage_impl.cc
index 04809eb..3fb8280 100644
--- a/webkit/appcache/appcache_storage_impl.cc
+++ b/webkit/appcache/appcache_storage_impl.cc
@@ -4,862 +4,12 @@
#include "webkit/appcache/appcache_storage_impl.h"
-#include "app/sql/connection.h"
-#include "app/sql/transaction.h"
-#include "base/logging.h"
-#include "base/message_loop.h"
-#include "base/stl_util-inl.h"
-#include "base/string_util.h"
-#include "webkit/appcache/appcache.h"
-#include "webkit/appcache/appcache_database.h"
-#include "webkit/appcache/appcache_entry.h"
-#include "webkit/appcache/appcache_group.h"
-#include "webkit/appcache/appcache_response.h"
-#include "webkit/appcache/appcache_thread.h"
-
namespace appcache {
-static const char kAppCacheDatabaseName[] = "Index";
-static const char kDiskCacheDirectoryName[] = "Cache";
-static const int kMaxDiskCacheSize = 10 * 1024 * 1024;
-
-// DatabaseTask -----------------------------------------
-
-class AppCacheStorageImpl::DatabaseTask
- : public base::RefCountedThreadSafe<DatabaseTask> {
- public:
- explicit DatabaseTask(AppCacheStorageImpl* storage)
- : storage_(storage), database_(storage->database_) {}
-
- void AddDelegate(DelegateReference* delegate_reference) {
- delegates_.push_back(delegate_reference);
- }
-
- // Schedules a task to be Run() on the DB thread. Tasks
- // are run in the order in which they are scheduled.
- void Schedule();
-
- // Called on the DB thread.
- virtual void Run() = 0;
-
- // Called on the IO thread after Run() has completed.
- virtual void RunCompleted() {}
-
- // Once scheduled a task cannot be cancelled, but the
- // call to RunCompleted may be. This method should only be
- // called on the IO thread. This is used by AppCacheStorageImpl
- // to cancel the completion calls when AppCacheStorageImpl is
- // destructed. This method may be overriden to release or delete
- // additional data associated with the task that is not DB thread
- // safe. If overriden, this base class method must be called from
- // within the override.
- virtual void CancelCompletion();
-
- protected:
- AppCacheStorageImpl* storage_;
- AppCacheDatabase* database_;
- DelegateReferenceVector delegates_;
-
- private:
- void CallRun();
- void CallRunCompleted();
-};
-
-void AppCacheStorageImpl::DatabaseTask::Schedule() {
- DCHECK(storage_);
- DCHECK(AppCacheThread::CurrentlyOn(AppCacheThread::io()));
- storage_->scheduled_database_tasks_.push_back(this);
- AppCacheThread::PostTask(AppCacheThread::db(), FROM_HERE,
- NewRunnableMethod(this, &DatabaseTask::CallRun));
-}
-
-void AppCacheStorageImpl::DatabaseTask::CancelCompletion() {
- DCHECK(AppCacheThread::CurrentlyOn(AppCacheThread::io()));
- delegates_.clear();
- storage_ = NULL;
-}
-
-void AppCacheStorageImpl::DatabaseTask::CallRun() {
- DCHECK(AppCacheThread::CurrentlyOn(AppCacheThread::db()));
- Run();
- AppCacheThread::PostTask(AppCacheThread::io(), FROM_HERE,
- NewRunnableMethod(this, &DatabaseTask::CallRunCompleted));
-}
-
-void AppCacheStorageImpl::DatabaseTask::CallRunCompleted() {
- if (storage_) {
- DCHECK(AppCacheThread::CurrentlyOn(AppCacheThread::io()));
- DCHECK(storage_->scheduled_database_tasks_.front() == this);
- storage_->scheduled_database_tasks_.pop_front();
- RunCompleted();
- }
-}
-
-// InitTask -------
-
-class AppCacheStorageImpl::InitTask : public DatabaseTask {
- public:
- explicit InitTask(AppCacheStorageImpl* storage)
- : DatabaseTask(storage), last_group_id_(0),
- last_cache_id_(0), last_response_id_(0) {}
-
- virtual void Run();
- virtual void RunCompleted();
-
- int64 last_group_id_;
- int64 last_cache_id_;
- int64 last_response_id_;
- std::set<GURL> origins_with_groups_;
-};
-
-void AppCacheStorageImpl::InitTask::Run() {
- database_->FindLastStorageIds(
- &last_group_id_, &last_cache_id_, &last_response_id_);
- database_->FindOriginsWithGroups(&origins_with_groups_);
-}
-
-void AppCacheStorageImpl::InitTask::RunCompleted() {
- storage_->last_group_id_ = last_group_id_;
- storage_->last_cache_id_ = last_cache_id_;
- storage_->last_response_id_ = last_response_id_;
- storage_->origins_with_groups_.swap(origins_with_groups_);
-}
-
-// CloseConnectionTask -------
-
-class AppCacheStorageImpl::CloseConnectionTask : public DatabaseTask {
- public:
- explicit CloseConnectionTask(AppCacheStorageImpl* storage)
- : DatabaseTask(storage) {}
-
- virtual void Run() { database_->CloseConnection(); }
-};
-
-// StoreOrLoadTask -------
-
-class AppCacheStorageImpl::StoreOrLoadTask : public DatabaseTask {
- protected:
- explicit StoreOrLoadTask(AppCacheStorageImpl* storage)
- : DatabaseTask(storage) {}
-
- bool FindRelatedCacheRecords(int64 cache_id);
- void CreateCacheAndGroupFromRecords(
- scoped_refptr<AppCache>* cache, scoped_refptr<AppCacheGroup>* group);
-
- AppCacheDatabase::GroupRecord group_record_;
- AppCacheDatabase::CacheRecord cache_record_;
- std::vector<AppCacheDatabase::EntryRecord> entry_records_;
- std::vector<AppCacheDatabase::FallbackNameSpaceRecord>
- fallback_namespace_records_;
- std::vector<AppCacheDatabase::OnlineWhiteListRecord>
- online_whitelist_records_;
-};
-
-bool AppCacheStorageImpl::StoreOrLoadTask::FindRelatedCacheRecords(
- int64 cache_id) {
- return database_->FindEntriesForCache(cache_id, &entry_records_) &&
- database_->FindFallbackNameSpacesForCache(
- cache_id, &fallback_namespace_records_) &&
- database_->FindOnlineWhiteListForCache(
- cache_id, &online_whitelist_records_);
-}
-
-void AppCacheStorageImpl::StoreOrLoadTask::CreateCacheAndGroupFromRecords(
- scoped_refptr<AppCache>* cache, scoped_refptr<AppCacheGroup>* group) {
- DCHECK(storage_ && cache && group);
-
- (*cache) = new AppCache(storage_->service_, cache_record_.cache_id);
- cache->get()->InitializeWithDatabaseRecords(
- cache_record_, entry_records_, fallback_namespace_records_,
- online_whitelist_records_);
- cache->get()->set_complete(true);
-
- (*group) = storage_->working_set_.GetGroup(group_record_.manifest_url);
- if (group->get()) {
- DCHECK(group_record_.group_id == group->get()->group_id());
- group->get()->AddCache(cache->get());
- } else {
- (*group) = new AppCacheGroup(
- storage_->service_, group_record_.manifest_url,
- group_record_.group_id);
- group->get()->AddCache(cache->get());
- }
- DCHECK(group->get()->newest_complete_cache() == cache->get());
-
- // We have to update foriegn entries if MarkEntryAsForeignTasks
- // are in flight.
- std::vector<GURL> urls;
- storage_->GetPendingForeignMarkingsForCache(cache->get()->cache_id(), &urls);
- for (std::vector<GURL>::iterator iter = urls.begin();
- iter != urls.end(); ++iter) {
- DCHECK(cache->get()->GetEntry(*iter));
- cache->get()->GetEntry(*iter)->add_types(AppCacheEntry::FOREIGN);
- }
-}
-
-// CacheLoadTask -------
-
-class AppCacheStorageImpl::CacheLoadTask : public StoreOrLoadTask {
- public:
- CacheLoadTask(int64 cache_id, AppCacheStorageImpl* storage)
- : StoreOrLoadTask(storage), cache_id_(cache_id),
- success_(false) {}
-
- virtual void Run();
- virtual void RunCompleted();
-
- int64 cache_id_;
- bool success_;
-};
-
-void AppCacheStorageImpl::CacheLoadTask::Run() {
- success_ =
- database_->FindCache(cache_id_, &cache_record_) &&
- database_->FindGroup(cache_record_.group_id, &group_record_) &&
- FindRelatedCacheRecords(cache_id_);
-}
-
-void AppCacheStorageImpl::CacheLoadTask::RunCompleted() {
- storage_->pending_cache_loads_.erase(cache_id_);
- scoped_refptr<AppCache> cache;
- scoped_refptr<AppCacheGroup> group;
- if (success_) {
- DCHECK(cache_record_.cache_id == cache_id_);
- DCHECK(!storage_->working_set_.GetCache(cache_record_.cache_id));
- CreateCacheAndGroupFromRecords(&cache, &group);
- }
- FOR_EACH_DELEGATE(delegates_, OnCacheLoaded(cache, cache_id_));
-}
-
-// GroupLoadTask -------
-
-class AppCacheStorageImpl::GroupLoadTask : public StoreOrLoadTask {
- public:
- GroupLoadTask(GURL manifest_url, AppCacheStorageImpl* storage)
- : StoreOrLoadTask(storage), manifest_url_(manifest_url),
- success_(false) {}
-
- virtual void Run();
- virtual void RunCompleted();
-
- GURL manifest_url_;
- bool success_;
-};
-
-void AppCacheStorageImpl::GroupLoadTask::Run() {
- success_ =
- database_->FindGroupForManifestUrl(manifest_url_, &group_record_) &&
- database_->FindCacheForGroup(group_record_.group_id, &cache_record_) &&
- FindRelatedCacheRecords(cache_record_.cache_id);
-}
-
-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());
- }
- FOR_EACH_DELEGATE(delegates_, OnGroupLoaded(group, manifest_url_));
-}
-
-// StoreGroupAndCacheTask -------
-
-class AppCacheStorageImpl::StoreGroupAndCacheTask : public StoreOrLoadTask {
- public:
- StoreGroupAndCacheTask(AppCacheStorageImpl* storage, AppCacheGroup* group,
- AppCache* newest_cache);
-
- virtual void Run();
- virtual void RunCompleted();
- virtual void CancelCompletion();
-
- scoped_refptr<AppCacheGroup> group_;
- scoped_refptr<AppCache> cache_;
- bool success_;
-};
-
-AppCacheStorageImpl::StoreGroupAndCacheTask::StoreGroupAndCacheTask(
- AppCacheStorageImpl* storage, AppCacheGroup* group, AppCache* newest_cache)
- : StoreOrLoadTask(storage), group_(group), cache_(newest_cache),
- success_(false) {
- group_record_.group_id = group->group_id();
- group_record_.manifest_url = group->manifest_url();
- group_record_.origin = group_record_.manifest_url.GetOrigin();
- newest_cache->ToDatabaseRecords(
- group,
- &cache_record_, &entry_records_, &fallback_namespace_records_,
- &online_whitelist_records_);
-}
-
-void AppCacheStorageImpl::StoreGroupAndCacheTask::Run() {
- DCHECK(!success_);
- sql::Connection* connection = database_->db_connection();
- if (!connection)
- return;
-
- sql::Transaction transaction(connection);
- if (!transaction.Begin())
- return;
-
- AppCacheDatabase::GroupRecord existing_group;
- success_ = database_->FindGroup(group_record_.group_id, &existing_group);
- if (!success_) {
- success_ = database_->InsertGroup(&group_record_);
- } else {
- DCHECK(group_record_.group_id == existing_group.group_id);
- DCHECK(group_record_.manifest_url == existing_group.manifest_url);
- DCHECK(group_record_.origin == existing_group.origin);
-
- AppCacheDatabase::CacheRecord cache;
- if (database_->FindCacheForGroup(group_record_.group_id, &cache)) {
- success_ =
- database_->DeleteCache(cache.cache_id) &&
- database_->DeleteEntriesForCache(cache.cache_id) &&
- database_->DeleteFallbackNameSpacesForCache(cache.cache_id) &&
- database_->DeleteOnlineWhiteListForCache(cache.cache_id);
- // TODO(michaeln): schedule to purge unused responses from the disk cache
- } else {
- NOTREACHED() << "A existing group without a cache is unexpected";
- }
- }
-
- success_ =
- success_ &&
- database_->InsertCache(&cache_record_) &&
- database_->InsertEntryRecords(entry_records_) &&
- database_->InsertFallbackNameSpaceRecords(fallback_namespace_records_)&&
- database_->InsertOnlineWhiteListRecords(online_whitelist_records_) &&
- transaction.Commit();
-}
-
-void AppCacheStorageImpl::StoreGroupAndCacheTask::RunCompleted() {
- if (success_) {
- storage_->origins_with_groups_.insert(group_->manifest_url().GetOrigin());
- if (cache_ != group_->newest_complete_cache())
- group_->AddCache(cache_);
- }
- FOR_EACH_DELEGATE(delegates_, OnGroupAndNewestCacheStored(group_, success_));
- group_ = NULL;
- cache_ = NULL;
-}
-
-void AppCacheStorageImpl::StoreGroupAndCacheTask::CancelCompletion() {
- // Overriden to safely drop our reference to the group and cache
- // which are not thread safe refcounted.
- DatabaseTask::CancelCompletion();
- group_ = NULL;
- cache_ = NULL;
-}
-
-// FindMainResponseTask -------
-
-class AppCacheStorageImpl::FindMainResponseTask : public DatabaseTask {
- public:
- FindMainResponseTask(AppCacheStorageImpl* storage, const GURL& url,
- const AppCacheWorkingSet::GroupMap* groups_in_use)
- : DatabaseTask(storage), url_(url), cache_id_(kNoCacheId) {
- if (groups_in_use) {
- for (AppCacheWorkingSet::GroupMap::const_iterator it =
- groups_in_use->begin();
- it != groups_in_use->end(); ++it) {
- AppCacheGroup* group = it->second;
- AppCache* cache = group->newest_complete_cache();
- if (group->is_obsolete() || !cache)
- continue;
- cache_ids_in_use_.insert(cache->cache_id());
- }
- }
- }
-
- virtual void Run();
- virtual void RunCompleted();
-
- GURL url_;
- std::set<int64> cache_ids_in_use_;
- AppCacheEntry entry_;
- AppCacheEntry fallback_entry_;
- int64 cache_id_;
- GURL manifest_url_;
-};
-
-namespace {
-
-bool SortByLength(
- const AppCacheDatabase::FallbackNameSpaceRecord& lhs,
- const AppCacheDatabase::FallbackNameSpaceRecord& rhs) {
- return lhs.namespace_url.spec().length() > rhs.namespace_url.spec().length();
-}
-
-}
-
-void AppCacheStorageImpl::FindMainResponseTask::Run() {
- // We have a bias for hits from caches that are in use.
-
- // TODO(michaeln): The heuristics around choosing amoungst
- // multiple candidates is under specified, and just plain
- // not fully understood. Refine these over time. In particular,
- // * prefer candidates from newer caches
- // * take into account the cache associated with the document
- // that initiated the navigation
- // * take into account the cache associated with the document
- // currently residing in the frame being navigated
-
- // First look for an exact match. We don't worry about whether
- // the containing cache is in-use in this loop because the
- // storage class's FindResponseForMainRequest method does that
- // as a pre-optimization.
- std::vector<AppCacheDatabase::EntryRecord> entries;
- if (database_->FindEntriesForUrl(url_, &entries) && !entries.empty()) {
- std::vector<AppCacheDatabase::EntryRecord>::iterator iter;
- for (iter = entries.begin(); iter < entries.end(); ++iter) {
- if (iter->flags & AppCacheEntry::FOREIGN)
- continue;
-
- AppCacheDatabase::GroupRecord group_record;
- if (!database_->FindGroupForCache(iter->cache_id, &group_record)) {
- NOTREACHED() << "A cache without a group is not expected.";
- continue;
- }
- entry_ = AppCacheEntry(iter->flags, iter->response_id);
- cache_id_ = iter->cache_id;
- manifest_url_ = group_record.manifest_url;
- return;
- }
- }
-
- // No exact matches, look at the fallback namespaces for this origin.
- std::vector<AppCacheDatabase::FallbackNameSpaceRecord> fallbacks;
- if (!database_->FindFallbackNameSpacesForOrigin(url_.GetOrigin(), &fallbacks)
- || fallbacks.empty()) {
- return;
- }
-
- // Sort by namespace url string length, longest to shortest,
- // since longer matches trump when matching a url to a namespace.
- std::sort(fallbacks.begin(), fallbacks.end(), SortByLength);
-
- bool has_candidate = false;
- GURL candidate_fallback_namespace;
- std::vector<AppCacheDatabase::FallbackNameSpaceRecord>::iterator iter;
- for (iter = fallbacks.begin(); iter < fallbacks.end(); ++iter) {
- if (has_candidate &&
- (candidate_fallback_namespace.spec().length() >
- iter->namespace_url.spec().length())) {
- break; // Stop iterating since longer namespace prefix matches win.
- }
-
- if (StartsWithASCII(url_.spec(), iter->namespace_url.spec(), true)) {
- bool is_cache_in_use = cache_ids_in_use_.find(iter->cache_id) !=
- cache_ids_in_use_.end();
-
- bool take_new_candidate = !has_candidate || is_cache_in_use;
-
- AppCacheDatabase::EntryRecord entry_record;
- if (take_new_candidate &&
- database_->FindEntry(iter->cache_id, iter->fallback_entry_url,
- &entry_record)) {
- AppCacheDatabase::GroupRecord group_record;
- if (!database_->FindGroupForCache(iter->cache_id, &group_record)) {
- NOTREACHED() << "A cache without a group is not expected.";
- continue;
- }
- cache_id_ = iter->cache_id;
- manifest_url_ = group_record.manifest_url;
- fallback_entry_ = AppCacheEntry(
- entry_record.flags, entry_record.response_id);
- if (is_cache_in_use)
- break; // Stop iterating since we favor hits from in-use caches.
- candidate_fallback_namespace = iter->namespace_url;
- has_candidate = true;
- }
- }
- }
-}
-
-void AppCacheStorageImpl::FindMainResponseTask::RunCompleted() {
- FOR_EACH_DELEGATE(delegates_,
- OnMainResponseFound(url_, entry_, fallback_entry_,
- cache_id_, manifest_url_));
-}
-
-// MarkEntryAsForeignTask -------
-
-class AppCacheStorageImpl::MarkEntryAsForeignTask : public DatabaseTask {
- public:
- MarkEntryAsForeignTask(
- AppCacheStorageImpl* storage, const GURL& url, int64 cache_id)
- : DatabaseTask(storage), cache_id_(cache_id), entry_url_(url) {}
-
- virtual void Run();
- virtual void RunCompleted();
-
- int64 cache_id_;
- GURL entry_url_;
-};
-
-void AppCacheStorageImpl::MarkEntryAsForeignTask::Run() {
- database_->AddEntryFlags(entry_url_, cache_id_, AppCacheEntry::FOREIGN);
-}
-
-void AppCacheStorageImpl::MarkEntryAsForeignTask::RunCompleted() {
- DCHECK(storage_->pending_foreign_markings_.front().first == entry_url_ &&
- storage_->pending_foreign_markings_.front().second == cache_id_);
- storage_->pending_foreign_markings_.pop_front();
-}
-
-// MakeGroupObsoleteTask -------
-
-class AppCacheStorageImpl::MakeGroupObsoleteTask : public DatabaseTask {
- public:
- MakeGroupObsoleteTask(AppCacheStorageImpl* storage, AppCacheGroup* group);
-
- virtual void Run();
- virtual void RunCompleted();
- virtual void CancelCompletion();
-
- scoped_refptr<AppCacheGroup> group_;
- int64 group_id_;
- bool success_;
- std::set<GURL> origins_with_groups_;
-};
-
-AppCacheStorageImpl::MakeGroupObsoleteTask::MakeGroupObsoleteTask(
- AppCacheStorageImpl* storage, AppCacheGroup* group)
- : DatabaseTask(storage), group_(group), group_id_(group->group_id()),
- success_(false) {
-}
-
-void AppCacheStorageImpl::MakeGroupObsoleteTask::Run() {
- DCHECK(!success_);
- sql::Connection* connection = database_->db_connection();
- if (!connection)
- return;
-
- sql::Transaction transaction(connection);
- if (!transaction.Begin())
- return;
-
- AppCacheDatabase::GroupRecord group_record;
- if (!database_->FindGroup(group_id_, &group_record)) {
- // This group doesn't exists in the database, nothing todo here.
- success_ = true;
- return;
- }
-
- AppCacheDatabase::CacheRecord cache_record;
- if (database_->FindCacheForGroup(group_id_, &cache_record)) {
- success_ =
- database_->DeleteGroup(group_id_) &&
- database_->DeleteCache(cache_record.cache_id) &&
- database_->DeleteEntriesForCache(cache_record.cache_id) &&
- database_->DeleteFallbackNameSpacesForCache(cache_record.cache_id) &&
- database_->DeleteOnlineWhiteListForCache(cache_record.cache_id);
- } else {
- NOTREACHED() << "A existing group without a cache is unexpected";
- success_ = database_->DeleteGroup(group_id_);
- }
-
- success_ = success_ &&
- database_->FindOriginsWithGroups(&origins_with_groups_) &&
- transaction.Commit();
-
- // TODO(michaeln): schedule to purge unused responses from the disk cache
-}
-
-void AppCacheStorageImpl::MakeGroupObsoleteTask::RunCompleted() {
- if (success_) {
- storage_->origins_with_groups_.swap(origins_with_groups_);
- group_->set_obsolete(true);
- }
- FOR_EACH_DELEGATE(delegates_, OnGroupMadeObsolete(group_, success_));
- group_ = NULL;
-}
-
-void AppCacheStorageImpl::MakeGroupObsoleteTask::CancelCompletion() {
- // Overriden to safely drop our reference to the group
- // which is not thread safe refcounted.
- DatabaseTask::CancelCompletion();
- group_ = NULL;
-}
-
-
-// AppCacheStorageImpl ---------------------------------------------------
-
-AppCacheStorageImpl::AppCacheStorageImpl(AppCacheService* service)
- : AppCacheStorage(service), is_incognito_(false),
- ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
-}
-
-AppCacheStorageImpl::~AppCacheStorageImpl() {
- STLDeleteElements(&pending_simple_tasks_);
-
- std::for_each(scheduled_database_tasks_.begin(),
- scheduled_database_tasks_.end(),
- std::mem_fun(&DatabaseTask::CancelCompletion));
-
- if (database_)
- AppCacheThread::DeleteSoon(AppCacheThread::db(), FROM_HERE, database_);
-}
-
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;
- is_incognito_ = cache_directory_.empty();
-
- FilePath db_file_path;
- if (!is_incognito_)
- db_file_path = cache_directory.AppendASCII(kAppCacheDatabaseName);
- database_ = new AppCacheDatabase(db_file_path);
-
- scoped_refptr<InitTask> task = new InitTask(this);
- task->Schedule();
-}
-
-void AppCacheStorageImpl::LoadCache(int64 id, Delegate* delegate) {
- DCHECK(delegate);
- AppCache* cache = working_set_.GetCache(id);
- if (cache) {
- delegate->OnCacheLoaded(cache, id);
- return;
- }
- scoped_refptr<CacheLoadTask> task = GetPendingCacheLoadTask(id);
- if (task) {
- task->AddDelegate(GetOrCreateDelegateReference(delegate));
- return;
- }
- task = new CacheLoadTask(id, this);
- task->AddDelegate(GetOrCreateDelegateReference(delegate));
- task->Schedule();
- pending_cache_loads_[id] = task;
-}
-
-void AppCacheStorageImpl::LoadOrCreateGroup(
- const GURL& manifest_url, Delegate* delegate) {
- DCHECK(delegate);
- AppCacheGroup* group = working_set_.GetGroup(manifest_url);
- if (group) {
- delegate->OnGroupLoaded(group, manifest_url);
- return;
- }
-
- scoped_refptr<GroupLoadTask> task = GetPendingGroupLoadTask(manifest_url);
- if (task) {
- task->AddDelegate(GetOrCreateDelegateReference(delegate));
- return;
- }
-
- if (origins_with_groups_.find(manifest_url.GetOrigin()) ==
- origins_with_groups_.end()) {
- // No need to query the database, return NULL immediately.
- scoped_refptr<AppCacheGroup> group = new AppCacheGroup(
- service_, manifest_url, NewGroupId());
- delegate->OnGroupLoaded(group, manifest_url);
- return;
- }
-
- task = new GroupLoadTask(manifest_url, this);
- task->AddDelegate(GetOrCreateDelegateReference(delegate));
- task->Schedule();
- pending_group_loads_[manifest_url] = task.get();
-}
-
-void AppCacheStorageImpl::StoreGroupAndNewestCache(
- AppCacheGroup* group, AppCache* newest_cache, Delegate* delegate) {
- // TODO(michaeln): distinguish between a simple update of an existing
- // cache that just adds new master entry(s), and the insertion of a
- // whole new cache. The StoreGroupAndCacheTask as written will handle
- // the simple update case in a very heavy weight way (delete all and
- // the reinsert all over again).
- DCHECK(group && delegate);
- DCHECK(newest_cache && newest_cache->is_complete());
- scoped_refptr<StoreGroupAndCacheTask> task =
- new StoreGroupAndCacheTask(this, group, newest_cache);
- task->AddDelegate(GetOrCreateDelegateReference(delegate));
- task->Schedule();
-}
-
-void AppCacheStorageImpl::FindResponseForMainRequest(
- const GURL& url, Delegate* delegate) {
- DCHECK(delegate);
-
- const GURL* url_ptr = &url;
- GURL url_no_ref;
- if (url.has_ref()) {
- GURL::Replacements replacements;
- replacements.ClearRef();
- url_no_ref = url.ReplaceComponents(replacements);
- url_ptr = &url_no_ref;
- }
-
- // First look in our working set for a direct hit without having to query
- // the database.
- const AppCacheWorkingSet::GroupMap* groups_in_use =
- working_set()->GetGroupsInOrigin(url_ptr->GetOrigin());
- if (groups_in_use) {
- for (AppCacheWorkingSet::GroupMap::const_iterator it =
- groups_in_use->begin();
- it != groups_in_use->end(); ++it) {
- AppCacheGroup* group = it->second;
- AppCache* cache = group->newest_complete_cache();
- if (group->is_obsolete() || !cache)
- continue;
-
- AppCacheEntry* entry = cache->GetEntry(*url_ptr);
- if (entry && !entry->IsForeign()) {
- ScheduleSimpleTask(method_factory_.NewRunnableMethod(
- &AppCacheStorageImpl::DeliverShortCircuitedFindMainResponse,
- url, *entry, make_scoped_refptr(group), make_scoped_refptr(cache),
- make_scoped_refptr(GetOrCreateDelegateReference(delegate))));
- return;
- }
- }
- }
-
- if (origins_with_groups_.find(url.GetOrigin()) ==
- origins_with_groups_.end()) {
- // No need to query the database, return async'ly but without going thru
- // the DB thread.
- scoped_refptr<AppCacheGroup> no_group;
- scoped_refptr<AppCache> no_cache;
- ScheduleSimpleTask(method_factory_.NewRunnableMethod(
- &AppCacheStorageImpl::DeliverShortCircuitedFindMainResponse,
- url, AppCacheEntry(), no_group, no_cache,
- make_scoped_refptr(GetOrCreateDelegateReference(delegate))));
- return;
- }
-
- // We have to query the database, schedule a database task to do so.
- scoped_refptr<FindMainResponseTask> task =
- new FindMainResponseTask(this, *url_ptr, groups_in_use);
- task->AddDelegate(GetOrCreateDelegateReference(delegate));
- task->Schedule();
-}
-
-void AppCacheStorageImpl::DeliverShortCircuitedFindMainResponse(
- const GURL& url, AppCacheEntry found_entry,
- scoped_refptr<AppCacheGroup> group, scoped_refptr<AppCache> cache,
- scoped_refptr<DelegateReference> delegate_ref) {
- if (delegate_ref->delegate) {
- delegate_ref->delegate->OnMainResponseFound(
- url, found_entry, AppCacheEntry(),
- cache.get() ? cache->cache_id() : kNoCacheId,
- group.get() ? group->manifest_url() : GURL::EmptyGURL());
- }
-}
-
-void AppCacheStorageImpl::FindResponseForSubRequest(
- AppCache* cache, const GURL& url,
- AppCacheEntry* found_entry, AppCacheEntry* found_fallback_entry,
- bool* found_network_namespace) {
- DCHECK(cache && cache->is_complete());
- GURL fallback_namespace_not_used;
- cache->FindResponseForRequest(
- url, found_entry, found_fallback_entry,
- &fallback_namespace_not_used, found_network_namespace);
-}
-
-void AppCacheStorageImpl::MarkEntryAsForeign(
- const GURL& entry_url, int64 cache_id) {
- AppCache* cache = working_set_.GetCache(cache_id);
- if (cache) {
- AppCacheEntry* entry = cache->GetEntry(entry_url);
- DCHECK(entry);
- if (entry)
- entry->add_types(AppCacheEntry::FOREIGN);
- }
- scoped_refptr<MarkEntryAsForeignTask> task =
- new MarkEntryAsForeignTask(this, entry_url, cache_id);
- task->Schedule();
- pending_foreign_markings_.push_back(std::make_pair(entry_url, cache_id));
-}
-
-void AppCacheStorageImpl::MakeGroupObsolete(
- AppCacheGroup* group, Delegate* delegate) {
- DCHECK(group && delegate);
- scoped_refptr<MakeGroupObsoleteTask> task =
- new MakeGroupObsoleteTask(this, group);
- task->AddDelegate(GetOrCreateDelegateReference(delegate));
- task->Schedule();
-}
-
-AppCacheResponseReader* AppCacheStorageImpl::CreateResponseReader(
- const GURL& manifest_url, int64 response_id) {
- return new AppCacheResponseReader(response_id, disk_cache());
-}
-
-AppCacheResponseWriter* AppCacheStorageImpl::CreateResponseWriter(
- const GURL& manifest_url) {
- return new AppCacheResponseWriter(NewResponseId(), disk_cache());
-}
-
-void AppCacheStorageImpl::DoomResponses(
- const GURL& manifest_url, const std::vector<int64>& response_ids) {
- // TODO(michaeln): do something here when deleting responses
-}
-
-AppCacheStorageImpl::CacheLoadTask*
-AppCacheStorageImpl::GetPendingCacheLoadTask(int64 cache_id) {
- PendingCacheLoads::iterator found = pending_cache_loads_.find(cache_id);
- if (found != pending_cache_loads_.end())
- return found->second;
- return NULL;
-}
-
-AppCacheStorageImpl::GroupLoadTask*
-AppCacheStorageImpl::GetPendingGroupLoadTask(const GURL& manifest_url) {
- PendingGroupLoads::iterator found = pending_group_loads_.find(manifest_url);
- if (found != pending_group_loads_.end())
- return found->second;
- return NULL;
-}
-
-void AppCacheStorageImpl::GetPendingForeignMarkingsForCache(
- int64 cache_id, std::vector<GURL>* urls) {
- PendingForeignMarkings::iterator iter = pending_foreign_markings_.begin();
- while (iter != pending_foreign_markings_.end()) {
- if (iter->second == cache_id)
- urls->push_back(iter->first);
- ++iter;
- }
-}
-
-void AppCacheStorageImpl::ScheduleSimpleTask(Task* task) {
- pending_simple_tasks_.push_back(task);
- MessageLoop::current()->PostTask(FROM_HERE,
- method_factory_.NewRunnableMethod(
- &AppCacheStorageImpl::RunOnePendingSimpleTask));
-}
-
-void AppCacheStorageImpl::RunOnePendingSimpleTask() {
- DCHECK(!pending_simple_tasks_.empty());
- Task* task = pending_simple_tasks_.front();
- pending_simple_tasks_.pop_front();
- task->Run();
- delete task;
-}
-
-disk_cache::Backend* AppCacheStorageImpl::disk_cache() {
- if (!disk_cache_.get()) {
- if (is_incognito_) {
- disk_cache_.reset(
- disk_cache::CreateInMemoryCacheBackend(kMaxDiskCacheSize));
- } else {
- // TODO(michaeln): create a disk backed backend
- disk_cache_.reset(
- disk_cache::CreateInMemoryCacheBackend(kMaxDiskCacheSize));
- }
- }
- return disk_cache_.get();
+ is_incognito_ = cache_directory.empty();
+ cache_directory_ = cache_directory;
+ // TODO(michaeln): retrieve last_ids from storage
}
} // namespace appcache