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

Side by Side 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, 1 month 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "webkit/appcache/mock_appcache_storage.h" 5 #include "webkit/appcache/mock_appcache_storage.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/message_loop.h"
8 #include "base/ref_counted.h" 9 #include "base/ref_counted.h"
10 #include "base/stl_util-inl.h"
9 #include "webkit/appcache/appcache.h" 11 #include "webkit/appcache/appcache.h"
10 #include "webkit/appcache/appcache_entry.h" 12 #include "webkit/appcache/appcache_entry.h"
11 #include "webkit/appcache/appcache_group.h" 13 #include "webkit/appcache/appcache_group.h"
12 #include "webkit/appcache/appcache_response.h" 14 #include "webkit/appcache/appcache_response.h"
13 15
16 // This is a quick and easy 'mock' implementation of the storage interface
17 // that doesn't put anything to disk.
18 //
19 // We simply add an extra reference to objects when they're put in storage,
20 // and remove the extra reference when they are removed from storage.
21 // Responses are never really removed from the in-memory disk cache.
22 // Delegate callbacks are made asyncly to appropiately mimic what will
23 // happen with a real disk-backed storage impl that involves IO on a
24 // background thread.
25
14 namespace appcache { 26 namespace appcache {
15 27
16 MockAppCacheStorage::MockAppCacheStorage(AppCacheService* service) 28 MockAppCacheStorage::MockAppCacheStorage(AppCacheService* service)
17 : AppCacheStorage(service) { 29 : AppCacheStorage(service),
30 ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
18 last_cache_id_ = 0; 31 last_cache_id_ = 0;
19 last_entry_id_ = 0; 32 last_entry_id_ = 0;
20 last_group_id_ = 0; 33 last_group_id_ = 0;
21 last_response_id_ = 0; 34 last_response_id_ = 0;
22 } 35 }
23 36
37 MockAppCacheStorage::~MockAppCacheStorage() {
38 STLDeleteElements(&pending_tasks_);
39 }
40
24 void MockAppCacheStorage::LoadCache(int64 id, Delegate* delegate) { 41 void MockAppCacheStorage::LoadCache(int64 id, Delegate* delegate) {
42 DCHECK(delegate);
25 AppCache* cache = working_set_.GetCache(id); 43 AppCache* cache = working_set_.GetCache(id);
26 if (cache->HasOneRef()) { 44 if (ShouldCacheLoadAppearAsync(cache)) {
27 // TODO(michaeln): make the load look async 45 ScheduleTask(method_factory_.NewRunnableMethod(
46 &MockAppCacheStorage::ProcessLoadCache,
47 id, GetOrCreateDelegateReference(delegate)));
48 return;
28 } 49 }
29 delegate->OnCacheLoaded(cache, id); 50 ProcessLoadCache(id, GetOrCreateDelegateReference(delegate));
30 } 51 }
31 52
32 void MockAppCacheStorage::LoadOrCreateGroup( 53 void MockAppCacheStorage::LoadOrCreateGroup(
33 const GURL& manifest_url, Delegate* delegate) { 54 const GURL& manifest_url, Delegate* delegate) {
34 scoped_refptr<AppCacheGroup> group = working_set_.GetGroup(manifest_url); 55 DCHECK(delegate);
35 if (!group.get()) { 56 AppCacheGroup* group = working_set_.GetGroup(manifest_url);
36 group = new AppCacheGroup(service_, manifest_url); 57 if (ShouldGroupLoadAppearAsync(group)) {
37 DCHECK(working_set_.GetGroup(manifest_url)); 58 ScheduleTask(method_factory_.NewRunnableMethod(
59 &MockAppCacheStorage::ProcessLoadOrCreateGroup,
60 manifest_url, GetOrCreateDelegateReference(delegate)));
61 return;
38 } 62 }
39 // TODO(michaeln): make the load look async if all of the groups 63 ProcessLoadOrCreateGroup(
40 // caches only have one ref 64 manifest_url, GetOrCreateDelegateReference(delegate));
41 delegate->OnGroupLoaded(group.get(), manifest_url);
42 } 65 }
43 66
44 void MockAppCacheStorage::StoreGroupAndNewestCache( 67 void MockAppCacheStorage::StoreGroupAndNewestCache(
45 AppCacheGroup* group, Delegate* delegate) { 68 AppCacheGroup* group, Delegate* delegate) {
69 DCHECK(group && delegate);
46 DCHECK(group->newest_complete_cache()); 70 DCHECK(group->newest_complete_cache());
47 71
48 // TODO(michaeln): write me 72 // Always make this operation look async.
49 // 'store' the group + newest 73 ScheduleTask(method_factory_.NewRunnableMethod(
50 // 'unstore' the old caches 74 &MockAppCacheStorage::ProcessStoreGroupAndNewestCache,
51 // figure out which responses can be doomed and doom them 75 group, group->newest_complete_cache(),
52 // OldRepsonses - NewestResponse == ToBeDoomed 76 GetOrCreateDelegateReference(delegate)));
53
54 // TODO(michaeln): Make this appear async
55 //AddStoredGroup(group);
56 //AddStoredCache(group->newest_complete_cache());
57 //
58 //foreach(group->old_caches())
59 // RemoveStoredCache(old_cache);
60 //std::set<int64> doomed_responses_ = responses from old caches
61 //std::set<int64> needed_responses_ = responses from newest cache
62 //foreach(needed_responses_)
63 // doomed_responses_.remove(needed_response_);
64 //DoomResponses(group->manifest_url(), doomed_responses_);
65
66 delegate->OnGroupAndNewestCacheStored(group, false);
67 } 77 }
68 78
69 void MockAppCacheStorage::FindResponseForMainRequest( 79 void MockAppCacheStorage::FindResponseForMainRequest(
70 const GURL& url, Delegate* delegate) { 80 const GURL& url, Delegate* delegate) {
71 // TODO(michaeln): write me 81 DCHECK(delegate);
72 // 82
73 //foreach(stored_group) { 83 // Always make this operation look async.
74 // if (group->manifest_url()->origin() != url.GetOrigin()) 84 ScheduleTask(method_factory_.NewRunnableMethod(
75 // continue; 85 &MockAppCacheStorage::ProcessFindResponseForMainRequest,
76 // 86 url, GetOrCreateDelegateReference(delegate)));
77 // look for an entry
78 // look for a fallback namespace
79 // look for a online namespace
80 //}
81 delegate->OnMainResponseFound(
82 url, kNoResponseId, false, kNoCacheId, GURL::EmptyGURL());
83 } 87 }
84 88
85 void MockAppCacheStorage::MarkEntryAsForeign( 89 void MockAppCacheStorage::MarkEntryAsForeign(
86 const GURL& entry_url, int64 cache_id) { 90 const GURL& entry_url, int64 cache_id) {
87 // Update the working set.
88 AppCache* cache = working_set_.GetCache(cache_id); 91 AppCache* cache = working_set_.GetCache(cache_id);
89 if (cache) { 92 if (cache) {
90 AppCacheEntry* entry = cache->GetEntry(entry_url); 93 AppCacheEntry* entry = cache->GetEntry(entry_url);
91 DCHECK(entry); 94 DCHECK(entry);
92 if (entry) 95 if (entry)
93 entry->add_types(AppCacheEntry::FOREIGN); 96 entry->add_types(AppCacheEntry::FOREIGN);
94 } 97 }
95 // TODO(michaeln): in real storage update in storage, and if this cache is 98 // TODO(michaeln): in real storage update in storage, and if this cache is
96 // being loaded be sure to update the memory cache upon load completion. 99 // being loaded be sure to update the memory cache upon load completion.
97 } 100 }
98 101
99 void MockAppCacheStorage::MarkGroupAsObsolete( 102 void MockAppCacheStorage::MakeGroupObsolete(
100 AppCacheGroup* group, Delegate* delegate) { 103 AppCacheGroup* group, Delegate* delegate) {
101 // TODO(michaeln): write me 104 DCHECK(group && delegate);
102 // remove from working_set 105
103 // remove from storage 106 // Always make this method look async.
104 // doom things 107 ScheduleTask(method_factory_.NewRunnableMethod(
105 // group->set_obsolete(true); 108 &MockAppCacheStorage::ProcessMakeGroupObsolete,
106 // TODO(michaeln): Make this appear async 109 group, GetOrCreateDelegateReference(delegate)));
107 } 110 }
108 111
109 AppCacheResponseReader* MockAppCacheStorage::CreateResponseReader( 112 AppCacheResponseReader* MockAppCacheStorage::CreateResponseReader(
110 const GURL& origin, int64 response_id) { 113 const GURL& origin, int64 response_id) {
111 return new AppCacheResponseReader(response_id, disk_cache()); 114 return new AppCacheResponseReader(response_id, disk_cache());
112 } 115 }
113 116
114 AppCacheResponseWriter* MockAppCacheStorage::CreateResponseWriter( 117 AppCacheResponseWriter* MockAppCacheStorage::CreateResponseWriter(
115 const GURL& manifest_url) { 118 const GURL& manifest_url) {
116 return new AppCacheResponseWriter(NewResponseId(), disk_cache()); 119 return new AppCacheResponseWriter(NewResponseId(), disk_cache());
117 } 120 }
118 121
119 void MockAppCacheStorage::DoomResponses( 122 void MockAppCacheStorage::DoomResponses(
120 const GURL& manifest_url, const std::vector<int64>& response_ids) { 123 const GURL& manifest_url, const std::vector<int64>& response_ids) {
121 // We don't bother with deleting responses from mock storage. 124 // We don't bother with actually removing responses from the disk-cache,
125 // just keep track of which ids have been doomed.
126 std::vector<int64>::const_iterator it = response_ids.begin();
127 while (it != response_ids.end()) {
128 doomed_response_ids_.insert(*it);
129 ++it;
130 }
131 }
132
133 void MockAppCacheStorage::ProcessLoadCache(
134 int64 id, scoped_refptr<DelegateReference> delegate_ref) {
135 AppCache* cache = working_set_.GetCache(id);
136 if (delegate_ref->delegate)
137 delegate_ref->delegate->OnCacheLoaded(cache, id);
138 }
139
140 void MockAppCacheStorage::ProcessLoadOrCreateGroup(
141 const GURL& manifest_url, scoped_refptr<DelegateReference> delegate_ref) {
142 scoped_refptr<AppCacheGroup> group = working_set_.GetGroup(manifest_url);
143
144 // Newly created groups are not put in the stored_groups collection
145 // until StoreGroupAndNewestCache is called.
146 if (!group)
147 group = new AppCacheGroup(service_, manifest_url);
148
149 if (delegate_ref->delegate)
150 delegate_ref->delegate->OnGroupLoaded(group, manifest_url);
151 }
152
153 void MockAppCacheStorage::ProcessStoreGroupAndNewestCache(
154 scoped_refptr<AppCacheGroup> group,
155 scoped_refptr<AppCache> newest_cache,
156 scoped_refptr<DelegateReference> delegate_ref) {
157 DCHECK(group->newest_complete_cache() == newest_cache.get());
158
159 AddStoredGroup(group);
160 AddStoredCache(group->newest_complete_cache());
161
162 // Copy the collection prior to removal, on final release
163 // of a cache the group's collection will change.
164 AppCacheGroup::Caches copy = group->old_caches();
165 RemoveStoredCaches(copy);
166
167 if (delegate_ref->delegate)
168 delegate_ref->delegate->OnGroupAndNewestCacheStored(group, true);
169
170 // We don't bother with removing responses from 'mock' storage
171 // TODO(michaeln): for 'real' storage...
172 // std::set<int64> doomed_responses_ = responses from old caches
173 // std::set<int64> needed_responses_ = responses from newest cache
174 // foreach(needed_responses_)
175 // doomed_responses_.remove(needed_response_);
176 // DoomResponses(group->manifest_url(), doomed_responses_);
177 }
178
179 void MockAppCacheStorage::ProcessFindResponseForMainRequest(
180 const GURL& url, scoped_refptr<DelegateReference> delegate_ref) {
181 // TODO(michaeln): write me when doing AppCacheRequestHandler
182 // foreach(stored_group) {
183 // if (group->manifest_url()->origin() != url.GetOrigin())
184 // continue;
185 // look for an entry
186 // look for a fallback namespace
187 // look for a online namespace
188 // }
189 if (delegate_ref->delegate) {
190 delegate_ref->delegate->OnMainResponseFound(
191 url, AppCacheEntry(), kNoCacheId, GURL());
192 }
193 }
194
195 void MockAppCacheStorage::ProcessMakeGroupObsolete(
196 scoped_refptr<AppCacheGroup> group,
197 scoped_refptr<DelegateReference> delegate_ref) {
198 RemoveStoredGroup(group);
199 if (group->newest_complete_cache())
200 RemoveStoredCache(group->newest_complete_cache());
201
202 // Copy the collection prior to removal, on final release
203 // of a cache the group's collection will change.
204 AppCacheGroup::Caches copy = group->old_caches();
205 RemoveStoredCaches(copy);
206
207 group->set_obsolete(true);
208
209 if (delegate_ref->delegate)
210 delegate_ref->delegate->OnGroupMadeObsolete(group, true);
211 }
212
213 void MockAppCacheStorage::ScheduleTask(Task* task) {
214 pending_tasks_.push_back(task);
215 MessageLoop::current()->PostTask(FROM_HERE,
216 method_factory_.NewRunnableMethod(
217 &MockAppCacheStorage::RunOnePendingTask));
218 }
219
220 void MockAppCacheStorage::RunOnePendingTask() {
221 DCHECK(!pending_tasks_.empty());
222 Task* task = pending_tasks_.front();
223 pending_tasks_.pop_front();
224 task->Run();
225 delete task;
122 } 226 }
123 227
124 void MockAppCacheStorage::AddStoredCache(AppCache* cache) { 228 void MockAppCacheStorage::AddStoredCache(AppCache* cache) {
125 // cache->set_is_stored(true);
126 int64 cache_id = cache->cache_id(); 229 int64 cache_id = cache->cache_id();
127 if (stored_caches_.find(cache_id) == stored_caches_.end()) 230 if (stored_caches_.find(cache_id) == stored_caches_.end())
128 stored_caches_.insert(StoredCacheMap::value_type(cache_id, cache)); 231 stored_caches_.insert(StoredCacheMap::value_type(cache_id, cache));
129 } 232 }
130 233
131 void MockAppCacheStorage::RemoveStoredCache(AppCache* cache) { 234 void MockAppCacheStorage::RemoveStoredCache(AppCache* cache) {
132 // cache->set_is_stored(false); 235 // Do not remove from the working set, active caches are still usable
236 // and may be looked up by id until they fall out of use.
133 stored_caches_.erase(cache->cache_id()); 237 stored_caches_.erase(cache->cache_id());
134 } 238 }
135 239
240 void MockAppCacheStorage::RemoveStoredCaches(
241 const AppCacheGroup::Caches& caches) {
242 AppCacheGroup::Caches::const_iterator it = caches.begin();
243 while (it != caches.end()) {
244 RemoveStoredCache(*it);
245 ++it;
246 }
247 }
248
136 void MockAppCacheStorage::AddStoredGroup(AppCacheGroup* group) { 249 void MockAppCacheStorage::AddStoredGroup(AppCacheGroup* group) {
137 // group->set_is_stored(true);
138 const GURL& url = group->manifest_url(); 250 const GURL& url = group->manifest_url();
139 if (stored_groups_.find(url) == stored_groups_.end()) 251 if (stored_groups_.find(url) == stored_groups_.end())
140 stored_groups_.insert(StoredGroupMap::value_type(url, group)); 252 stored_groups_.insert(StoredGroupMap::value_type(url, group));
141 } 253 }
142 254
143 void MockAppCacheStorage::RemoveStoredGroup(AppCacheGroup* group) { 255 void MockAppCacheStorage::RemoveStoredGroup(AppCacheGroup* group) {
144 // group->set_is_stored(false); 256 // Also remove from the working set, caches for an 'obsolete' group
257 // may linger in use, but the group itself cannot be looked up by
258 // 'manifest_url' in the working set any longer.
259 working_set()->RemoveGroup(group);
145 stored_groups_.erase(group->manifest_url()); 260 stored_groups_.erase(group->manifest_url());
146 } 261 }
147 262
263 bool MockAppCacheStorage::ShouldGroupLoadAppearAsync(
264 const AppCacheGroup* group) {
265 // We'll have to query the database to see if a group for the
266 // manifest_url exists on disk. So return true for async.
267 if (!group)
268 return true;
269
270 // Groups without a newest cache can't have been put to disk yet, so
271 // we can synchronously return a reference we have in the working set.
272 if (!group->newest_complete_cache())
273 return false;
274
275 // The LoadGroup interface implies also loading the newest cache, so
276 // 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"
277 // loading of this group.
278 if (ShouldCacheLoadAppearAsync(group->newest_complete_cache()))
279 return true;
280
281
282 // If any of the old caches are "in use", then the group must also
283 // be memory resident and not require async loading.
284 const AppCacheGroup::Caches& old_caches = group->old_caches();
285 AppCacheGroup::Caches::const_iterator it = old_caches.begin();
286 while (it != old_caches.end()) {
287 // "in use" caches don't require async loading
288 if (!ShouldCacheLoadAppearAsync(*it))
289 return false;
290 ++it;
291 }
292
293 return true;
294 }
295
296 bool MockAppCacheStorage::ShouldCacheLoadAppearAsync(const AppCache* cache) {
297 if (!cache)
298 return true;
299
300 // If the 'stored' ref is the only ref, real storage will have to load from
301 // the database.
302 return IsCacheStored(cache) && cache->HasOneRef();
303 }
304
148 } // namespace appcache 305 } // namespace appcache
OLDNEW
« 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