Home | History | Annotate | Download | only in appcache
      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 CONTENT_BROWSER_APPCACHE_APPCACHE_H_
      6 #define CONTENT_BROWSER_APPCACHE_APPCACHE_H_
      7 
      8 #include <map>
      9 #include <set>
     10 #include <vector>
     11 
     12 #include "base/gtest_prod_util.h"
     13 #include "base/memory/ref_counted.h"
     14 #include "base/time/time.h"
     15 #include "content/browser/appcache/appcache_database.h"
     16 #include "content/browser/appcache/appcache_entry.h"
     17 #include "content/browser/appcache/appcache_manifest_parser.h"
     18 #include "content/common/content_export.h"
     19 #include "url/gurl.h"
     20 
     21 namespace net {
     22 class IOBuffer;
     23 }
     24 
     25 namespace content {
     26 FORWARD_DECLARE_TEST(AppCacheTest, InitializeWithManifest);
     27 FORWARD_DECLARE_TEST(AppCacheTest, ToFromDatabaseRecords);
     28 class AppCacheExecutableHandler;
     29 class AppCacheGroup;
     30 class AppCacheHost;
     31 class AppCacheStorage;
     32 class AppCacheTest;
     33 class AppCacheStorageImplTest;
     34 class AppCacheUpdateJobTest;
     35 
     36 // Set of cached resources for an application. A cache exists as long as a
     37 // host is associated with it, the cache is in an appcache group or the
     38 // cache is being created during an appcache upate.
     39 class CONTENT_EXPORT AppCache
     40     : public base::RefCounted<AppCache> {
     41  public:
     42   typedef std::map<GURL, AppCacheEntry> EntryMap;
     43   typedef std::set<AppCacheHost*> AppCacheHosts;
     44 
     45   AppCache(AppCacheStorage* storage, int64 cache_id);
     46 
     47   int64 cache_id() const { return cache_id_; }
     48 
     49   AppCacheGroup* owning_group() const { return owning_group_.get(); }
     50 
     51   bool is_complete() const { return is_complete_; }
     52   void set_complete(bool value) { is_complete_ = value; }
     53 
     54   // Adds a new entry. Entry must not already be in cache.
     55   void AddEntry(const GURL& url, const AppCacheEntry& entry);
     56 
     57   // Adds a new entry or modifies an existing entry by merging the types
     58   // of the new entry with the existing entry. Returns true if a new entry
     59   // is added, false if the flags are merged into an existing entry.
     60   bool AddOrModifyEntry(const GURL& url, const AppCacheEntry& entry);
     61 
     62   // Removes an entry from the EntryMap, the URL must be in the set.
     63   void RemoveEntry(const GURL& url);
     64 
     65   // Do not store or delete the returned ptr, they're owned by 'this'.
     66   AppCacheEntry* GetEntry(const GURL& url);
     67   const AppCacheEntry* GetEntryWithResponseId(int64 response_id) {
     68     return GetEntryAndUrlWithResponseId(response_id, NULL);
     69   }
     70   const AppCacheEntry* GetEntryAndUrlWithResponseId(
     71       int64 response_id, GURL* optional_url);
     72   const EntryMap& entries() const { return entries_; }
     73 
     74   // The AppCache owns the collection of executable handlers that have
     75   // been started for this instance. The getter looks up an existing
     76   // handler returning null if not found, the GetOrCreate method will
     77   // cons one up if not found.
     78   // Do not store the returned ptrs, they're owned by 'this'.
     79   AppCacheExecutableHandler* GetExecutableHandler(int64 response_id);
     80   AppCacheExecutableHandler* GetOrCreateExecutableHandler(
     81       int64 response_id, net::IOBuffer* handler_source);
     82 
     83   // Returns the URL of the resource used as entry for 'namespace_url'.
     84   GURL GetFallbackEntryUrl(const GURL& namespace_url) const {
     85     return GetNamespaceEntryUrl(fallback_namespaces_, namespace_url);
     86   }
     87   GURL GetInterceptEntryUrl(const GURL& namespace_url) const {
     88     return GetNamespaceEntryUrl(intercept_namespaces_, namespace_url);
     89   }
     90 
     91   AppCacheHosts& associated_hosts() { return associated_hosts_; }
     92 
     93   bool IsNewerThan(AppCache* cache) const {
     94     // TODO(michaeln): revisit, the system clock can be set
     95     // back in time which would confuse this logic.
     96     if (update_time_ > cache->update_time_)
     97       return true;
     98 
     99     // Tie breaker. Newer caches have a larger cache ID.
    100     if (update_time_ == cache->update_time_)
    101       return cache_id_ > cache->cache_id_;
    102 
    103     return false;
    104   }
    105 
    106   base::Time update_time() const { return update_time_; }
    107 
    108   int64 cache_size() const { return cache_size_; }
    109 
    110   void set_update_time(base::Time ticks) { update_time_ = ticks; }
    111 
    112   // Initializes the cache with information in the manifest.
    113   // Do not use the manifest after this call.
    114   void InitializeWithManifest(AppCacheManifest* manifest);
    115 
    116   // Initializes the cache with the information in the database records.
    117   void InitializeWithDatabaseRecords(
    118       const AppCacheDatabase::CacheRecord& cache_record,
    119       const std::vector<AppCacheDatabase::EntryRecord>& entries,
    120       const std::vector<AppCacheDatabase::NamespaceRecord>& intercepts,
    121       const std::vector<AppCacheDatabase::NamespaceRecord>& fallbacks,
    122       const std::vector<AppCacheDatabase::OnlineWhiteListRecord>& whitelists);
    123 
    124   // Returns the database records to be stored in the AppCacheDatabase
    125   // to represent this cache.
    126   void ToDatabaseRecords(
    127       const AppCacheGroup* group,
    128       AppCacheDatabase::CacheRecord* cache_record,
    129       std::vector<AppCacheDatabase::EntryRecord>* entries,
    130       std::vector<AppCacheDatabase::NamespaceRecord>* intercepts,
    131       std::vector<AppCacheDatabase::NamespaceRecord>* fallbacks,
    132       std::vector<AppCacheDatabase::OnlineWhiteListRecord>* whitelists);
    133 
    134   bool FindResponseForRequest(const GURL& url,
    135       AppCacheEntry* found_entry, GURL* found_intercept_namespace,
    136       AppCacheEntry* found_fallback_entry, GURL* found_fallback_namespace,
    137       bool* found_network_namespace);
    138 
    139   // Populates the 'infos' vector with an element per entry in the appcache.
    140   void ToResourceInfoVector(AppCacheResourceInfoVector* infos) const;
    141 
    142   static const AppCacheNamespace* FindNamespace(
    143       const AppCacheNamespaceVector& namespaces,
    144       const GURL& url);
    145 
    146  private:
    147   friend class AppCacheGroup;
    148   friend class AppCacheHost;
    149   friend class content::AppCacheTest;
    150   friend class content::AppCacheStorageImplTest;
    151   friend class content::AppCacheUpdateJobTest;
    152   friend class base::RefCounted<AppCache>;
    153 
    154   ~AppCache();
    155 
    156   // Use AppCacheGroup::Add/RemoveCache() to manipulate owning group.
    157   void set_owning_group(AppCacheGroup* group) { owning_group_ = group; }
    158 
    159   // FindResponseForRequest helpers
    160   const AppCacheNamespace* FindInterceptNamespace(const GURL& url) {
    161     return FindNamespace(intercept_namespaces_, url);
    162   }
    163   const AppCacheNamespace* FindFallbackNamespace(const GURL& url) {
    164     return FindNamespace(fallback_namespaces_, url);
    165   }
    166   bool IsInNetworkNamespace(const GURL& url) {
    167     return FindNamespace(online_whitelist_namespaces_, url) != NULL;
    168   }
    169 
    170   GURL GetNamespaceEntryUrl(const AppCacheNamespaceVector& namespaces,
    171                             const GURL& namespace_url) const;
    172 
    173   // Use AppCacheHost::Associate*Cache() to manipulate host association.
    174   void AssociateHost(AppCacheHost* host) {
    175     associated_hosts_.insert(host);
    176   }
    177   void UnassociateHost(AppCacheHost* host);
    178 
    179   const int64 cache_id_;
    180   scoped_refptr<AppCacheGroup> owning_group_;
    181   AppCacheHosts associated_hosts_;
    182 
    183   EntryMap entries_;    // contains entries of all types
    184 
    185   AppCacheNamespaceVector intercept_namespaces_;
    186   AppCacheNamespaceVector fallback_namespaces_;
    187   AppCacheNamespaceVector online_whitelist_namespaces_;
    188   bool online_whitelist_all_;
    189 
    190   bool is_complete_;
    191 
    192   // when this cache was last updated
    193   base::Time update_time_;
    194 
    195   int64 cache_size_;
    196 
    197   typedef std::map<int64, AppCacheExecutableHandler*> HandlerMap;
    198   HandlerMap executable_handlers_;
    199 
    200   // to notify storage when cache is deleted
    201   AppCacheStorage* storage_;
    202 
    203   FRIEND_TEST_ALL_PREFIXES(content::AppCacheTest, InitializeWithManifest);
    204   FRIEND_TEST_ALL_PREFIXES(content::AppCacheTest, ToFromDatabaseRecords);
    205   DISALLOW_COPY_AND_ASSIGN(AppCache);
    206 };
    207 
    208 }  // namespace content
    209 
    210 #endif  // CONTENT_BROWSER_APPCACHE_APPCACHE_H_
    211