diff options
Diffstat (limited to 'webkit/browser/appcache/appcache_storage.h')
-rw-r--r-- | webkit/browser/appcache/appcache_storage.h | 322 |
1 files changed, 322 insertions, 0 deletions
diff --git a/webkit/browser/appcache/appcache_storage.h b/webkit/browser/appcache/appcache_storage.h new file mode 100644 index 0000000..eb4df25 --- /dev/null +++ b/webkit/browser/appcache/appcache_storage.h @@ -0,0 +1,322 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef WEBKIT_BROWSER_APPCACHE_APPCACHE_STORAGE_H_ +#define WEBKIT_BROWSER_APPCACHE_APPCACHE_STORAGE_H_ + +#include <map> +#include <vector> + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "base/gtest_prod_util.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "net/base/completion_callback.h" +#include "webkit/browser/appcache/appcache_working_set.h" +#include "webkit/storage/webkit_storage_export.h" + +class GURL; + +namespace appcache { + +class AppCache; +class AppCacheEntry; +class AppCacheGroup; +class AppCacheResponseReader; +class AppCacheResponseWriter; +class AppCacheService; +struct AppCacheInfoCollection; +struct HttpResponseInfoIOBuffer; + +class WEBKIT_STORAGE_EXPORT AppCacheStorage { + public: + typedef std::map<GURL, int64> UsageMap; + + class WEBKIT_STORAGE_EXPORT Delegate { + public: + // If retrieval fails, 'collection' will be NULL. + virtual void OnAllInfo(AppCacheInfoCollection* collection) {} + + // If a load fails the 'cache' will be NULL. + virtual void OnCacheLoaded(AppCache* cache, int64 cache_id) {} + + // If a load fails the 'group' will be NULL. + virtual void OnGroupLoaded( + AppCacheGroup* group, const GURL& manifest_url) {} + + // If successfully stored 'success' will be true. + virtual void OnGroupAndNewestCacheStored( + AppCacheGroup* group, AppCache* newest_cache, bool success, + bool would_exceed_quota) {} + + // If the operation fails, success will be false. + virtual void OnGroupMadeObsolete(AppCacheGroup* group, bool success) {} + + // If a load fails the 'response_info' will be NULL. + virtual void OnResponseInfoLoaded( + AppCacheResponseInfo* response_info, int64 response_id) {} + + // If no response is found, entry.response_id() and + // fallback_entry.response_id() will be kNoResponseId. + // If the response is the entry for an intercept or fallback + // namespace, the url of the namespece entry is returned. + // If a response is found, the cache id and manifest url of the + // containing cache and group are also returned. + virtual void OnMainResponseFound( + const GURL& url, const AppCacheEntry& entry, + const GURL& namespace_entry_url, const AppCacheEntry& fallback_entry, + int64 cache_id, int64 group_id, const GURL& mainfest_url) {} + + protected: + virtual ~Delegate() {} + }; + + explicit AppCacheStorage(AppCacheService* service); + virtual ~AppCacheStorage(); + + // Schedules a task to retrieve basic info about all groups and caches + // stored in the system. Upon completion the delegate will be called + // with the results. + virtual void GetAllInfo(Delegate* delegate) = 0; + + // Schedules a cache to be loaded from storage. Upon load completion + // the delegate will be called back. If the cache already resides in + // memory, the delegate will be called back immediately without returning + // to the message loop. If the load fails, the delegate will be called + // back with a NULL cache pointer. + virtual void LoadCache(int64 id, Delegate* delegate) = 0; + + // Schedules a group and its newest cache, if any, to be loaded from storage. + // Upon load completion the delegate will be called back. If the group + // and newest cache already reside in memory, the delegate will be called + // back immediately without returning to the message loop. If the load fails, + // the delegate will be called back with a NULL group pointer. + virtual void LoadOrCreateGroup( + const GURL& manifest_url, Delegate* delegate) = 0; + + // Schedules response info to be loaded from storage. + // Upon load completion the delegate will be called back. If the data + // already resides in memory, the delegate will be called back + // immediately without returning to the message loop. If the load fails, + // the delegate will be called back with a NULL pointer. + virtual void LoadResponseInfo( + const GURL& manifest_url, int64 group_id, int64 response_id, + Delegate* delegate); + + // Schedules a group and its newest complete cache to be initially stored or + // incrementally updated with new changes. Upon completion the delegate + // will be called back. A group without a newest cache cannot be stored. + // It's a programming error to call this method without a newest cache. A + // side effect of storing a new newest cache is the removal of the group's + // old caches and responses from persistent storage (although they may still + // linger in the in-memory working set until no longer needed). The new + // cache will be added as the group's newest complete cache only if storage + // succeeds. + virtual void StoreGroupAndNewestCache( + AppCacheGroup* group, AppCache* newest_cache, Delegate* delegate) = 0; + + // Schedules a query to identify a response for a main request. Upon + // completion the delegate will be called back. + virtual void FindResponseForMainRequest( + const GURL& url, + const GURL& preferred_manifest_url, + Delegate* delegate) = 0; + + // Performs an immediate lookup of the in-memory cache to + // identify a response for a sub resource request. + virtual void FindResponseForSubRequest( + AppCache* cache, const GURL& url, + AppCacheEntry* found_entry, AppCacheEntry* found_fallback_entry, + bool* found_network_namespace) = 0; + + // Immediately updates in-memory storage, if the cache is in memory, + // and schedules a task to update persistent storage. If the cache is + // already scheduled to be loaded, upon loading completion the entry + // will be marked. There is no delegate completion callback. + virtual void MarkEntryAsForeign(const GURL& entry_url, int64 cache_id) = 0; + + // Schedules a task to update persistent storage and doom the group and all + // related caches and responses for deletion. Upon completion the in-memory + // instance is marked as obsolete and the delegate callback is called. + virtual void MakeGroupObsolete( + AppCacheGroup* group, Delegate* delegate) = 0; + + // Cancels all pending callbacks for the delegate. The delegate callbacks + // will not be invoked after, however any scheduled operations will still + // take place. The callbacks for subsequently scheduled operations are + // unaffected. + void CancelDelegateCallbacks(Delegate* delegate) { + DelegateReference* delegate_reference = GetDelegateReference(delegate); + if (delegate_reference) + delegate_reference->CancelReference(); + } + + // Creates a reader to read a response from storage. + virtual AppCacheResponseReader* CreateResponseReader( + const GURL& manifest_url, int64 group_id, int64 response_id) = 0; + + // Creates a writer to write a new response to storage. This call + // establishes a new response id. + virtual AppCacheResponseWriter* CreateResponseWriter( + const GURL& manifest_url, int64 group_id) = 0; + + // Schedules the lazy deletion of responses and saves the ids + // persistently such that the responses will be deleted upon restart + // if they aren't deleted prior to shutdown. + virtual void DoomResponses( + const GURL& manifest_url, const std::vector<int64>& response_ids) = 0; + + // Schedules the lazy deletion of responses without persistently saving + // the response ids. + virtual void DeleteResponses( + const GURL& manifest_url, const std::vector<int64>& response_ids) = 0; + + virtual void PurgeMemory() = 0; + + // Generates unique storage ids for different object types. + int64 NewCacheId() { + return ++last_cache_id_; + } + int64 NewGroupId() { + return ++last_group_id_; + } + + // The working set of object instances currently in memory. + AppCacheWorkingSet* working_set() { return &working_set_; } + + // A map of origins to usage. + const UsageMap* usage_map() { return &usage_map_; } + + // Simple ptr back to the service object that owns us. + AppCacheService* service() { return service_; } + + protected: + friend class AppCacheQuotaClientTest; + friend class AppCacheResponseTest; + friend class AppCacheStorageTest; + + // Helper to call a collection of delegates. + #define FOR_EACH_DELEGATE(delegates, func_and_args) \ + do { \ + for (DelegateReferenceVector::iterator it = delegates.begin(); \ + it != delegates.end(); ++it) { \ + if (it->get()->delegate) \ + it->get()->delegate->func_and_args; \ + } \ + } while (0) + + // Helper used to manage multiple references to a 'delegate' and to + // allow all pending callbacks to that delegate to be easily cancelled. + struct DelegateReference : public base::RefCounted<DelegateReference> { + Delegate* delegate; + AppCacheStorage* storage; + + DelegateReference(Delegate* delegate, AppCacheStorage* storage); + + void CancelReference() { + storage->delegate_references_.erase(delegate); + storage = NULL; + delegate = NULL; + } + + private: + friend class base::RefCounted<DelegateReference>; + + virtual ~DelegateReference(); + }; + typedef std::map<Delegate*, DelegateReference*> DelegateReferenceMap; + typedef std::vector<scoped_refptr<DelegateReference> > + DelegateReferenceVector; + + // Helper used to manage an async LoadResponseInfo calls on behalf of + // multiple callers. + class ResponseInfoLoadTask { + public: + ResponseInfoLoadTask(const GURL& manifest_url, int64 group_id, + int64 response_id, AppCacheStorage* storage); + ~ResponseInfoLoadTask(); + + int64 response_id() const { return response_id_; } + const GURL& manifest_url() const { return manifest_url_; } + int64 group_id() const { return group_id_; } + + void AddDelegate(DelegateReference* delegate_reference) { + delegates_.push_back(delegate_reference); + } + + void StartIfNeeded(); + + private: + void OnReadComplete(int result); + + AppCacheStorage* storage_; + GURL manifest_url_; + int64 group_id_; + int64 response_id_; + scoped_ptr<AppCacheResponseReader> reader_; + DelegateReferenceVector delegates_; + scoped_refptr<HttpResponseInfoIOBuffer> info_buffer_; + }; + + typedef std::map<int64, ResponseInfoLoadTask*> PendingResponseInfoLoads; + + DelegateReference* GetDelegateReference(Delegate* delegate) { + DelegateReferenceMap::iterator iter = + delegate_references_.find(delegate); + if (iter != delegate_references_.end()) + return iter->second; + return NULL; + } + + DelegateReference* GetOrCreateDelegateReference(Delegate* delegate) { + DelegateReference* reference = GetDelegateReference(delegate); + if (reference) + return reference; + return new DelegateReference(delegate, this); + } + + ResponseInfoLoadTask* GetOrCreateResponseInfoLoadTask( + const GURL& manifest_url, int64 group_id, int64 response_id) { + PendingResponseInfoLoads::iterator iter = + pending_info_loads_.find(response_id); + if (iter != pending_info_loads_.end()) + return iter->second; + return new ResponseInfoLoadTask(manifest_url, group_id, response_id, this); + } + + // Should only be called when creating a new response writer. + int64 NewResponseId() { + return ++last_response_id_; + } + + // Helpers to query and notify the QuotaManager. + void UpdateUsageMapAndNotify(const GURL& origin, int64 new_usage); + void ClearUsageMapAndNotify(); + void NotifyStorageAccessed(const GURL& origin); + + // The last storage id used for different object types. + int64 last_cache_id_; + int64 last_group_id_; + int64 last_response_id_; + + UsageMap usage_map_; // maps origin to usage + AppCacheWorkingSet working_set_; + AppCacheService* service_; + DelegateReferenceMap delegate_references_; + PendingResponseInfoLoads pending_info_loads_; + + // The set of last ids must be retrieved from storage prior to being used. + static const int64 kUnitializedId; + + FRIEND_TEST_ALL_PREFIXES(AppCacheStorageTest, DelegateReferences); + FRIEND_TEST_ALL_PREFIXES(AppCacheStorageTest, UsageMap); + + DISALLOW_COPY_AND_ASSIGN(AppCacheStorage); +}; + +} // namespace appcache + +#endif // WEBKIT_BROWSER_APPCACHE_APPCACHE_STORAGE_H_ + |