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.
5 #ifndef WEBKIT_BROWSER_APPCACHE_APPCACHE_HOST_H_
6 #define WEBKIT_BROWSER_APPCACHE_APPCACHE_HOST_H_
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"
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"
27 class AppCacheFrontend;
28 class AppCacheRequestHandler;
30 typedef base::Callback<void(Status, void*)> GetStatusCallback;
31 typedef base::Callback<void(bool, void*)> StartUpdateCallback;
32 typedef base::Callback<void(bool, void*)> SwapCacheCallback;
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 {
41 class WEBKIT_STORAGE_BROWSER_EXPORT Observer {
43 // Called just after the cache selection algorithm completes.
44 virtual void OnCacheSelectionComplete(AppCacheHost* host) = 0;
46 // Called just prior to the instance being deleted.
47 virtual void OnDestructionImminent(AppCacheHost* host) = 0;
49 virtual ~Observer() {}
52 AppCacheHost(int host_id, AppCacheFrontend* frontend,
53 AppCacheService* service);
54 virtual ~AppCacheHost();
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);
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,
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);
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);
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;
86 const GURL& preferred_manifest_url() const {
87 return preferred_manifest_url_;
89 void set_preferred_manifest_url(const GURL& url) {
90 preferred_manifest_url_ = url;
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);
98 // Support for devtools inspecting appcache resources.
99 void GetResourceList(std::vector<AppCacheResourceInfo>* resource_infos);
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);
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);
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);
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);
125 // Used to ensure that a loaded appcache survives a frame navigation.
126 void LoadMainResourceCache(int64 cache_id);
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);
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);
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_;
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(); }
148 bool is_selection_pending() const {
149 return pending_selected_cache_id_ != kNoCacheId ||
150 !pending_selected_manifest_url_.is_empty();
153 const GURL& first_party_url() const { return first_party_url_; }
157 void LoadSelectedCache(int64 cache_id);
158 void LoadOrCreateGroup(const GURL& manifest_url);
160 // See public Associate*Host() methods above.
161 void AssociateCacheHelper(AppCache* cache, const GURL& manifest_url);
163 // AppCacheStorage::Delegate impl
164 virtual void OnCacheLoaded(AppCache* cache, int64 cache_id) OVERRIDE;
165 virtual void OnGroupLoaded(AppCacheGroup* group,
166 const GURL& manifest_url) OVERRIDE;
167 // AppCacheService::Observer impl
168 virtual void OnServiceReinitialized(
169 AppCacheStorageReference* old_storage_ref) OVERRIDE;
171 void FinishCacheSelection(AppCache* cache, AppCacheGroup* group);
172 void DoPendingGetStatus();
173 void DoPendingStartUpdate();
174 void DoPendingSwapCache();
176 void ObserveGroupBeingUpdated(AppCacheGroup* group);
178 // AppCacheGroup::UpdateObserver methods.
179 virtual void OnUpdateComplete(AppCacheGroup* group) OVERRIDE;
181 // Returns true if this host is for a dedicated worker context.
182 bool is_for_dedicated_worker() const {
183 return parent_host_id_ != kNoHostId;
186 // Returns the parent context's host instance. This is only valid
187 // to call when this instance is_for_dedicated_worker.
188 AppCacheHost* GetParentAppCacheHost() const;
190 // Identifies the corresponding appcache host in the child process.
193 // Information about the host that created this one; the manifest
194 // preferred by our creator influences which cache our main resource
195 // should be loaded from.
196 int spawning_host_id_;
197 int spawning_process_id_;
198 GURL preferred_manifest_url_;
200 // Hosts for dedicated workers are special cased to shunt
201 // request handling off to the dedicated worker's parent.
202 // The scriptable api is not accessible in dedicated workers
203 // so the other aspects of this class are not relevant for
204 // these special case instances.
206 int parent_process_id_;
208 // Defined prior to refs to AppCaches and Groups because destruction
209 // order matters, the disabled_storage_reference_ must outlive those
210 // objects. See additional comments for the storage_ member.
211 scoped_refptr<AppCacheStorageReference> disabled_storage_reference_;
213 // The cache associated with this host, if any.
214 scoped_refptr<AppCache> associated_cache_;
216 // Hold a reference to the newest complete cache (if associated cache is
217 // not the newest) to keep the newest cache in existence while the app cache
218 // group is in use. The newest complete cache may have no associated hosts
219 // holding any references to it and would otherwise be deleted prematurely.
220 scoped_refptr<AppCache> swappable_cache_;
222 // Keep a reference to the group being updated until the update completes.
223 scoped_refptr<AppCacheGroup> group_being_updated_;
225 // Similarly, keep a reference to the newest cache of the group until the
226 // update completes. When adding a new master entry to a cache that is not
227 // in use in any other host, this reference keeps the cache in memory.
228 scoped_refptr<AppCache> newest_cache_of_group_being_updated_;
230 // Keep a reference to the cache of the main resource so it survives frame
232 scoped_refptr<AppCache> main_resource_cache_;
233 int64 pending_main_resource_cache_id_;
235 // Cache loading is async, if we're loading a specific cache or group
236 // for the purposes of cache selection, one or the other of these will
237 // indicate which cache or group is being loaded.
238 int64 pending_selected_cache_id_;
239 GURL pending_selected_manifest_url_;
241 // A new master entry to be added to the cache, may be empty.
242 GURL new_master_entry_url_;
244 // The frontend proxy to deliver notifications to the child process.
245 AppCacheFrontend* frontend_;
247 // Our central service object.
248 AppCacheService* service_;
250 // And the equally central storage object, with a twist. In some error
251 // conditions the storage object gets recreated and reinitialized. The
252 // disabled_storage_reference_ (defined earlier) allows for cleanup of an
253 // instance that got disabled after we had latched onto it. In normal
254 // circumstances, disabled_storage_reference_ is expected to be NULL.
255 // When non-NULL both storage_ and disabled_storage_reference_ refer to the
257 AppCacheStorage* storage_;
259 // Since these are synchronous scriptable API calls in the client, there can
260 // only be one type of callback pending. Also, we have to wait until we have a
261 // cache selection prior to responding to these calls, as cache selection
262 // involves async loading of a cache or a group from storage.
263 GetStatusCallback pending_get_status_callback_;
264 StartUpdateCallback pending_start_update_callback_;
265 SwapCacheCallback pending_swap_cache_callback_;
266 void* pending_callback_param_;
268 // True if an intercept or fallback namespace resource was
269 // delivered as the main resource.
270 bool main_resource_was_namespace_entry_;
271 GURL namespace_entry_url_;
273 // True if requests for this host were blocked by a policy.
274 bool main_resource_blocked_;
275 GURL blocked_manifest_url_;
277 // Tells if info about associated cache is pending. Info is pending
278 // when update job has not returned success yet.
279 bool associated_cache_info_pending_;
281 // List of objects observing us.
282 ObserverList<Observer> observers_;
284 // Used to inform the QuotaManager of what origins are currently in use.
287 // First party url to be used in policy checks.
288 GURL first_party_url_;
290 friend class AppCacheStorageImplTest;
291 friend class AppCacheRequestHandlerTest;
292 friend class AppCacheUpdateJobTest;
293 FRIEND_TEST_ALL_PREFIXES(AppCacheTest, CleanupUnusedCache);
294 FRIEND_TEST_ALL_PREFIXES(AppCacheGroupTest, CleanupUnusedGroup);
295 FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, Basic);
296 FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, SelectNoCache);
297 FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, ForeignEntry);
298 FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, FailedCacheLoad);
299 FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, FailedGroupLoad);
300 FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, SetSwappableCache);
301 FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, ForDedicatedWorker);
302 FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, SelectCacheAllowed);
303 FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, SelectCacheBlocked);
304 FRIEND_TEST_ALL_PREFIXES(AppCacheGroupTest, QueueUpdate);
306 DISALLOW_COPY_AND_ASSIGN(AppCacheHost);
309 } // namespace appcache
311 #endif // WEBKIT_BROWSER_APPCACHE_APPCACHE_HOST_H_