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