15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#ifndef WEBKIT_BROWSER_APPCACHE_APPCACHE_STORAGE_H_
6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#define WEBKIT_BROWSER_APPCACHE_APPCACHE_STORAGE_H_
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/gtest_prod_util.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/ref_counted.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/completion_callback.h"
17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "webkit/browser/appcache/appcache_working_set.h"
187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "webkit/browser/webkit_storage_browser_export.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class GURL;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace appcache {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AppCache;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AppCacheEntry;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AppCacheGroup;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AppCacheResponseReader;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AppCacheResponseWriter;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AppCacheService;
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct AppCacheInfoCollection;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct HttpResponseInfoIOBuffer;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)class WEBKIT_STORAGE_BROWSER_EXPORT AppCacheStorage {
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::map<GURL, int64> UsageMap;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  class WEBKIT_STORAGE_BROWSER_EXPORT Delegate {
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If retrieval fails, 'collection' will be NULL.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void OnAllInfo(AppCacheInfoCollection* collection) {}
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If a load fails the 'cache' will be NULL.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void OnCacheLoaded(AppCache* cache, int64 cache_id) {}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If a load fails the 'group' will be NULL.
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void OnGroupLoaded(
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AppCacheGroup* group, const GURL& manifest_url) {}
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If successfully stored 'success' will be true.
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void OnGroupAndNewestCacheStored(
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AppCacheGroup* group, AppCache* newest_cache, bool success,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bool would_exceed_quota) {}
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If the operation fails, success will be false.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void OnGroupMadeObsolete(AppCacheGroup* group, bool success) {}
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If a load fails the 'response_info' will be NULL.
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void OnResponseInfoLoaded(
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AppCacheResponseInfo* response_info, int64 response_id) {}
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If no response is found, entry.response_id() and
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // fallback_entry.response_id() will be kNoResponseId.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If the response is the entry for an intercept or fallback
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // namespace, the url of the namespece entry is returned.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If a response is found, the cache id and manifest url of the
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // containing cache and group are also returned.
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual void OnMainResponseFound(
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const GURL& url, const AppCacheEntry& entry,
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        const GURL& namespace_entry_url, const AppCacheEntry& fallback_entry,
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int64 cache_id, int64 group_id, const GURL& mainfest_url) {}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   protected:
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual ~Delegate() {}
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit AppCacheStorage(AppCacheService* service);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~AppCacheStorage();
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Schedules a task to retrieve basic info about all groups and caches
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // stored in the system. Upon completion the delegate will be called
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // with the results.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void GetAllInfo(Delegate* delegate) = 0;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Schedules a cache to be loaded from storage. Upon load completion
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the delegate will be called back. If the cache already resides in
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // memory, the delegate will be called back immediately without returning
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to the message loop. If the load fails, the delegate will be called
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // back with a NULL cache pointer.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void LoadCache(int64 id, Delegate* delegate) = 0;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Schedules a group and its newest cache, if any, to be loaded from storage.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Upon load completion the delegate will be called back. If the group
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and newest cache already reside in memory, the delegate will be called
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // back immediately without returning to the message loop. If the load fails,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the delegate will be called back with a NULL group pointer.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void LoadOrCreateGroup(
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& manifest_url, Delegate* delegate) = 0;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Schedules response info to be loaded from storage.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Upon load completion the delegate will be called back. If the data
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // already resides in memory, the delegate will be called back
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // immediately without returning to the message loop. If the load fails,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the delegate will be called back with a NULL pointer.
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void LoadResponseInfo(
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& manifest_url, int64 group_id, int64 response_id,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Delegate* delegate);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Schedules a group and its newest complete cache to be initially stored or
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // incrementally updated with new changes. Upon completion the delegate
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will be called back. A group without a newest cache cannot be stored.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It's a programming error to call this method without a newest cache. A
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // side effect of storing a new newest cache is the removal of the group's
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // old caches and responses from persistent storage (although they may still
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // linger in the in-memory working set until no longer needed). The new
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cache will be added as the group's newest complete cache only if storage
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // succeeds.
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void StoreGroupAndNewestCache(
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AppCacheGroup* group, AppCache* newest_cache, Delegate* delegate) = 0;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Schedules a query to identify a response for a main request. Upon
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // completion the delegate will be called back.
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void FindResponseForMainRequest(
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& url,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& preferred_manifest_url,
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Delegate* delegate) = 0;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Performs an immediate lookup of the in-memory cache to
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // identify a response for a sub resource request.
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void FindResponseForSubRequest(
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AppCache* cache, const GURL& url,
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AppCacheEntry* found_entry, AppCacheEntry* found_fallback_entry,
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool* found_network_namespace) = 0;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Immediately updates in-memory storage, if the cache is in memory,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and schedules a task to update persistent storage. If the cache is
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // already scheduled to be loaded, upon loading completion the entry
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will be marked. There is no delegate completion callback.
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void MarkEntryAsForeign(const GURL& entry_url, int64 cache_id) = 0;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Schedules a task to update persistent storage and doom the group and all
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // related caches and responses for deletion. Upon completion the in-memory
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // instance is marked as obsolete and the delegate callback is called.
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void MakeGroupObsolete(
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AppCacheGroup* group, Delegate* delegate) = 0;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cancels all pending callbacks for the delegate. The delegate callbacks
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will not be invoked after, however any scheduled operations will still
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // take place. The callbacks for subsequently scheduled operations are
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // unaffected.
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CancelDelegateCallbacks(Delegate* delegate) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DelegateReference* delegate_reference = GetDelegateReference(delegate);
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delegate_reference)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate_reference->CancelReference();
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates a reader to read a response from storage.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual AppCacheResponseReader* CreateResponseReader(
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& manifest_url, int64 group_id, int64 response_id) = 0;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates a writer to write a new response to storage. This call
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // establishes a new response id.
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual AppCacheResponseWriter* CreateResponseWriter(
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& manifest_url, int64 group_id) = 0;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Schedules the lazy deletion of responses and saves the ids
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // persistently such that the responses will be deleted upon restart
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // if they aren't deleted prior to shutdown.
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DoomResponses(
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& manifest_url, const std::vector<int64>& response_ids) = 0;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Schedules the lazy deletion of responses without persistently saving
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the response ids.
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void DeleteResponses(
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& manifest_url, const std::vector<int64>& response_ids) = 0;
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void PurgeMemory() = 0;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Generates unique storage ids for different object types.
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 NewCacheId() {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ++last_cache_id_;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 NewGroupId() {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ++last_group_id_;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The working set of object instances currently in memory.
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppCacheWorkingSet* working_set() { return &working_set_; }
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A map of origins to usage.
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const UsageMap* usage_map() { return &usage_map_; }
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Simple ptr back to the service object that owns us.
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppCacheService* service() { return service_; }
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class AppCacheQuotaClientTest;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class AppCacheResponseTest;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class AppCacheStorageTest;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Helper to call a collection of delegates.
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  #define FOR_EACH_DELEGATE(delegates, func_and_args)                \
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    do {                                                             \
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (DelegateReferenceVector::iterator it = delegates.begin(); \
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           it != delegates.end(); ++it) {                            \
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (it->get()->delegate)                                     \
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          it->get()->delegate->func_and_args;                        \
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }                                                              \
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } while (0)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Helper used to manage multiple references to a 'delegate' and to
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // allow all pending callbacks to that delegate to be easily cancelled.
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct DelegateReference : public base::RefCounted<DelegateReference> {
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Delegate* delegate;
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppCacheStorage* storage;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DelegateReference(Delegate* delegate, AppCacheStorage* storage);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void CancelReference() {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      storage->delegate_references_.erase(delegate);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      storage = NULL;
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate = NULL;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    friend class base::RefCounted<DelegateReference>;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    virtual ~DelegateReference();
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::map<Delegate*, DelegateReference*> DelegateReferenceMap;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::vector<scoped_refptr<DelegateReference> >
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DelegateReferenceVector;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Helper used to manage an async LoadResponseInfo calls on behalf of
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // multiple callers.
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  class ResponseInfoLoadTask {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   public:
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResponseInfoLoadTask(const GURL& manifest_url, int64 group_id,
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         int64 response_id, AppCacheStorage* storage);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ~ResponseInfoLoadTask();
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 response_id() const { return response_id_; }
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& manifest_url() const { return manifest_url_; }
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 group_id() const { return group_id_; }
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void AddDelegate(DelegateReference* delegate_reference) {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegates_.push_back(delegate_reference);
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void StartIfNeeded();
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)   private:
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void OnReadComplete(int result);
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AppCacheStorage* storage_;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GURL manifest_url_;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 group_id_;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 response_id_;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<AppCacheResponseReader> reader_;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DelegateReferenceVector delegates_;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<HttpResponseInfoIOBuffer> info_buffer_;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef std::map<int64, ResponseInfoLoadTask*> PendingResponseInfoLoads;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelegateReference* GetDelegateReference(Delegate* delegate) {
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DelegateReferenceMap::iterator iter =
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delegate_references_.find(delegate);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (iter != delegate_references_.end())
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return iter->second;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelegateReference* GetOrCreateDelegateReference(Delegate* delegate) {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DelegateReference* reference = GetDelegateReference(delegate);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (reference)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return reference;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new DelegateReference(delegate, this);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResponseInfoLoadTask* GetOrCreateResponseInfoLoadTask(
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const GURL& manifest_url, int64 group_id, int64 response_id) {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PendingResponseInfoLoads::iterator iter =
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pending_info_loads_.find(response_id);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (iter != pending_info_loads_.end())
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return iter->second;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return new ResponseInfoLoadTask(manifest_url, group_id, response_id, this);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Should only be called when creating a new response writer.
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 NewResponseId() {
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ++last_response_id_;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Helpers to query and notify the QuotaManager.
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void UpdateUsageMapAndNotify(const GURL& origin, int64 new_usage);
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ClearUsageMapAndNotify();
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void NotifyStorageAccessed(const GURL& origin);
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The last storage id used for different object types.
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 last_cache_id_;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 last_group_id_;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 last_response_id_;
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UsageMap usage_map_;  // maps origin to usage
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppCacheWorkingSet working_set_;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppCacheService* service_;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DelegateReferenceMap delegate_references_;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingResponseInfoLoads pending_info_loads_;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The set of last ids must be retrieved from storage prior to being used.
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int64 kUnitializedId;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(AppCacheStorageTest, DelegateReferences);
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FRIEND_TEST_ALL_PREFIXES(AppCacheStorageTest, UsageMap);
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(AppCacheStorage);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace appcache
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
321868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#endif  // WEBKIT_BROWSER_APPCACHE_APPCACHE_STORAGE_H_
322