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