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