1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
|
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef WEBKIT_APPCACHE_APPCACHE_HOST_H_
#define WEBKIT_APPCACHE_APPCACHE_HOST_H_
#include "base/callback.h"
#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
#include "base/observer_list.h"
#include "googleurl/src/gurl.h"
#include "webkit/appcache/appcache_group.h"
#include "webkit/appcache/appcache_interfaces.h"
#include "webkit/appcache/appcache_service.h"
#include "webkit/appcache/appcache_storage.h"
#include "webkit/glue/resource_type.h"
namespace net {
class URLRequest;
} // namespace net
namespace appcache {
class AppCache;
class AppCacheFrontend;
class AppCacheRequestHandler;
typedef Callback2<Status, void*>::Type GetStatusCallback;
typedef Callback2<bool, void*>::Type StartUpdateCallback;
typedef Callback2<bool, void*>::Type SwapCacheCallback;
// Server-side representation of an application cache host.
class AppCacheHost : public AppCacheStorage::Delegate,
public AppCacheGroup::UpdateObserver {
public:
class Observer {
public:
// Called just after the cache selection algorithm completes.
virtual void OnCacheSelectionComplete(AppCacheHost* host) = 0;
// Called just prior to the instance being deleted.
virtual void OnDestructionImminent(AppCacheHost* host) = 0;
virtual ~Observer() {}
};
AppCacheHost(int host_id, AppCacheFrontend* frontend,
AppCacheService* service);
~AppCacheHost();
// Adds/removes an observer, the AppCacheHost does not take
// ownership of the observer.
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
// Support for cache selection and scriptable method calls.
void SelectCache(const GURL& document_url,
const int64 cache_document_was_loaded_from,
const GURL& manifest_url);
void SelectCacheForWorker(int parent_process_id,
int parent_host_id);
void SelectCacheForSharedWorker(int64 appcache_id);
void MarkAsForeignEntry(const GURL& document_url,
int64 cache_document_was_loaded_from);
void GetStatusWithCallback(GetStatusCallback* callback,
void* callback_param);
void StartUpdateWithCallback(StartUpdateCallback* callback,
void* callback_param);
void SwapCacheWithCallback(SwapCacheCallback* callback,
void* callback_param);
// Called prior to the main resource load. When the system contains multiple
// candidates for a main resource load, the appcache preferred by the host
// that created this host is used to break ties.
void SetSpawningHostId(int spawning_process_id, int spawning_host_id);
// May return NULL if the spawning host context has been closed, or if a
// spawning host context was never identified.
const AppCacheHost* GetSpawningHost() const;
const GURL& preferred_manifest_url() const {
return preferred_manifest_url_;
}
void set_preferred_manifest_url(const GURL& url) {
preferred_manifest_url_ = url;
}
// Support for loading resources out of the appcache.
// May return NULL if the request isn't subject to retrieval from an appache.
AppCacheRequestHandler* CreateRequestHandler(
net::URLRequest* request, ResourceType::Type resource_type);
// Support for devtools inspecting appcache resources.
void GetResourceList(std::vector<AppCacheResourceInfo>* resource_infos);
// Establishes an association between this host and a cache. 'cache' may be
// NULL to break any existing association. Associations are established
// either thru the cache selection algorithm implemented (in this class),
// or by the update algorithm (see AppCacheUpdateJob).
void AssociateCache(AppCache* cache);
// Adds a reference to the newest complete cache in a group, unless it's the
// same as the cache that is currently associated with the host.
void SetSwappableCache(AppCacheGroup* group);
// Used to ensure that a loaded appcache survives a frame navigation.
void LoadMainResourceCache(int64 cache_id);
// Used to notify the host that a fallback resource is being delivered as
// the main resource of the page and to provide its url.
void NotifyMainResourceFallback(const GURL& fallback_url);
// Used to notify the host that the main resource was blocked by a policy. To
// work properly, this method needs to by invoked prior to cache selection.
void NotifyMainResourceBlocked(const GURL& manifest_url);
// Used by the update job to keep track of which hosts are associated
// with which pending master entries.
const GURL& pending_master_entry_url() const {
return new_master_entry_url_;
}
int host_id() const { return host_id_; }
AppCacheService* service() const { return service_; }
AppCacheFrontend* frontend() const { return frontend_; }
AppCache* associated_cache() const { return associated_cache_.get(); }
bool is_selection_pending() const {
return pending_selected_cache_id_ != kNoCacheId ||
!pending_selected_manifest_url_.is_empty();
}
private:
Status GetStatus();
void LoadSelectedCache(int64 cache_id);
void LoadOrCreateGroup(const GURL& manifest_url);
// AppCacheStorage::Delegate impl
virtual void OnCacheLoaded(AppCache* cache, int64 cache_id);
virtual void OnGroupLoaded(AppCacheGroup* group,
const GURL& manifest_url);
void FinishCacheSelection(AppCache* cache, AppCacheGroup* group);
void DoPendingGetStatus();
void DoPendingStartUpdate();
void DoPendingSwapCache();
void ObserveGroupBeingUpdated(AppCacheGroup* group);
// AppCacheGroup::UpdateObserver methods.
virtual void OnContentBlocked(AppCacheGroup* group);
virtual void OnUpdateComplete(AppCacheGroup* group);
// Returns true if this host is for a dedicated worker context.
bool is_for_dedicated_worker() const {
return parent_host_id_ != kNoHostId;
}
// Returns the parent context's host instance. This is only valid
// to call when this instance is_for_dedicated_worker.
AppCacheHost* GetParentAppCacheHost() const;
// Identifies the corresponding appcache host in the child process.
int host_id_;
// Information about the host that created this one; the manifest
// preferred by our creator influences which cache our main resource
// should be loaded from.
int spawning_host_id_;
int spawning_process_id_;
GURL preferred_manifest_url_;
// Hosts for dedicated workers are special cased to shunt
// request handling off to the dedicated worker's parent.
// The scriptable api is not accessible in dedicated workers
// so the other aspects of this class are not relevant for
// these special case instances.
int parent_host_id_;
int parent_process_id_;
// The cache associated with this host, if any.
scoped_refptr<AppCache> associated_cache_;
// Hold a reference to the newest complete cache (if associated cache is
// not the newest) to keep the newest cache in existence while the app cache
// group is in use. The newest complete cache may have no associated hosts
// holding any references to it and would otherwise be deleted prematurely.
scoped_refptr<AppCache> swappable_cache_;
// Keep a reference to the group being updated until the update completes.
scoped_refptr<AppCacheGroup> group_being_updated_;
// Similarly, keep a reference to the newest cache of the group until the
// update completes. When adding a new master entry to a cache that is not
// in use in any other host, this reference keeps the cache in memory.
scoped_refptr<AppCache> newest_cache_of_group_being_updated_;
// Keep a reference to the cache of the main resource so it survives frame
// navigations.
scoped_refptr<AppCache> main_resource_cache_;
int64 pending_main_resource_cache_id_;
// Cache loading is async, if we're loading a specific cache or group
// for the purposes of cache selection, one or the other of these will
// indicate which cache or group is being loaded.
int64 pending_selected_cache_id_;
GURL pending_selected_manifest_url_;
// A new master entry to be added to the cache, may be empty.
GURL new_master_entry_url_;
// The frontend proxy to deliver notifications to the child process.
AppCacheFrontend* frontend_;
// Our central service object.
AppCacheService* service_;
// Since these are synchronous scriptable api calls in the client,
// there can only be one type of callback pending.
// Also, we have to wait until we have a cache selection prior
// to responding to these calls, as cache selection involves
// async loading of a cache or a group from storage.
GetStatusCallback* pending_get_status_callback_;
StartUpdateCallback* pending_start_update_callback_;
SwapCacheCallback* pending_swap_cache_callback_;
void* pending_callback_param_;
// True if a fallback resource was delivered as the main resource.
bool main_resource_was_fallback_;
GURL fallback_url_;
// True if requests for this host were blocked by a policy.
bool main_resource_blocked_;
GURL blocked_manifest_url_;
// Tells if info about associated cache is pending. Info is pending
// when update job has not returned success yet.
bool associated_cache_info_pending_;
// List of objects observing us.
ObserverList<Observer> observers_;
// Used to inform the QuotaManager of what origins are currently in use.
GURL origin_in_use_;
friend class AppCacheRequestHandlerTest;
friend class AppCacheUpdateJobTest;
FRIEND_TEST_ALL_PREFIXES(AppCacheTest, CleanupUnusedCache);
FRIEND_TEST_ALL_PREFIXES(AppCacheGroupTest, CleanupUnusedGroup);
FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, Basic);
FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, SelectNoCache);
FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, ForeignEntry);
FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, FailedCacheLoad);
FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, FailedGroupLoad);
FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, SetSwappableCache);
FRIEND_TEST_ALL_PREFIXES(AppCacheHostTest, ForDedicatedWorker);
FRIEND_TEST_ALL_PREFIXES(AppCacheGroupTest, QueueUpdate);
DISALLOW_COPY_AND_ASSIGN(AppCacheHost);
};
} // namespace appcache
#endif // WEBKIT_APPCACHE_APPCACHE_HOST_H_
|