Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(362)

Unified Diff: webkit/appcache/mock_appcache_storage.cc

Issue 300043: MockAppCacheStorage implemenation (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webkit/appcache/mock_appcache_storage.h ('k') | webkit/appcache/mock_appcache_storage_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webkit/appcache/mock_appcache_storage.cc
===================================================================
--- webkit/appcache/mock_appcache_storage.cc (revision 29670)
+++ webkit/appcache/mock_appcache_storage.cc (working copy)
@@ -5,86 +5,89 @@
#include "webkit/appcache/mock_appcache_storage.h"
#include "base/logging.h"
+#include "base/message_loop.h"
#include "base/ref_counted.h"
+#include "base/stl_util-inl.h"
#include "webkit/appcache/appcache.h"
#include "webkit/appcache/appcache_entry.h"
#include "webkit/appcache/appcache_group.h"
#include "webkit/appcache/appcache_response.h"
+// This is a quick and easy 'mock' implementation of the storage interface
+// that doesn't put anything to disk.
+//
+// We simply add an extra reference to objects when they're put in storage,
+// and remove the extra reference when they are removed from storage.
+// Responses are never really removed from the in-memory disk cache.
+// Delegate callbacks are made asyncly to appropiately mimic what will
+// happen with a real disk-backed storage impl that involves IO on a
+// background thread.
+
namespace appcache {
MockAppCacheStorage::MockAppCacheStorage(AppCacheService* service)
- : AppCacheStorage(service) {
+ : AppCacheStorage(service),
+ ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
last_cache_id_ = 0;
last_entry_id_ = 0;
last_group_id_ = 0;
last_response_id_ = 0;
}
+MockAppCacheStorage::~MockAppCacheStorage() {
+ STLDeleteElements(&pending_tasks_);
+}
+
void MockAppCacheStorage::LoadCache(int64 id, Delegate* delegate) {
+ DCHECK(delegate);
AppCache* cache = working_set_.GetCache(id);
- if (cache->HasOneRef()) {
- // TODO(michaeln): make the load look async
+ if (ShouldCacheLoadAppearAsync(cache)) {
+ ScheduleTask(method_factory_.NewRunnableMethod(
+ &MockAppCacheStorage::ProcessLoadCache,
+ id, GetOrCreateDelegateReference(delegate)));
+ return;
}
- delegate->OnCacheLoaded(cache, id);
+ ProcessLoadCache(id, GetOrCreateDelegateReference(delegate));
}
void MockAppCacheStorage::LoadOrCreateGroup(
const GURL& manifest_url, Delegate* delegate) {
- scoped_refptr<AppCacheGroup> group = working_set_.GetGroup(manifest_url);
- if (!group.get()) {
- group = new AppCacheGroup(service_, manifest_url);
- DCHECK(working_set_.GetGroup(manifest_url));
+ DCHECK(delegate);
+ AppCacheGroup* group = working_set_.GetGroup(manifest_url);
+ if (ShouldGroupLoadAppearAsync(group)) {
+ ScheduleTask(method_factory_.NewRunnableMethod(
+ &MockAppCacheStorage::ProcessLoadOrCreateGroup,
+ manifest_url, GetOrCreateDelegateReference(delegate)));
+ return;
}
- // TODO(michaeln): make the load look async if all of the groups
- // caches only have one ref
- delegate->OnGroupLoaded(group.get(), manifest_url);
+ ProcessLoadOrCreateGroup(
+ manifest_url, GetOrCreateDelegateReference(delegate));
}
void MockAppCacheStorage::StoreGroupAndNewestCache(
AppCacheGroup* group, Delegate* delegate) {
+ DCHECK(group && delegate);
DCHECK(group->newest_complete_cache());
- // TODO(michaeln): write me
- // 'store' the group + newest
- // 'unstore' the old caches
- // figure out which responses can be doomed and doom them
- // OldRepsonses - NewestResponse == ToBeDoomed
-
- // TODO(michaeln): Make this appear async
- //AddStoredGroup(group);
- //AddStoredCache(group->newest_complete_cache());
- //
- //foreach(group->old_caches())
- // RemoveStoredCache(old_cache);
- //std::set<int64> doomed_responses_ = responses from old caches
- //std::set<int64> needed_responses_ = responses from newest cache
- //foreach(needed_responses_)
- // doomed_responses_.remove(needed_response_);
- //DoomResponses(group->manifest_url(), doomed_responses_);
-
- delegate->OnGroupAndNewestCacheStored(group, false);
+ // Always make this operation look async.
+ ScheduleTask(method_factory_.NewRunnableMethod(
+ &MockAppCacheStorage::ProcessStoreGroupAndNewestCache,
+ group, group->newest_complete_cache(),
+ GetOrCreateDelegateReference(delegate)));
}
void MockAppCacheStorage::FindResponseForMainRequest(
const GURL& url, Delegate* delegate) {
- // TODO(michaeln): write me
- //
- //foreach(stored_group) {
- // if (group->manifest_url()->origin() != url.GetOrigin())
- // continue;
- //
- // look for an entry
- // look for a fallback namespace
- // look for a online namespace
- //}
- delegate->OnMainResponseFound(
- url, kNoResponseId, false, kNoCacheId, GURL::EmptyGURL());
+ DCHECK(delegate);
+
+ // Always make this operation look async.
+ ScheduleTask(method_factory_.NewRunnableMethod(
+ &MockAppCacheStorage::ProcessFindResponseForMainRequest,
+ url, GetOrCreateDelegateReference(delegate)));
}
void MockAppCacheStorage::MarkEntryAsForeign(
const GURL& entry_url, int64 cache_id) {
- // Update the working set.
AppCache* cache = working_set_.GetCache(cache_id);
if (cache) {
AppCacheEntry* entry = cache->GetEntry(entry_url);
@@ -96,14 +99,14 @@
// being loaded be sure to update the memory cache upon load completion.
}
-void MockAppCacheStorage::MarkGroupAsObsolete(
+void MockAppCacheStorage::MakeGroupObsolete(
AppCacheGroup* group, Delegate* delegate) {
- // TODO(michaeln): write me
- // remove from working_set
- // remove from storage
- // doom things
- // group->set_obsolete(true);
- // TODO(michaeln): Make this appear async
+ DCHECK(group && delegate);
+
+ // Always make this method look async.
+ ScheduleTask(method_factory_.NewRunnableMethod(
+ &MockAppCacheStorage::ProcessMakeGroupObsolete,
+ group, GetOrCreateDelegateReference(delegate)));
}
AppCacheResponseReader* MockAppCacheStorage::CreateResponseReader(
@@ -118,31 +121,185 @@
void MockAppCacheStorage::DoomResponses(
const GURL& manifest_url, const std::vector<int64>& response_ids) {
- // We don't bother with deleting responses from mock storage.
+ // We don't bother with actually removing responses from the disk-cache,
+ // just keep track of which ids have been doomed.
+ std::vector<int64>::const_iterator it = response_ids.begin();
+ while (it != response_ids.end()) {
+ doomed_response_ids_.insert(*it);
+ ++it;
+ }
}
+void MockAppCacheStorage::ProcessLoadCache(
+ int64 id, scoped_refptr<DelegateReference> delegate_ref) {
+ AppCache* cache = working_set_.GetCache(id);
+ if (delegate_ref->delegate)
+ delegate_ref->delegate->OnCacheLoaded(cache, id);
+}
+
+void MockAppCacheStorage::ProcessLoadOrCreateGroup(
+ const GURL& manifest_url, scoped_refptr<DelegateReference> delegate_ref) {
+ scoped_refptr<AppCacheGroup> group = working_set_.GetGroup(manifest_url);
+
+ // Newly created groups are not put in the stored_groups collection
+ // until StoreGroupAndNewestCache is called.
+ if (!group)
+ group = new AppCacheGroup(service_, manifest_url);
+
+ if (delegate_ref->delegate)
+ delegate_ref->delegate->OnGroupLoaded(group, manifest_url);
+}
+
+void MockAppCacheStorage::ProcessStoreGroupAndNewestCache(
+ scoped_refptr<AppCacheGroup> group,
+ scoped_refptr<AppCache> newest_cache,
+ scoped_refptr<DelegateReference> delegate_ref) {
+ DCHECK(group->newest_complete_cache() == newest_cache.get());
+
+ AddStoredGroup(group);
+ AddStoredCache(group->newest_complete_cache());
+
+ // Copy the collection prior to removal, on final release
+ // of a cache the group's collection will change.
+ AppCacheGroup::Caches copy = group->old_caches();
+ RemoveStoredCaches(copy);
+
+ if (delegate_ref->delegate)
+ delegate_ref->delegate->OnGroupAndNewestCacheStored(group, true);
+
+ // We don't bother with removing responses from 'mock' storage
+ // TODO(michaeln): for 'real' storage...
+ // std::set<int64> doomed_responses_ = responses from old caches
+ // std::set<int64> needed_responses_ = responses from newest cache
+ // foreach(needed_responses_)
+ // doomed_responses_.remove(needed_response_);
+ // DoomResponses(group->manifest_url(), doomed_responses_);
+}
+
+void MockAppCacheStorage::ProcessFindResponseForMainRequest(
+ const GURL& url, scoped_refptr<DelegateReference> delegate_ref) {
+ // TODO(michaeln): write me when doing AppCacheRequestHandler
+ // foreach(stored_group) {
+ // if (group->manifest_url()->origin() != url.GetOrigin())
+ // continue;
+ // look for an entry
+ // look for a fallback namespace
+ // look for a online namespace
+ // }
+ if (delegate_ref->delegate) {
+ delegate_ref->delegate->OnMainResponseFound(
+ url, AppCacheEntry(), kNoCacheId, GURL());
+ }
+}
+
+void MockAppCacheStorage::ProcessMakeGroupObsolete(
+ scoped_refptr<AppCacheGroup> group,
+ scoped_refptr<DelegateReference> delegate_ref) {
+ RemoveStoredGroup(group);
+ if (group->newest_complete_cache())
+ RemoveStoredCache(group->newest_complete_cache());
+
+ // Copy the collection prior to removal, on final release
+ // of a cache the group's collection will change.
+ AppCacheGroup::Caches copy = group->old_caches();
+ RemoveStoredCaches(copy);
+
+ group->set_obsolete(true);
+
+ if (delegate_ref->delegate)
+ delegate_ref->delegate->OnGroupMadeObsolete(group, true);
+}
+
+void MockAppCacheStorage::ScheduleTask(Task* task) {
+ pending_tasks_.push_back(task);
+ MessageLoop::current()->PostTask(FROM_HERE,
+ method_factory_.NewRunnableMethod(
+ &MockAppCacheStorage::RunOnePendingTask));
+}
+
+void MockAppCacheStorage::RunOnePendingTask() {
+ DCHECK(!pending_tasks_.empty());
+ Task* task = pending_tasks_.front();
+ pending_tasks_.pop_front();
+ task->Run();
+ delete task;
+}
+
void MockAppCacheStorage::AddStoredCache(AppCache* cache) {
-// cache->set_is_stored(true);
int64 cache_id = cache->cache_id();
if (stored_caches_.find(cache_id) == stored_caches_.end())
stored_caches_.insert(StoredCacheMap::value_type(cache_id, cache));
}
void MockAppCacheStorage::RemoveStoredCache(AppCache* cache) {
-// cache->set_is_stored(false);
+ // Do not remove from the working set, active caches are still usable
+ // and may be looked up by id until they fall out of use.
stored_caches_.erase(cache->cache_id());
}
+void MockAppCacheStorage::RemoveStoredCaches(
+ const AppCacheGroup::Caches& caches) {
+ AppCacheGroup::Caches::const_iterator it = caches.begin();
+ while (it != caches.end()) {
+ RemoveStoredCache(*it);
+ ++it;
+ }
+}
+
void MockAppCacheStorage::AddStoredGroup(AppCacheGroup* group) {
-// group->set_is_stored(true);
const GURL& url = group->manifest_url();
if (stored_groups_.find(url) == stored_groups_.end())
stored_groups_.insert(StoredGroupMap::value_type(url, group));
}
void MockAppCacheStorage::RemoveStoredGroup(AppCacheGroup* group) {
-// group->set_is_stored(false);
+ // 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.
+ working_set()->RemoveGroup(group);
stored_groups_.erase(group->manifest_url());
}
+bool MockAppCacheStorage::ShouldGroupLoadAppearAsync(
+ const AppCacheGroup* group) {
+ // We'll have to query the database to see if a group for the
+ // manifest_url exists on disk. So return true for async.
+ if (!group)
+ return true;
+
+ // Groups without a newest cache can't have been put to disk yet, so
+ // we can synchronously return a reference we have in the working set.
+ if (!group->newest_complete_cache())
+ return false;
+
+ // The LoadGroup interface implies also loading the newest cache, so
+ // if loading the newest cache should appear async, so to must this
michaeln 2009/10/24 00:36:06 changed locally to... "so too must the"
+ // loading of this group.
+ if (ShouldCacheLoadAppearAsync(group->newest_complete_cache()))
+ return true;
+
+
+ // If any of the old caches are "in use", then the group must also
+ // be memory resident and not require async loading.
+ const AppCacheGroup::Caches& old_caches = group->old_caches();
+ AppCacheGroup::Caches::const_iterator it = old_caches.begin();
+ while (it != old_caches.end()) {
+ // "in use" caches don't require async loading
+ if (!ShouldCacheLoadAppearAsync(*it))
+ return false;
+ ++it;
+ }
+
+ return true;
+}
+
+bool MockAppCacheStorage::ShouldCacheLoadAppearAsync(const AppCache* cache) {
+ if (!cache)
+ return true;
+
+ // If the 'stored' ref is the only ref, real storage will have to load from
+ // the database.
+ return IsCacheStored(cache) && cache->HasOneRef();
+}
+
} // namespace appcache
« no previous file with comments | « webkit/appcache/mock_appcache_storage.h ('k') | webkit/appcache/mock_appcache_storage_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698