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