| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |