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_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"
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
);
38 class AppCacheHostTest
;
39 class AppCacheGroupTest
;
40 class AppCacheStorageImplTest
;
41 class AppCacheRequestHandlerTest
;
42 class AppCacheUpdateJobTest
;
48 class AppCacheFrontend
;
49 class AppCacheRequestHandler
;
51 typedef base::Callback
<void(AppCacheStatus
, void*)> GetStatusCallback
;
52 typedef base::Callback
<void(bool, void*)> StartUpdateCallback
;
53 typedef base::Callback
<void(bool, void*)> SwapCacheCallback
;
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
{
62 class WEBKIT_STORAGE_BROWSER_EXPORT Observer
{
64 // Called just after the cache selection algorithm completes.
65 virtual void OnCacheSelectionComplete(AppCacheHost
* host
) = 0;
67 // Called just prior to the instance being deleted.
68 virtual void OnDestructionImminent(AppCacheHost
* host
) = 0;
70 virtual ~Observer() {}
73 AppCacheHost(int host_id
, AppCacheFrontend
* frontend
,
74 AppCacheServiceImpl
* service
);
75 virtual ~AppCacheHost();
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
);
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
,
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
);
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
);
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;
107 const GURL
& preferred_manifest_url() const {
108 return preferred_manifest_url_
;
110 void set_preferred_manifest_url(const GURL
& url
) {
111 preferred_manifest_url_
= url
;
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
);
119 // Support for devtools inspecting appcache resources.
120 void GetResourceList(std::vector
<AppCacheResourceInfo
>* resource_infos
);
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
);
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
);
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
);
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
);
146 // Used to ensure that a loaded appcache survives a frame navigation.
147 void LoadMainResourceCache(int64 cache_id
);
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
);
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
);
157 // Used by the update job to keep track of which hosts are associated
158 // with which pending master entries.
159 const GURL
& pending_master_entry_url() const {
160 return new_master_entry_url_
;
163 int host_id() const { return host_id_
; }
164 AppCacheServiceImpl
* service() const { return service_
; }
165 AppCacheStorage
* storage() const { return storage_
; }
166 AppCacheFrontend
* frontend() const { return frontend_
; }
167 AppCache
* associated_cache() const { return associated_cache_
.get(); }
169 bool is_selection_pending() const {
170 return pending_selected_cache_id_
!= kAppCacheNoCacheId
||
171 !pending_selected_manifest_url_
.is_empty();
174 const GURL
& first_party_url() const { return first_party_url_
; }
176 // Methods to support cross site navigations.
177 void PrepareForTransfer();
178 void CompleteTransfer(int host_id
, AppCacheFrontend
* frontend
);
181 friend class content::AppCacheHostTest
;
182 friend class content::AppCacheStorageImplTest
;
183 friend class content::AppCacheRequestHandlerTest
;
184 friend class content::AppCacheUpdateJobTest
;
186 AppCacheStatus
GetStatus();
187 void LoadSelectedCache(int64 cache_id
);
188 void LoadOrCreateGroup(const GURL
& manifest_url
);
190 // See public Associate*Host() methods above.
191 void AssociateCacheHelper(AppCache
* cache
, const GURL
& manifest_url
);
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
;
201 void FinishCacheSelection(AppCache
* cache
, AppCacheGroup
* group
);
202 void DoPendingGetStatus();
203 void DoPendingStartUpdate();
204 void DoPendingSwapCache();
206 void ObserveGroupBeingUpdated(AppCacheGroup
* group
);
208 // AppCacheGroup::UpdateObserver methods.
209 virtual void OnUpdateComplete(AppCacheGroup
* group
) OVERRIDE
;
211 // Returns true if this host is for a dedicated worker context.
212 bool is_for_dedicated_worker() const {
213 return parent_host_id_
!= kAppCacheNoHostId
;
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;
220 // Identifies the corresponding appcache host in the child process.
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_
;
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.
236 int parent_process_id_
;
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_
;
243 // The cache associated with this host, if any.
244 scoped_refptr
<AppCache
> associated_cache_
;
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_
;
252 // Keep a reference to the group being updated until the update completes.
253 scoped_refptr
<AppCacheGroup
> group_being_updated_
;
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_
;
260 // Keep a reference to the cache of the main resource so it survives frame
262 scoped_refptr
<AppCache
> main_resource_cache_
;
263 int64 pending_main_resource_cache_id_
;
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_
;
271 // A new master entry to be added to the cache, may be empty.
272 GURL new_master_entry_url_
;
274 // The frontend proxy to deliver notifications to the child process.
275 AppCacheFrontend
* frontend_
;
277 // Our central service object.
278 AppCacheServiceImpl
* service_
;
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
287 AppCacheStorage
* storage_
;
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_
;
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_
;
303 // True if requests for this host were blocked by a policy.
304 bool main_resource_blocked_
;
305 GURL blocked_manifest_url_
;
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_
;
311 // List of objects observing us.
312 ObserverList
<Observer
> observers_
;
314 // Used to inform the QuotaManager of what origins are currently in use.
317 // First party url to be used in policy checks.
318 GURL first_party_url_
;
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
);
333 DISALLOW_COPY_AND_ASSIGN(AppCacheHost
);
336 } // namespace appcache
338 #endif // WEBKIT_BROWSER_APPCACHE_APPCACHE_HOST_H_