1 // Copyright (c) 2011 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_HOST_H_ 6 #define WEBKIT_BROWSER_APPCACHE_APPCACHE_HOST_H_ 7 8 #include "base/callback.h" 9 #include "base/gtest_prod_util.h" 10 #include "base/memory/ref_counted.h" 11 #include "base/observer_list.h" 12 #include "url/gurl.h" 13 #include "webkit/browser/appcache/appcache_group.h" 14 #include "webkit/browser/appcache/appcache_service_impl.h" 15 #include "webkit/browser/appcache/appcache_storage.h" 16 #include "webkit/browser/webkit_storage_browser_export.h" 17 #include "webkit/common/appcache/appcache_interfaces.h" 18 #include "webkit/common/resource_type.h" 19 20 namespace net { 21 class URLRequest; 22 } // namespace net 23 24 namespace content { 25 FORWARD_DECLARE_TEST(AppCacheGroupTest, CleanupUnusedGroup); 26 FORWARD_DECLARE_TEST(AppCacheGroupTest, QueueUpdate); 27 FORWARD_DECLARE_TEST(AppCacheHostTest, Basic); 28 FORWARD_DECLARE_TEST(AppCacheHostTest, SelectNoCache); 29 FORWARD_DECLARE_TEST(AppCacheHostTest, ForeignEntry); 30 FORWARD_DECLARE_TEST(AppCacheHostTest, FailedCacheLoad); 31 FORWARD_DECLARE_TEST(AppCacheHostTest, FailedGroupLoad); 32 FORWARD_DECLARE_TEST(AppCacheHostTest, SetSwappableCache); 33 FORWARD_DECLARE_TEST(AppCacheHostTest, ForDedicatedWorker); 34 FORWARD_DECLARE_TEST(AppCacheHostTest, SelectCacheAllowed); 35 FORWARD_DECLARE_TEST(AppCacheHostTest, SelectCacheBlocked); 36 FORWARD_DECLARE_TEST(AppCacheTest, CleanupUnusedCache); 37 class AppCacheTest; 38 class AppCacheHostTest; 39 class AppCacheGroupTest; 40 class AppCacheStorageImplTest; 41 class AppCacheRequestHandlerTest; 42 class AppCacheUpdateJobTest; 43 } 44 45 namespace appcache { 46 47 class AppCache; 48 class AppCacheFrontend; 49 class AppCacheRequestHandler; 50 51 typedef base::Callback<void(AppCacheStatus, void*)> GetStatusCallback; 52 typedef base::Callback<void(bool, void*)> StartUpdateCallback; 53 typedef base::Callback<void(bool, void*)> SwapCacheCallback; 54 55 // Server-side representation of an application cache host. 56 class WEBKIT_STORAGE_BROWSER_EXPORT AppCacheHost 57 : public AppCacheStorage::Delegate, 58 public AppCacheGroup::UpdateObserver, 59 public AppCacheServiceImpl::Observer { 60 public: 61 62 class WEBKIT_STORAGE_BROWSER_EXPORT Observer { 63 public: 64 // Called just after the cache selection algorithm completes. 65 virtual void OnCacheSelectionComplete(AppCacheHost* host) = 0; 66 67 // Called just prior to the instance being deleted. 68 virtual void OnDestructionImminent(AppCacheHost* host) = 0; 69 ~Observer()70 virtual ~Observer() {} 71 }; 72 73 AppCacheHost(int host_id, AppCacheFrontend* frontend, 74 AppCacheServiceImpl* service); 75 virtual ~AppCacheHost(); 76 77 // Adds/removes an observer, the AppCacheHost does not take 78 // ownership of the observer. 79 void AddObserver(Observer* observer); 80 void RemoveObserver(Observer* observer); 81 82 // Support for cache selection and scriptable method calls. 83 void SelectCache(const GURL& document_url, 84 const int64 cache_document_was_loaded_from, 85 const GURL& manifest_url); 86 void SelectCacheForWorker(int parent_process_id, 87 int parent_host_id); 88 void SelectCacheForSharedWorker(int64 appcache_id); 89 void MarkAsForeignEntry(const GURL& document_url, 90 int64 cache_document_was_loaded_from); 91 void GetStatusWithCallback(const GetStatusCallback& callback, 92 void* callback_param); 93 void StartUpdateWithCallback(const StartUpdateCallback& callback, 94 void* callback_param); 95 void SwapCacheWithCallback(const SwapCacheCallback& callback, 96 void* callback_param); 97 98 // Called prior to the main resource load. When the system contains multiple 99 // candidates for a main resource load, the appcache preferred by the host 100 // that created this host is used to break ties. 101 void SetSpawningHostId(int spawning_process_id, int spawning_host_id); 102 103 // May return NULL if the spawning host context has been closed, or if a 104 // spawning host context was never identified. 105 const AppCacheHost* GetSpawningHost() const; 106 preferred_manifest_url()107 const GURL& preferred_manifest_url() const { 108 return preferred_manifest_url_; 109 } set_preferred_manifest_url(const GURL & url)110 void set_preferred_manifest_url(const GURL& url) { 111 preferred_manifest_url_ = url; 112 } 113 114 // Support for loading resources out of the appcache. 115 // May return NULL if the request isn't subject to retrieval from an appache. 116 AppCacheRequestHandler* CreateRequestHandler( 117 net::URLRequest* request, ResourceType::Type resource_type); 118 119 // Support for devtools inspecting appcache resources. 120 void GetResourceList(std::vector<AppCacheResourceInfo>* resource_infos); 121 122 // Breaks any existing association between this host and a cache. 123 // 'manifest_url' is sent to DevTools as the manifest url that could have 124 // been associated before or could be associated later with this host. 125 // Associations are broken either thru the cache selection algorithm 126 // implemented in this class, or by the update algorithm (see 127 // AppCacheUpdateJob). 128 void AssociateNoCache(const GURL& manifest_url); 129 130 // Establishes an association between this host and an incomplete cache. 131 // 'manifest_url' is manifest url of the cache group being updated. 132 // Associations with incomplete caches are established by the update algorithm 133 // (see AppCacheUpdateJob). 134 void AssociateIncompleteCache(AppCache* cache, const GURL& manifest_url); 135 136 // Establishes an association between this host and a complete cache. 137 // Associations with complete caches are established either thru the cache 138 // selection algorithm implemented (in this class), or by the update algorithm 139 // (see AppCacheUpdateJob). 140 void AssociateCompleteCache(AppCache* cache); 141 142 // Adds a reference to the newest complete cache in a group, unless it's the 143 // same as the cache that is currently associated with the host. 144 void SetSwappableCache(AppCacheGroup* group); 145 146 // Used to ensure that a loaded appcache survives a frame navigation. 147 void LoadMainResourceCache(int64 cache_id); 148 149 // Used to notify the host that a namespace resource is being delivered as 150 // the main resource of the page and to provide its url. 151 void NotifyMainResourceIsNamespaceEntry(const GURL& namespace_entry_url); 152 153 // Used to notify the host that the main resource was blocked by a policy. To 154 // work properly, this method needs to by invoked prior to cache selection. 155 void NotifyMainResourceBlocked(const GURL& manifest_url); 156 157 // Used by the update job to keep track of which hosts are associated 158 // with which pending master entries. pending_master_entry_url()159 const GURL& pending_master_entry_url() const { 160 return new_master_entry_url_; 161 } 162 host_id()163 int host_id() const { return host_id_; } service()164 AppCacheServiceImpl* service() const { return service_; } storage()165 AppCacheStorage* storage() const { return storage_; } frontend()166 AppCacheFrontend* frontend() const { return frontend_; } associated_cache()167 AppCache* associated_cache() const { return associated_cache_.get(); } 168 is_selection_pending()169 bool is_selection_pending() const { 170 return pending_selected_cache_id_ != kAppCacheNoCacheId || 171 !pending_selected_manifest_url_.is_empty(); 172 } 173 first_party_url()174 const GURL& first_party_url() const { return first_party_url_; } 175 176 // Methods to support cross site navigations. 177 void PrepareForTransfer(); 178 void CompleteTransfer(int host_id, AppCacheFrontend* frontend); 179 180 private: 181 friend class content::AppCacheHostTest; 182 friend class content::AppCacheStorageImplTest; 183 friend class content::AppCacheRequestHandlerTest; 184 friend class content::AppCacheUpdateJobTest; 185 186 AppCacheStatus GetStatus(); 187 void LoadSelectedCache(int64 cache_id); 188 void LoadOrCreateGroup(const GURL& manifest_url); 189 190 // See public Associate*Host() methods above. 191 void AssociateCacheHelper(AppCache* cache, const GURL& manifest_url); 192 193 // AppCacheStorage::Delegate impl 194 virtual void OnCacheLoaded(AppCache* cache, int64 cache_id) OVERRIDE; 195 virtual void OnGroupLoaded(AppCacheGroup* group, 196 const GURL& manifest_url) OVERRIDE; 197 // AppCacheServiceImpl::Observer impl 198 virtual void OnServiceReinitialized( 199 AppCacheStorageReference* old_storage_ref) OVERRIDE; 200 201 void FinishCacheSelection(AppCache* cache, AppCacheGroup* group); 202 void DoPendingGetStatus(); 203 void DoPendingStartUpdate(); 204 void DoPendingSwapCache(); 205 206 void ObserveGroupBeingUpdated(AppCacheGroup* group); 207 208 // AppCacheGroup::UpdateObserver methods. 209 virtual void OnUpdateComplete(AppCacheGroup* group) OVERRIDE; 210 211 // Returns true if this host is for a dedicated worker context. is_for_dedicated_worker()212 bool is_for_dedicated_worker() const { 213 return parent_host_id_ != kAppCacheNoHostId; 214 } 215 216 // Returns the parent context's host instance. This is only valid 217 // to call when this instance is_for_dedicated_worker. 218 AppCacheHost* GetParentAppCacheHost() const; 219 220 // Identifies the corresponding appcache host in the child process. 221 int host_id_; 222 223 // Information about the host that created this one; the manifest 224 // preferred by our creator influences which cache our main resource 225 // should be loaded from. 226 int spawning_host_id_; 227 int spawning_process_id_; 228 GURL preferred_manifest_url_; 229 230 // Hosts for dedicated workers are special cased to shunt 231 // request handling off to the dedicated worker's parent. 232 // The scriptable api is not accessible in dedicated workers 233 // so the other aspects of this class are not relevant for 234 // these special case instances. 235 int parent_host_id_; 236 int parent_process_id_; 237 238 // Defined prior to refs to AppCaches and Groups because destruction 239 // order matters, the disabled_storage_reference_ must outlive those 240 // objects. See additional comments for the storage_ member. 241 scoped_refptr<AppCacheStorageReference> disabled_storage_reference_; 242 243 // The cache associated with this host, if any. 244 scoped_refptr<AppCache> associated_cache_; 245 246 // Hold a reference to the newest complete cache (if associated cache is 247 // not the newest) to keep the newest cache in existence while the app cache 248 // group is in use. The newest complete cache may have no associated hosts 249 // holding any references to it and would otherwise be deleted prematurely. 250 scoped_refptr<AppCache> swappable_cache_; 251 252 // Keep a reference to the group being updated until the update completes. 253 scoped_refptr<AppCacheGroup> group_being_updated_; 254 255 // Similarly, keep a reference to the newest cache of the group until the 256 // update completes. When adding a new master entry to a cache that is not 257 // in use in any other host, this reference keeps the cache in memory. 258 scoped_refptr<AppCache> newest_cache_of_group_being_updated_; 259 260 // Keep a reference to the cache of the main resource so it survives frame 261 // navigations. 262 scoped_refptr<AppCache> main_resource_cache_; 263 int64 pending_main_resource_cache_id_; 264 265 // Cache loading is async, if we're loading a specific cache or group 266 // for the purposes of cache selection, one or the other of these will 267 // indicate which cache or group is being loaded. 268 int64 pending_selected_cache_id_; 269 GURL pending_selected_manifest_url_; 270 271 // A new master entry to be added to the cache, may be empty. 272 GURL new_master_entry_url_; 273 274 // The frontend proxy to deliver notifications to the child process. 275 AppCacheFrontend* frontend_; 276 277 // Our central service object. 278 AppCacheServiceImpl* service_; 279 280 // And the equally central storage object, with a twist. In some error 281 // conditions the storage object gets recreated and reinitialized. The 282 // disabled_storage_reference_ (defined earlier) allows for cleanup of an 283 // instance that got disabled after we had latched onto it. In normal 284 // circumstances, disabled_storage_reference_ is expected to be NULL. 285 // When non-NULL both storage_ and disabled_storage_reference_ refer to the 286 // same instance. 287 AppCacheStorage* storage_; 288 289 // Since these are synchronous scriptable API calls in the client, there can 290 // only be one type of callback pending. Also, we have to wait until we have a 291 // cache selection prior to responding to these calls, as cache selection 292 // involves async loading of a cache or a group from storage. 293 GetStatusCallback pending_get_status_callback_; 294 StartUpdateCallback pending_start_update_callback_; 295 SwapCacheCallback pending_swap_cache_callback_; 296 void* pending_callback_param_; 297 298 // True if an intercept or fallback namespace resource was 299 // delivered as the main resource. 300 bool main_resource_was_namespace_entry_; 301 GURL namespace_entry_url_; 302 303 // True if requests for this host were blocked by a policy. 304 bool main_resource_blocked_; 305 GURL blocked_manifest_url_; 306 307 // Tells if info about associated cache is pending. Info is pending 308 // when update job has not returned success yet. 309 bool associated_cache_info_pending_; 310 311 // List of objects observing us. 312 ObserverList<Observer> observers_; 313 314 // Used to inform the QuotaManager of what origins are currently in use. 315 GURL origin_in_use_; 316 317 // First party url to be used in policy checks. 318 GURL first_party_url_; 319 320 FRIEND_TEST_ALL_PREFIXES(content::AppCacheGroupTest, CleanupUnusedGroup); 321 FRIEND_TEST_ALL_PREFIXES(content::AppCacheGroupTest, QueueUpdate); 322 FRIEND_TEST_ALL_PREFIXES(content::AppCacheHostTest, Basic); 323 FRIEND_TEST_ALL_PREFIXES(content::AppCacheHostTest, SelectNoCache); 324 FRIEND_TEST_ALL_PREFIXES(content::AppCacheHostTest, ForeignEntry); 325 FRIEND_TEST_ALL_PREFIXES(content::AppCacheHostTest, FailedCacheLoad); 326 FRIEND_TEST_ALL_PREFIXES(content::AppCacheHostTest, FailedGroupLoad); 327 FRIEND_TEST_ALL_PREFIXES(content::AppCacheHostTest, SetSwappableCache); 328 FRIEND_TEST_ALL_PREFIXES(content::AppCacheHostTest, ForDedicatedWorker); 329 FRIEND_TEST_ALL_PREFIXES(content::AppCacheHostTest, SelectCacheAllowed); 330 FRIEND_TEST_ALL_PREFIXES(content::AppCacheHostTest, SelectCacheBlocked); 331 FRIEND_TEST_ALL_PREFIXES(content::AppCacheTest, CleanupUnusedCache); 332 333 DISALLOW_COPY_AND_ASSIGN(AppCacheHost); 334 }; 335 336 } // namespace appcache 337 338 #endif // WEBKIT_BROWSER_APPCACHE_APPCACHE_HOST_H_ 339