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

Side by Side Diff: webkit/appcache/appcache_storage.h

Issue 269062: AppCacheResponse storage implementation (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 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 #ifndef WEBKIT_APPCACHE_APPCACHE_STORAGE_H_ 5 #ifndef WEBKIT_APPCACHE_APPCACHE_STORAGE_H_
6 #define WEBKIT_APPCACHE_APPCACHE_STORAGE_H_ 6 #define WEBKIT_APPCACHE_APPCACHE_STORAGE_H_
7 7
8 #include <map>
8 #include <vector> 9 #include <vector>
9 10
11 #include "base/compiler_specific.h"
10 #include "base/basictypes.h" 12 #include "base/basictypes.h"
11 #include "base/logging.h" 13 #include "base/ref_counted.h"
14 #include "net/base/net_errors.h"
15 #include "webkit/appcache/appcache_response.h"
12 #include "webkit/appcache/appcache_working_set.h" 16 #include "webkit/appcache/appcache_working_set.h"
13 17
14 class GURL; 18 class GURL;
15 19
16 namespace appcache { 20 namespace appcache {
17 21
18 class AppCache; 22 class AppCache;
19 class AppCacheGroup; 23 class AppCacheGroup;
20 class AppCacheResponseInfo;
21 class AppCacheResponseReader;
22 class AppCacheResponseWriter;
23 class AppCacheService; 24 class AppCacheService;
24 25
25 class AppCacheStorage { 26 class AppCacheStorage {
26 public: 27 public:
27 28
28 class Delegate { 29 class Delegate {
29 public: 30 public:
30 virtual ~Delegate() {} 31 virtual ~Delegate() {}
31 32
32 // If a load fails the 'cache' will be NULL. 33 // If a load fails the 'cache' will be NULL.
(...skipping 15 matching lines...) Expand all
48 AppCacheResponseInfo* response_info, int64 response_id) {} 49 AppCacheResponseInfo* response_info, int64 response_id) {}
49 50
50 // If no response is found, response_id will be kNoResponseId. 51 // If no response is found, response_id will be kNoResponseId.
51 // If a response is found, the cache id and manifest url of the 52 // If a response is found, the cache id and manifest url of the
52 // containing cache and group are also returned. 53 // containing cache and group are also returned.
53 virtual void OnMainResponseFound( 54 virtual void OnMainResponseFound(
54 const GURL& url, int64 response_id, bool is_fallback, 55 const GURL& url, int64 response_id, bool is_fallback,
55 int64 cache_id, const GURL& mainfest_url) {} 56 int64 cache_id, const GURL& mainfest_url) {}
56 }; 57 };
57 58
58 explicit AppCacheStorage(AppCacheService* service) 59 explicit AppCacheStorage(AppCacheService* service);
59 : last_cache_id_(kUnitializedId), last_group_id_(kUnitializedId), 60 virtual ~AppCacheStorage();
60 last_entry_id_(kUnitializedId), last_response_id_(kUnitializedId),
61 service_(service) {}
62 virtual ~AppCacheStorage() {}
63 61
64 // Schedules a cache to be loaded from storage. Upon load completion 62 // Schedules a cache to be loaded from storage. Upon load completion
65 // the delegate will be called back. If the cache already resides in 63 // the delegate will be called back. If the cache already resides in
66 // memory, the delegate will be called back immediately without returning 64 // memory, the delegate will be called back immediately without returning
67 // to the message loop. If the load fails, the delegate will be called 65 // to the message loop. If the load fails, the delegate will be called
68 // back with a NULL cache pointer. 66 // back with a NULL cache pointer.
69 virtual void LoadCache(int64 id, Delegate* delegate) = 0; 67 virtual void LoadCache(int64 id, Delegate* delegate) = 0;
70 68
71 // Schedules a group and its newest cache, if any, to be loaded from storage. 69 // Schedules a group and its newest cache, if any, to be loaded from storage.
72 // Upon load completion the delegate will be called back. If the group 70 // Upon load completion the delegate will be called back. If the group
73 // and newest cache already reside in memory, the delegate will be called 71 // and newest cache already reside in memory, the delegate will be called
74 // back immediately without returning to the message loop. If the load fails, 72 // back immediately without returning to the message loop. If the load fails,
75 // the delegate will be called back with a NULL group pointer. 73 // the delegate will be called back with a NULL group pointer.
76 virtual void LoadOrCreateGroup( 74 virtual void LoadOrCreateGroup(
77 const GURL& manifest_url, Delegate* delegate) = 0; 75 const GURL& manifest_url, Delegate* delegate) = 0;
78 76
79 // Schedules response info to be loaded from storage. 77 // Schedules response info to be loaded from storage.
80 // Upon load completion the delegate will be called back. If the data 78 // Upon load completion the delegate will be called back. If the data
81 // already resides in memory, the delegate will be called back 79 // already resides in memory, the delegate will be called back
82 // immediately without returning to the message loop. If the load fails, 80 // immediately without returning to the message loop. If the load fails,
83 // the delegate will be called back with a NULL pointer. 81 // the delegate will be called back with a NULL pointer.
84 virtual void LoadResponseInfo( 82 virtual void LoadResponseInfo(
85 const GURL& manifest_url, int64 response_id, Delegate* delegate) = 0; 83 const GURL& manifest_url, int64 response_id, Delegate* delegate);
86 84
87 // Schedules a group and its newest complete cache to be initially stored or 85 // Schedules a group and its newest complete cache to be initially stored or
88 // incrementally updated with new changes. Upon completion the delegate 86 // incrementally updated with new changes. Upon completion the delegate
89 // will be called back. A group without a newest cache cannot be stored. 87 // will be called back. A group without a newest cache cannot be stored.
90 // It's a programming error to call this method with such a group. A 88 // It's a programming error to call this method with such a group. A
91 // side effect of storing a new newest cache is the removal of the group's 89 // side effect of storing a new newest cache is the removal of the group's
92 // old caches and responses from persistent storage (although they may still 90 // old caches and responses from persistent storage (although they may still
93 // linger in the in-memory working set until no longer needed). 91 // linger in the in-memory working set until no longer needed).
94 virtual void StoreGroupAndNewestCache( 92 virtual void StoreGroupAndNewestCache(
95 AppCacheGroup* group, Delegate* delegate) = 0; 93 AppCacheGroup* group, Delegate* delegate) = 0;
(...skipping 12 matching lines...) Expand all
108 // Schedules a task to update persistent storage and doom the group and all 106 // Schedules a task to update persistent storage and doom the group and all
109 // related caches and responses for deletion. Upon completion the in-memory 107 // related caches and responses for deletion. Upon completion the in-memory
110 // instance is marked as obsolete and the delegate callback is called. 108 // instance is marked as obsolete and the delegate callback is called.
111 virtual void MarkGroupAsObsolete( 109 virtual void MarkGroupAsObsolete(
112 AppCacheGroup* group, Delegate* delegate) = 0; 110 AppCacheGroup* group, Delegate* delegate) = 0;
113 111
114 // Cancels all pending callbacks for the delegate. The delegate callbacks 112 // Cancels all pending callbacks for the delegate. The delegate callbacks
115 // will not be invoked after, however any scheduled operations will still 113 // will not be invoked after, however any scheduled operations will still
116 // take place. The callbacks for subsequently scheduled operations are 114 // take place. The callbacks for subsequently scheduled operations are
117 // unaffected. 115 // unaffected.
118 virtual void CancelDelegateCallbacks(Delegate* delegate) = 0; 116 void CancelDelegateCallbacks(Delegate* delegate) {
117 DelegateReference* delegate_reference = GetDelegateReference(delegate);
118 if (delegate_reference)
119 delegate_reference->CancelReference();
120 }
119 121
120 // Creates a reader to read a response from storage. 122 // Creates a reader to read a response from storage.
121 virtual AppCacheResponseReader* CreateResponseReader( 123 virtual AppCacheResponseReader* CreateResponseReader(
122 const GURL& manifest_url, int64 response_id) = 0; 124 const GURL& manifest_url, int64 response_id) = 0;
123 125
124 // Creates a writer to write a new response to storage. This call 126 // Creates a writer to write a new response to storage. This call
125 // establishes a new response id. 127 // establishes a new response id.
126 virtual AppCacheResponseWriter* CreateResponseWriter( 128 virtual AppCacheResponseWriter* CreateResponseWriter(
127 const GURL& manifest_url) = 0; 129 const GURL& manifest_url) = 0;
128 130
129 // Schedules the deletion of many responses. 131 // Schedules the deletion of many responses.
130 virtual void DoomResponses( 132 virtual void DoomResponses(
131 const GURL& manifest_url, const std::vector<int64>& response_ids) = 0; 133 const GURL& manifest_url, const std::vector<int64>& response_ids) = 0;
132 134
133 // Generates unique storage ids for different object types. 135 // Generates unique storage ids for different object types.
134 int64 NewCacheId() { 136 int64 NewCacheId() {
135 DCHECK(last_cache_id_ != kUnitializedId);
136 return ++last_cache_id_; 137 return ++last_cache_id_;
137 } 138 }
138 int64 NewGroupId() { 139 int64 NewGroupId() {
139 DCHECK(last_group_id_ != kUnitializedId);
140 return ++last_group_id_; 140 return ++last_group_id_;
141 } 141 }
142 int64 NewEntryId() { 142 int64 NewEntryId() {
143 DCHECK(last_entry_id_ != kUnitializedId);
144 return ++last_entry_id_; 143 return ++last_entry_id_;
145 } 144 }
146 145
147 // The working set of object instances currently in memory. 146 // The working set of object instances currently in memory.
148 AppCacheWorkingSet* working_set() { return &working_set_; } 147 AppCacheWorkingSet* working_set() { return &working_set_; }
149 148
150 // Simple ptr back to the service object that owns us. 149 // Simple ptr back to the service object that owns us.
151 AppCacheService* service() { return service_; } 150 AppCacheService* service() { return service_; }
152 151
153 protected: 152 protected:
153 friend class AppCacheResponseTest;
154
155 // Helper to call a collection of delegates.
156 #define FOR_EACH_DELEGATE(delegates, func_and_args) \
157 do { \
158 for (DelegateReferenceVector::iterator it = delegates.begin(); \
159 it != delegates.end(); ++it) { \
160 if (it->get()->delegate) \
161 it->get()->delegate->func_and_args; \
162 } \
163 } while (0)
164
165 // Helper used to manage multiple references to a 'delegate' and to
166 // allow all pending callbacks to that delegate to be easily cancelled.
167 struct DelegateReference : public base::RefCounted<DelegateReference> {
168 Delegate* delegate;
169 AppCacheStorage* storage;
170
171 DelegateReference(Delegate* delegate, AppCacheStorage* storage)
172 : delegate(delegate), storage(storage) {
173 storage->delegate_references_.insert(
174 DelegateReferenceMap::value_type(delegate, this));
175 }
176
177 ~DelegateReference() {
178 if (delegate)
179 storage->delegate_references_.erase(delegate);
180 }
181
182 void CancelReference() {
183 storage->delegate_references_.erase(delegate);
184 storage = NULL;
185 delegate = NULL;
186 }
187 };
188 typedef std::map<Delegate*, DelegateReference*> DelegateReferenceMap;
189 typedef std::vector<scoped_refptr<DelegateReference> >
190 DelegateReferenceVector;
191
192 // Helper used to manage an async LoadResponseInfo calls on behalf of
193 // multiple callers.
194 // TODO(michaeln): this may be generalizable for other load/store 'tasks'
195 class ResponseInfoLoadTask {
196 public:
197 ResponseInfoLoadTask(const GURL& manifest_url, int64 response_id,
198 AppCacheStorage* storage) :
199 storage_(storage),
200 manifest_url_(manifest_url),
201 response_id_(response_id),
202 info_buffer_(new HttpResponseInfoIOBuffer),
203 ALLOW_THIS_IN_INITIALIZER_LIST(read_callback_(
204 this, &ResponseInfoLoadTask::OnReadComplete)) {
205 ALLOW_THIS_IN_INITIALIZER_LIST(storage_->pending_info_loads_.insert(
206 PendingResponseInfoLoads::value_type(response_id, this)));
207 }
208
209 int64 response_id() const { return response_id_; }
210 const GURL& manifest_url() const { return manifest_url_; }
211
212 void AddDelegate(DelegateReference* delegate_reference) {
213 delegates_.push_back(delegate_reference);
214 }
215
216 void StartIfNeeded() {
217 if (reader_.get())
218 return;
219 reader_.reset(
220 storage_->CreateResponseReader(manifest_url_, response_id_));
221 reader_->ReadInfo(info_buffer_, &read_callback_);
222 }
223
224 private:
225 void OnReadComplete(int result) {
226 storage_->pending_info_loads_.erase(response_id_);
227 scoped_refptr<AppCacheResponseInfo> info;
228 if (result >= 0) {
229 info = new AppCacheResponseInfo(
230 storage_->service(), reader_->response_id(),
231 info_buffer_->http_info.release());
232 }
233 FOR_EACH_DELEGATE(
234 delegates_, OnResponseInfoLoaded(info.get(), response_id_));
235 delete this;
236 }
237
238 AppCacheStorage* storage_;
239 GURL manifest_url_;
240 int64 response_id_;
241 scoped_ptr<AppCacheResponseReader> reader_;
242 DelegateReferenceVector delegates_;
243 scoped_refptr<HttpResponseInfoIOBuffer> info_buffer_;
244 net::CompletionCallbackImpl<ResponseInfoLoadTask> read_callback_;
245 };
246
247 typedef std::map<int64, ResponseInfoLoadTask*> PendingResponseInfoLoads;
248
249 DelegateReference* GetDelegateReference(Delegate* delegate) {
250 DelegateReferenceMap::iterator iter =
251 delegate_references_.find(delegate);
252 if (iter != delegate_references_.end())
253 return iter->second;
254 return NULL;
255 }
256
257 DelegateReference* GetOrCreateDelegateReference(Delegate* delegate) {
258 DelegateReference* reference = GetDelegateReference(delegate);
259 if (reference)
260 return reference;
261 return new DelegateReference(delegate, this);
262 }
263
264 ResponseInfoLoadTask* GetOrCreateResponseInfoLoadTask(
265 const GURL& manifest_url, int64 response_id) {
266 PendingResponseInfoLoads::iterator iter =
267 pending_info_loads_.find(response_id);
268 if (iter != pending_info_loads_.end())
269 return iter->second;
270 return new ResponseInfoLoadTask(manifest_url, response_id, this);
271 }
272
154 // Should only be called when creating a new response writer. 273 // Should only be called when creating a new response writer.
155 int64 NewResponseId() { 274 int64 NewResponseId() {
156 DCHECK(last_response_id_ != kUnitializedId);
157 return ++last_response_id_; 275 return ++last_response_id_;
158 } 276 }
159 277
160 // The last storage id used for different object types. 278 // The last storage id used for different object types.
161 int64 last_cache_id_; 279 int64 last_cache_id_;
162 int64 last_group_id_; 280 int64 last_group_id_;
163 int64 last_entry_id_; 281 int64 last_entry_id_;
164 int64 last_response_id_; 282 int64 last_response_id_;
165 283
166 AppCacheWorkingSet working_set_; 284 AppCacheWorkingSet working_set_;
167 AppCacheService* service_; 285 AppCacheService* service_;
286 DelegateReferenceMap delegate_references_;
287 PendingResponseInfoLoads pending_info_loads_;
168 288
169 // The set of last ids must be retrieved from storage prior to being used. 289 // The set of last ids must be retrieved from storage prior to being used.
170 static const int64 kUnitializedId = -1; 290 static const int64 kUnitializedId = -1;
171 291
172 DISALLOW_COPY_AND_ASSIGN(AppCacheStorage); 292 DISALLOW_COPY_AND_ASSIGN(AppCacheStorage);
173 }; 293 };
174 294
295 // TODO(michaeln): Maybe?
296 class AppCacheStoredItem {
297 public:
298 bool is_doomed() const { return is_doomed_; }
299 bool is_stored() const { return is_stored_; }
300
301 protected:
302 AppCacheStoredItem() : is_doomed_(false), is_stored_(false) {}
303
304 private:
305 friend class AppCacheStorage;
306 friend class MockAppCacheStorage;
307
308 void set_is_doomed(bool b) { is_doomed_ = b; }
309 void set_is_stored(bool b) { is_stored_ = b; }
310
311 bool is_doomed_;
312 bool is_stored_;
313 };
314
175 } // namespace appcache 315 } // namespace appcache
176 316
177 #endif // WEBKIT_APPCACHE_APPCACHE_STORAGE_H_ 317 #endif // WEBKIT_APPCACHE_APPCACHE_STORAGE_H_
178 318
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698