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_APPCACHE_APPCACHE_HOST_H_
6 #define WEBKIT_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"
12 #include "googleurl/src/gurl.h"
13 #include "webkit/appcache/appcache_group.h"
14 #include "webkit/appcache/appcache_interfaces.h"
15 #include "webkit/appcache/appcache_service.h"
16 #include "webkit/appcache/appcache_storage.h"
17 #include "webkit/glue/resource_type.h"
18 #include "webkit/storage/webkit_storage_export.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_EXPORT AppCacheHost
36 : public AppCacheStorage::Delegate
,
37 public AppCacheGroup::UpdateObserver
{
40 class WEBKIT_STORAGE_EXPORT Observer
{
42 // Called just after the cache selection algorithm completes.
43 virtual void OnCacheSelectionComplete(AppCacheHost
* host
) = 0;
45 // Called just prior to the instance being deleted.
46 virtual void OnDestructionImminent(AppCacheHost
* host
) = 0;
48 virtual ~Observer() {}
51 AppCacheHost(int host_id
, AppCacheFrontend
* frontend
,
52 AppCacheService
* service
);
53 virtual ~AppCacheHost();
55 // Adds/removes an observer, the AppCacheHost does not take
56 // ownership of the observer.
57 void AddObserver(Observer
* observer
);
58 void RemoveObserver(Observer
* observer
);
60 // Support for cache selection and scriptable method calls.
61 void SelectCache(const GURL
& document_url
,
62 const int64 cache_document_was_loaded_from
,
63 const GURL
& manifest_url
);
64 void SelectCacheForWorker(int parent_process_id
,
66 void SelectCacheForSharedWorker(int64 appcache_id
);
67 void MarkAsForeignEntry(const GURL
& document_url
,
68 int64 cache_document_was_loaded_from
);
69 void GetStatusWithCallback(const GetStatusCallback
& callback
,
70 void* callback_param
);
71 void StartUpdateWithCallback(const StartUpdateCallback
& callback
,
72 void* callback_param
);
73 void SwapCacheWithCallback(const SwapCacheCallback
& callback
,
74 void* callback_param
);
76 // Called prior to the main resource load. When the system contains multiple
77 // candidates for a main resource load, the appcache preferred by the host
78 // that created this host is used to break ties.
79 void SetSpawningHostId(int spawning_process_id
, int spawning_host_id
);
81 // May return NULL if the spawning host context has been closed, or if a
82 // spawning host context was never identified.
83 const AppCacheHost
* GetSpawningHost() const;
85 const GURL
& preferred_manifest_url() const {
86 return preferred_manifest_url_
;
88 void set_preferred_manifest_url(const GURL
& url
) {
89 preferred_manifest_url_
= url
;
92 // Support for loading resources out of the appcache.
93 // May return NULL if the request isn't subject to retrieval from an appache.
94 AppCacheRequestHandler
* CreateRequestHandler(
95 net::URLRequest
* request
, ResourceType::Type resource_type
);
97 // Support for devtools inspecting appcache resources.
98 void GetResourceList(std::vector
<AppCacheResourceInfo
>* resource_infos
);
100 // Breaks any existing association between this host and a cache.
101 // 'manifest_url' is sent to DevTools as the manifest url that could have
102 // been associated before or could be associated later with this host.
103 // Associations are broken either thru the cache selection algorithm
104 // implemented in this class, or by the update algorithm (see
105 // AppCacheUpdateJob).
106 void AssociateNoCache(const GURL
& manifest_url
);
108 // Establishes an association between this host and an incomplete cache.
109 // 'manifest_url' is manifest url of the cache group being updated.
110 // Associations with incomplete caches are established by the update algorithm
111 // (see AppCacheUpdateJob).
112 void AssociateIncompleteCache(AppCache
* cache
, const GURL
& manifest_url
);
114 // Establishes an association between this host and a complete cache.
115 // Associations with complete caches are established either thru the cache
116 // selection algorithm implemented (in this class), or by the update algorithm
117 // (see AppCacheUpdateJob).
118 void AssociateCompleteCache(AppCache
* cache
);
120 // Adds a reference to the newest complete cache in a group, unless it's the
121 // same as the cache that is currently associated with the host.
122 void SetSwappableCache(AppCacheGroup
* group
);
124 // Used to ensure that a loaded appcache survives a frame navigation.
125 void LoadMainResourceCache(int64 cache_id
);
127 // Used to notify the host that a namespace resource is being delivered as
128 // the main resource of the page and to provide its url.
129 void NotifyMainResourceIsNamespaceEntry(const GURL
& namespace_entry_url
);
131 // Used to notify the host that the main resource was blocked by a policy. To
132 // work properly, this method needs to by invoked prior to cache selection.
133 void NotifyMainResourceBlocked(const GURL
& manifest_url
);
135 // Used by the update job to keep track of which hosts are associated
136 // with which pending master entries.
137 const GURL
& pending_master_entry_url() const {
138 return new_master_entry_url_
;
141 int host_id() const { return host_id_
; }
142 AppCacheService
* service() const { return service_
; }
143 AppCacheFrontend
* frontend() const { return frontend_
; }
144 AppCache
* associated_cache() const { return associated_cache_
.get(); }
146 bool is_selection_pending() const {
147 return pending_selected_cache_id_
!= kNoCacheId
||
148 !pending_selected_manifest_url_
.is_empty();
151 const GURL
& first_party_url() const { return first_party_url_
; }
155 void LoadSelectedCache(int64 cache_id
);
156 void LoadOrCreateGroup(const GURL
& manifest_url
);
158 // See public Associate*Host() methods above.
159 void AssociateCacheHelper(AppCache
* cache
, const GURL
& manifest_url
);
161 // AppCacheStorage::Delegate impl
162 virtual void OnCacheLoaded(AppCache
* cache
, int64 cache_id
) OVERRIDE
;
163 virtual void OnGroupLoaded(AppCacheGroup
* group
,
164 const GURL
& manifest_url
) OVERRIDE
;
166 void FinishCacheSelection(AppCache
* cache
, AppCacheGroup
* group
);
167 void DoPendingGetStatus();
168 void DoPendingStartUpdate();
169 void DoPendingSwapCache();
171 void ObserveGroupBeingUpdated(AppCacheGroup
* group
);
173 // AppCacheGroup::UpdateObserver methods.
174 virtual void OnUpdateComplete(AppCacheGroup
* group
) OVERRIDE
;
176 // Returns true if this host is for a dedicated worker context.
177 bool is_for_dedicated_worker() const {
178 return parent_host_id_
!= kNoHostId
;
181 // Returns the parent context's host instance. This is only valid
182 // to call when this instance is_for_dedicated_worker.
183 AppCacheHost
* GetParentAppCacheHost() const;
185 // Identifies the corresponding appcache host in the child process.
188 // Information about the host that created this one; the manifest
189 // preferred by our creator influences which cache our main resource
190 // should be loaded from.
191 int spawning_host_id_
;
192 int spawning_process_id_
;
193 GURL preferred_manifest_url_
;
195 // Hosts for dedicated workers are special cased to shunt
196 // request handling off to the dedicated worker's parent.
197 // The scriptable api is not accessible in dedicated workers
198 // so the other aspects of this class are not relevant for
199 // these special case instances.
201 int parent_process_id_
;
203 // The cache associated with this host, if any.
204 scoped_refptr
<AppCache
> associated_cache_
;
206 // Hold a reference to the newest complete cache (if associated cache is
207 // not the newest) to keep the newest cache in existence while the app cache
208 // group is in use. The newest complete cache may have no associated hosts
209 // holding any references to it and would otherwise be deleted prematurely.
210 scoped_refptr
<AppCache
> swappable_cache_
;
212 // Keep a reference to the group being updated until the update completes.
213 scoped_refptr
<AppCacheGroup
> group_being_updated_
;
215 // Similarly, keep a reference to the newest cache of the group until the
216 // update completes. When adding a new master entry to a cache that is not
217 // in use in any other host, this reference keeps the cache in memory.
218 scoped_refptr
<AppCache
> newest_cache_of_group_being_updated_
;
220 // Keep a reference to the cache of the main resource so it survives frame
222 scoped_refptr
<AppCache
> main_resource_cache_
;
223 int64 pending_main_resource_cache_id_
;
225 // Cache loading is async, if we're loading a specific cache or group
226 // for the purposes of cache selection, one or the other of these will
227 // indicate which cache or group is being loaded.
228 int64 pending_selected_cache_id_
;
229 GURL pending_selected_manifest_url_
;
231 // A new master entry to be added to the cache, may be empty.
232 GURL new_master_entry_url_
;
234 // The frontend proxy to deliver notifications to the child process.
235 AppCacheFrontend
* frontend_
;
237 // Our central service object.
238 AppCacheService
* service_
;
240 // Since these are synchronous scriptable API calls in the client, there can
241 // only be one type of callback pending. Also, we have to wait until we have a
242 // cache selection prior to responding to these calls, as cache selection
243 // involves async loading of a cache or a group from storage.
244 GetStatusCallback pending_get_status_callback_
;
245 StartUpdateCallback pending_start_update_callback_
;
246 SwapCacheCallback pending_swap_cache_callback_
;
247 void* pending_callback_param_
;
249 // True if an intercept or fallback namespace resource was
250 // delivered as the main resource.
251 bool main_resource_was_namespace_entry_
;
252 GURL namespace_entry_url_
;
254 // True if requests for this host were blocked by a policy.
255 bool main_resource_blocked_
;
256 GURL blocked_manifest_url_
;
258 // Tells if info about associated cache is pending. Info is pending
259 // when update job has not returned success yet.
260 bool associated_cache_info_pending_
;
262 // List of objects observing us.
263 ObserverList
<Observer
> observers_
;
265 // Used to inform the QuotaManager of what origins are currently in use.
268 // First party url to be used in policy checks.
269 GURL first_party_url_
;
271 friend class AppCacheRequestHandlerTest
;
272 friend class AppCacheUpdateJobTest
;
273 FRIEND_TEST_ALL_PREFIXES(AppCacheTest
, CleanupUnusedCache
);
274 FRIEND_TEST_ALL_PREFIXES(AppCacheGroupTest
, CleanupUnusedGroup
);
275 FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest
, Basic
);
276 FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest
, SelectNoCache
);
277 FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest
, ForeignEntry
);
278 FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest
, FailedCacheLoad
);
279 FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest
, FailedGroupLoad
);
280 FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest
, SetSwappableCache
);
281 FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest
, ForDedicatedWorker
);
282 FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest
, SelectCacheAllowed
);
283 FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest
, SelectCacheBlocked
);
284 FRIEND_TEST_ALL_PREFIXES(AppCacheGroupTest
, QueueUpdate
);
286 DISALLOW_COPY_AND_ASSIGN(AppCacheHost
);
289 } // namespace appcache
291 #endif // WEBKIT_APPCACHE_APPCACHE_HOST_H_