| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #ifndef WEBKIT_BROWSER_APPCACHE_APPCACHE_STORAGE_H_ | |
| 6 #define WEBKIT_BROWSER_APPCACHE_APPCACHE_STORAGE_H_ | |
| 7 | |
| 8 #include <map> | |
| 9 #include <vector> | |
| 10 | |
| 11 #include "base/basictypes.h" | |
| 12 #include "base/compiler_specific.h" | |
| 13 #include "base/gtest_prod_util.h" | |
| 14 #include "base/memory/ref_counted.h" | |
| 15 #include "base/memory/scoped_ptr.h" | |
| 16 #include "net/base/completion_callback.h" | |
| 17 #include "webkit/browser/appcache/appcache_working_set.h" | |
| 18 #include "webkit/browser/webkit_storage_browser_export.h" | |
| 19 | |
| 20 class GURL; | |
| 21 | |
| 22 namespace content { | |
| 23 FORWARD_DECLARE_TEST(AppCacheStorageTest, DelegateReferences); | |
| 24 FORWARD_DECLARE_TEST(AppCacheStorageTest, UsageMap); | |
| 25 class AppCacheQuotaClientTest; | |
| 26 class AppCacheResponseTest; | |
| 27 class AppCacheStorageTest; | |
| 28 } | |
| 29 | |
| 30 namespace appcache { | |
| 31 | |
| 32 class AppCache; | |
| 33 class AppCacheEntry; | |
| 34 class AppCacheGroup; | |
| 35 class AppCacheResponseReader; | |
| 36 class AppCacheResponseWriter; | |
| 37 class AppCacheServiceImpl; | |
| 38 struct AppCacheInfoCollection; | |
| 39 struct HttpResponseInfoIOBuffer; | |
| 40 | |
| 41 class WEBKIT_STORAGE_BROWSER_EXPORT AppCacheStorage { | |
| 42 public: | |
| 43 typedef std::map<GURL, int64> UsageMap; | |
| 44 | |
| 45 class WEBKIT_STORAGE_BROWSER_EXPORT Delegate { | |
| 46 public: | |
| 47 // If retrieval fails, 'collection' will be NULL. | |
| 48 virtual void OnAllInfo(AppCacheInfoCollection* collection) {} | |
| 49 | |
| 50 // If a load fails the 'cache' will be NULL. | |
| 51 virtual void OnCacheLoaded(AppCache* cache, int64 cache_id) {} | |
| 52 | |
| 53 // If a load fails the 'group' will be NULL. | |
| 54 virtual void OnGroupLoaded( | |
| 55 AppCacheGroup* group, const GURL& manifest_url) {} | |
| 56 | |
| 57 // If successfully stored 'success' will be true. | |
| 58 virtual void OnGroupAndNewestCacheStored( | |
| 59 AppCacheGroup* group, AppCache* newest_cache, bool success, | |
| 60 bool would_exceed_quota) {} | |
| 61 | |
| 62 // If the operation fails, success will be false. | |
| 63 virtual void OnGroupMadeObsolete(AppCacheGroup* group, | |
| 64 bool success, | |
| 65 int response_code) {} | |
| 66 | |
| 67 // If a load fails the 'response_info' will be NULL. | |
| 68 virtual void OnResponseInfoLoaded( | |
| 69 AppCacheResponseInfo* response_info, int64 response_id) {} | |
| 70 | |
| 71 // If no response is found, entry.response_id() and | |
| 72 // fallback_entry.response_id() will be kAppCacheNoResponseId. | |
| 73 // If the response is the entry for an intercept or fallback | |
| 74 // namespace, the url of the namespece entry is returned. | |
| 75 // If a response is found, the cache id and manifest url of the | |
| 76 // containing cache and group are also returned. | |
| 77 virtual void OnMainResponseFound( | |
| 78 const GURL& url, const AppCacheEntry& entry, | |
| 79 const GURL& namespace_entry_url, const AppCacheEntry& fallback_entry, | |
| 80 int64 cache_id, int64 group_id, const GURL& mainfest_url) {} | |
| 81 | |
| 82 protected: | |
| 83 virtual ~Delegate() {} | |
| 84 }; | |
| 85 | |
| 86 explicit AppCacheStorage(AppCacheServiceImpl* service); | |
| 87 virtual ~AppCacheStorage(); | |
| 88 | |
| 89 // Schedules a task to retrieve basic info about all groups and caches | |
| 90 // stored in the system. Upon completion the delegate will be called | |
| 91 // with the results. | |
| 92 virtual void GetAllInfo(Delegate* delegate) = 0; | |
| 93 | |
| 94 // Schedules a cache to be loaded from storage. Upon load completion | |
| 95 // the delegate will be called back. If the cache already resides in | |
| 96 // memory, the delegate will be called back immediately without returning | |
| 97 // to the message loop. If the load fails, the delegate will be called | |
| 98 // back with a NULL cache pointer. | |
| 99 virtual void LoadCache(int64 id, Delegate* delegate) = 0; | |
| 100 | |
| 101 // Schedules a group and its newest cache, if any, to be loaded from storage. | |
| 102 // Upon load completion the delegate will be called back. If the group | |
| 103 // and newest cache already reside in memory, the delegate will be called | |
| 104 // back immediately without returning to the message loop. If the load fails, | |
| 105 // the delegate will be called back with a NULL group pointer. | |
| 106 virtual void LoadOrCreateGroup( | |
| 107 const GURL& manifest_url, Delegate* delegate) = 0; | |
| 108 | |
| 109 // Schedules response info to be loaded from storage. | |
| 110 // Upon load completion the delegate will be called back. If the data | |
| 111 // already resides in memory, the delegate will be called back | |
| 112 // immediately without returning to the message loop. If the load fails, | |
| 113 // the delegate will be called back with a NULL pointer. | |
| 114 virtual void LoadResponseInfo( | |
| 115 const GURL& manifest_url, int64 group_id, int64 response_id, | |
| 116 Delegate* delegate); | |
| 117 | |
| 118 // Schedules a group and its newest complete cache to be initially stored or | |
| 119 // incrementally updated with new changes. Upon completion the delegate | |
| 120 // will be called back. A group without a newest cache cannot be stored. | |
| 121 // It's a programming error to call this method without a newest cache. A | |
| 122 // side effect of storing a new newest cache is the removal of the group's | |
| 123 // old caches and responses from persistent storage (although they may still | |
| 124 // linger in the in-memory working set until no longer needed). The new | |
| 125 // cache will be added as the group's newest complete cache only if storage | |
| 126 // succeeds. | |
| 127 virtual void StoreGroupAndNewestCache( | |
| 128 AppCacheGroup* group, AppCache* newest_cache, Delegate* delegate) = 0; | |
| 129 | |
| 130 // Schedules a query to identify a response for a main request. Upon | |
| 131 // completion the delegate will be called back. | |
| 132 virtual void FindResponseForMainRequest( | |
| 133 const GURL& url, | |
| 134 const GURL& preferred_manifest_url, | |
| 135 Delegate* delegate) = 0; | |
| 136 | |
| 137 // Performs an immediate lookup of the in-memory cache to | |
| 138 // identify a response for a sub resource request. | |
| 139 virtual void FindResponseForSubRequest( | |
| 140 AppCache* cache, const GURL& url, | |
| 141 AppCacheEntry* found_entry, AppCacheEntry* found_fallback_entry, | |
| 142 bool* found_network_namespace) = 0; | |
| 143 | |
| 144 // Immediately updates in-memory storage, if the cache is in memory, | |
| 145 // and schedules a task to update persistent storage. If the cache is | |
| 146 // already scheduled to be loaded, upon loading completion the entry | |
| 147 // will be marked. There is no delegate completion callback. | |
| 148 virtual void MarkEntryAsForeign(const GURL& entry_url, int64 cache_id) = 0; | |
| 149 | |
| 150 // Schedules a task to update persistent storage and doom the group and all | |
| 151 // related caches and responses for deletion. Upon completion the in-memory | |
| 152 // instance is marked as obsolete and the delegate callback is called. | |
| 153 virtual void MakeGroupObsolete(AppCacheGroup* group, | |
| 154 Delegate* delegate, | |
| 155 int response_code) = 0; | |
| 156 | |
| 157 // Cancels all pending callbacks for the delegate. The delegate callbacks | |
| 158 // will not be invoked after, however any scheduled operations will still | |
| 159 // take place. The callbacks for subsequently scheduled operations are | |
| 160 // unaffected. | |
| 161 void CancelDelegateCallbacks(Delegate* delegate) { | |
| 162 DelegateReference* delegate_reference = GetDelegateReference(delegate); | |
| 163 if (delegate_reference) | |
| 164 delegate_reference->CancelReference(); | |
| 165 } | |
| 166 | |
| 167 // Creates a reader to read a response from storage. | |
| 168 virtual AppCacheResponseReader* CreateResponseReader( | |
| 169 const GURL& manifest_url, int64 group_id, int64 response_id) = 0; | |
| 170 | |
| 171 // Creates a writer to write a new response to storage. This call | |
| 172 // establishes a new response id. | |
| 173 virtual AppCacheResponseWriter* CreateResponseWriter( | |
| 174 const GURL& manifest_url, int64 group_id) = 0; | |
| 175 | |
| 176 // Schedules the lazy deletion of responses and saves the ids | |
| 177 // persistently such that the responses will be deleted upon restart | |
| 178 // if they aren't deleted prior to shutdown. | |
| 179 virtual void DoomResponses( | |
| 180 const GURL& manifest_url, const std::vector<int64>& response_ids) = 0; | |
| 181 | |
| 182 // Schedules the lazy deletion of responses without persistently saving | |
| 183 // the response ids. | |
| 184 virtual void DeleteResponses( | |
| 185 const GURL& manifest_url, const std::vector<int64>& response_ids) = 0; | |
| 186 | |
| 187 // Generates unique storage ids for different object types. | |
| 188 int64 NewCacheId() { | |
| 189 return ++last_cache_id_; | |
| 190 } | |
| 191 int64 NewGroupId() { | |
| 192 return ++last_group_id_; | |
| 193 } | |
| 194 | |
| 195 // The working set of object instances currently in memory. | |
| 196 AppCacheWorkingSet* working_set() { return &working_set_; } | |
| 197 | |
| 198 // A map of origins to usage. | |
| 199 const UsageMap* usage_map() { return &usage_map_; } | |
| 200 | |
| 201 // Simple ptr back to the service object that owns us. | |
| 202 AppCacheServiceImpl* service() { return service_; } | |
| 203 | |
| 204 protected: | |
| 205 friend class content::AppCacheQuotaClientTest; | |
| 206 friend class content::AppCacheResponseTest; | |
| 207 friend class content::AppCacheStorageTest; | |
| 208 | |
| 209 // Helper to call a collection of delegates. | |
| 210 #define FOR_EACH_DELEGATE(delegates, func_and_args) \ | |
| 211 do { \ | |
| 212 for (DelegateReferenceVector::iterator it = delegates.begin(); \ | |
| 213 it != delegates.end(); ++it) { \ | |
| 214 if (it->get()->delegate) \ | |
| 215 it->get()->delegate->func_and_args; \ | |
| 216 } \ | |
| 217 } while (0) | |
| 218 | |
| 219 // Helper used to manage multiple references to a 'delegate' and to | |
| 220 // allow all pending callbacks to that delegate to be easily cancelled. | |
| 221 struct DelegateReference : public base::RefCounted<DelegateReference> { | |
| 222 Delegate* delegate; | |
| 223 AppCacheStorage* storage; | |
| 224 | |
| 225 DelegateReference(Delegate* delegate, AppCacheStorage* storage); | |
| 226 | |
| 227 void CancelReference() { | |
| 228 storage->delegate_references_.erase(delegate); | |
| 229 storage = NULL; | |
| 230 delegate = NULL; | |
| 231 } | |
| 232 | |
| 233 private: | |
| 234 friend class base::RefCounted<DelegateReference>; | |
| 235 | |
| 236 virtual ~DelegateReference(); | |
| 237 }; | |
| 238 typedef std::map<Delegate*, DelegateReference*> DelegateReferenceMap; | |
| 239 typedef std::vector<scoped_refptr<DelegateReference> > | |
| 240 DelegateReferenceVector; | |
| 241 | |
| 242 // Helper used to manage an async LoadResponseInfo calls on behalf of | |
| 243 // multiple callers. | |
| 244 class ResponseInfoLoadTask { | |
| 245 public: | |
| 246 ResponseInfoLoadTask(const GURL& manifest_url, int64 group_id, | |
| 247 int64 response_id, AppCacheStorage* storage); | |
| 248 ~ResponseInfoLoadTask(); | |
| 249 | |
| 250 int64 response_id() const { return response_id_; } | |
| 251 const GURL& manifest_url() const { return manifest_url_; } | |
| 252 int64 group_id() const { return group_id_; } | |
| 253 | |
| 254 void AddDelegate(DelegateReference* delegate_reference) { | |
| 255 delegates_.push_back(delegate_reference); | |
| 256 } | |
| 257 | |
| 258 void StartIfNeeded(); | |
| 259 | |
| 260 private: | |
| 261 void OnReadComplete(int result); | |
| 262 | |
| 263 AppCacheStorage* storage_; | |
| 264 GURL manifest_url_; | |
| 265 int64 group_id_; | |
| 266 int64 response_id_; | |
| 267 scoped_ptr<AppCacheResponseReader> reader_; | |
| 268 DelegateReferenceVector delegates_; | |
| 269 scoped_refptr<HttpResponseInfoIOBuffer> info_buffer_; | |
| 270 }; | |
| 271 | |
| 272 typedef std::map<int64, ResponseInfoLoadTask*> PendingResponseInfoLoads; | |
| 273 | |
| 274 DelegateReference* GetDelegateReference(Delegate* delegate) { | |
| 275 DelegateReferenceMap::iterator iter = | |
| 276 delegate_references_.find(delegate); | |
| 277 if (iter != delegate_references_.end()) | |
| 278 return iter->second; | |
| 279 return NULL; | |
| 280 } | |
| 281 | |
| 282 DelegateReference* GetOrCreateDelegateReference(Delegate* delegate) { | |
| 283 DelegateReference* reference = GetDelegateReference(delegate); | |
| 284 if (reference) | |
| 285 return reference; | |
| 286 return new DelegateReference(delegate, this); | |
| 287 } | |
| 288 | |
| 289 ResponseInfoLoadTask* GetOrCreateResponseInfoLoadTask( | |
| 290 const GURL& manifest_url, int64 group_id, int64 response_id) { | |
| 291 PendingResponseInfoLoads::iterator iter = | |
| 292 pending_info_loads_.find(response_id); | |
| 293 if (iter != pending_info_loads_.end()) | |
| 294 return iter->second; | |
| 295 return new ResponseInfoLoadTask(manifest_url, group_id, response_id, this); | |
| 296 } | |
| 297 | |
| 298 // Should only be called when creating a new response writer. | |
| 299 int64 NewResponseId() { | |
| 300 return ++last_response_id_; | |
| 301 } | |
| 302 | |
| 303 // Helpers to query and notify the QuotaManager. | |
| 304 void UpdateUsageMapAndNotify(const GURL& origin, int64 new_usage); | |
| 305 void ClearUsageMapAndNotify(); | |
| 306 void NotifyStorageAccessed(const GURL& origin); | |
| 307 | |
| 308 // The last storage id used for different object types. | |
| 309 int64 last_cache_id_; | |
| 310 int64 last_group_id_; | |
| 311 int64 last_response_id_; | |
| 312 | |
| 313 UsageMap usage_map_; // maps origin to usage | |
| 314 AppCacheWorkingSet working_set_; | |
| 315 AppCacheServiceImpl* service_; | |
| 316 DelegateReferenceMap delegate_references_; | |
| 317 PendingResponseInfoLoads pending_info_loads_; | |
| 318 | |
| 319 // The set of last ids must be retrieved from storage prior to being used. | |
| 320 static const int64 kUnitializedId; | |
| 321 | |
| 322 FRIEND_TEST_ALL_PREFIXES(content::AppCacheStorageTest, DelegateReferences); | |
| 323 FRIEND_TEST_ALL_PREFIXES(content::AppCacheStorageTest, UsageMap); | |
| 324 | |
| 325 DISALLOW_COPY_AND_ASSIGN(AppCacheStorage); | |
| 326 }; | |
| 327 | |
| 328 } // namespace appcache | |
| 329 | |
| 330 #endif // WEBKIT_BROWSER_APPCACHE_APPCACHE_STORAGE_H_ | |
| OLD | NEW |