Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(178)

Side by Side Diff: webkit/appcache/appcache_host.cc

Issue 192043: AppCacheHost cache selection algorithm (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « webkit/appcache/appcache_host.h ('k') | webkit/appcache/appcache_host_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "webkit/appcache/appcache_host.h" 5 #include "webkit/appcache/appcache_host.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "webkit/appcache/appcache.h" 8 #include "webkit/appcache/appcache.h"
9 #include "webkit/appcache/appcache_group.h" 9 #include "webkit/appcache/appcache_group.h"
10 #include "webkit/appcache/appcache_interfaces.h" 10 #include "webkit/appcache/appcache_interfaces.h"
11 #include "webkit/appcache/appcache_request_handler.h"
12 #include "webkit/appcache/appcache_service.h"
11 13
12 namespace appcache { 14 namespace appcache {
13 15
14 AppCacheHost::AppCacheHost(int host_id, AppCacheFrontend* frontend) 16 AppCacheHost::AppCacheHost(int host_id, AppCacheFrontend* frontend,
15 : host_id_(host_id), 17 AppCacheService* service)
16 selected_cache_(NULL), 18 : host_id_(host_id), pending_selected_cache_id_(kNoCacheId),
17 group_(NULL), 19 frontend_(frontend), service_(service),
18 frontend_(frontend) { 20 pending_get_status_callback_(NULL), pending_start_update_callback_(NULL),
21 pending_swap_cache_callback_(NULL), pending_callback_param_(NULL) {
19 } 22 }
20 23
21 AppCacheHost::~AppCacheHost() { 24 AppCacheHost::~AppCacheHost() {
22 if (selected_cache_) 25 if (associated_cache_.get())
23 set_selected_cache(NULL); 26 associated_cache_->UnassociateHost(this);
24 DCHECK(!group_); 27 service_->CancelLoads(this);
25 } 28 }
26 29
27 void AppCacheHost::set_selected_cache(AppCache *cache) { 30 void AppCacheHost::SelectCache(const GURL& document_url,
28 if (selected_cache_) 31 const int64 cache_document_was_loaded_from,
29 selected_cache_->UnassociateHost(this); 32 const GURL& manifest_url) {
30 33 DCHECK(!pending_start_update_callback_ &&
31 selected_cache_ = cache; 34 !pending_swap_cache_callback_ &&
35 !pending_get_status_callback_);
36
37 // First we handle an unusual case of SelectCache being called a second
38 // time. Generally this shouldn't happen, but with bad content I think
39 // this can occur... <html manifest=foo> <html manifest=bar></html></html>
40 // We handle this by killing whatever loading we have initiated, and by
41 // unassociating any hosts we currently have associated... and starting
42 // anew with the inputs to this SelectCache call.
43 // TODO(michaeln): at some point determine what behavior the algorithms
44 // described in the HTML5 draft produce and have our impl produce those
45 // results (or suggest changes to the algorihtms described in the spec
46 // if the resulting behavior is just too insane).
47 if (is_selection_pending()) {
48 service_->CancelLoads(this);
49 pending_selected_manifest_url_ = GURL::EmptyGURL();
50 pending_selected_cache_id_ = kNoCacheId;
51 } else if (associated_cache()) {
52 AssociateCache(NULL);
53 }
54 new_master_entry_url_ = GURL::EmptyGURL();
55
56 // 6.9.6 The application cache selection algorithm.
57 // The algorithm is started here and continues in FinishCacheSelection,
58 // after cache or group loading is complete.
59 // Note: foriegn entries are detected on the client side and
60 // MarkAsForeignEntry is called in that case, so that detection
61 // step is skipped here.
62
63 if (cache_document_was_loaded_from != kNoCacheId) {
64 LoadCache(cache_document_was_loaded_from);
65 return;
66 }
67
68 if (!manifest_url.is_empty() &&
69 (manifest_url.GetOrigin() == document_url.GetOrigin())) {
70 new_master_entry_url_ = document_url;
71 LoadOrCreateGroup(manifest_url);
72 return;
73 }
74
75 // TODO(michaeln): If there was a manifest URL, the user agent may report
76 // to the user that it was ignored, to aid in application development.
77 FinishCacheSelection(NULL, NULL);
78 }
79
80 void AppCacheHost::MarkAsForeignEntry(const GURL& document_url,
81 int64 cache_document_was_loaded_from) {
82 service_->MarkAsForeignEntry(document_url, cache_document_was_loaded_from);
83 SelectCache(document_url, kNoCacheId, GURL::EmptyGURL());
84 }
85
86 void AppCacheHost::GetStatusWithCallback(GetStatusCallback* callback,
87 void* callback_param) {
88 DCHECK(!pending_start_update_callback_ &&
89 !pending_swap_cache_callback_ &&
90 !pending_get_status_callback_);
91
92 pending_get_status_callback_ = callback;
93 pending_callback_param_ = callback_param;
94 if (is_selection_pending())
95 return;
96
97 DoPendingGetStatus();
98 }
99
100 void AppCacheHost::DoPendingGetStatus() {
101 DCHECK(pending_get_status_callback_);
102
103 pending_get_status_callback_->Run(
104 GetStatus(), pending_callback_param_);
105
106 pending_get_status_callback_ = NULL;
107 pending_callback_param_ = NULL;
108 }
109
110 void AppCacheHost::StartUpdateWithCallback(StartUpdateCallback* callback,
111 void* callback_param) {
112 DCHECK(!pending_start_update_callback_ &&
113 !pending_swap_cache_callback_ &&
114 !pending_get_status_callback_);
115
116 pending_start_update_callback_ = callback;
117 pending_callback_param_ = callback_param;
118 if (is_selection_pending())
119 return;
120
121 DoPendingStartUpdate();
122 }
123
124 void AppCacheHost::DoPendingStartUpdate() {
125 DCHECK(pending_start_update_callback_);
126
127 // TODO(michaeln): start an update if appropiate to do so
128 pending_start_update_callback_->Run(
129 false, pending_callback_param_);
130
131 pending_start_update_callback_ = NULL;
132 pending_callback_param_ = NULL;
133 }
134
135 void AppCacheHost::SwapCacheWithCallback(SwapCacheCallback* callback,
136 void* callback_param) {
137 DCHECK(!pending_start_update_callback_ &&
138 !pending_swap_cache_callback_ &&
139 !pending_get_status_callback_);
140
141 pending_swap_cache_callback_ = callback;
142 pending_callback_param_ = callback_param;
143 if (is_selection_pending())
144 return;
145
146 DoPendingSwapCache();
147 }
148
149 void AppCacheHost::DoPendingSwapCache() {
150 DCHECK(pending_swap_cache_callback_);
151
152 // TODO(michaeln): swap if we have a cache that can be swapped.
153 pending_swap_cache_callback_->Run(
154 false, pending_callback_param_);
155
156 pending_swap_cache_callback_ = NULL;
157 pending_callback_param_ = NULL;
158 }
159
160 AppCacheRequestHandler* AppCacheHost::CreateRequestHandler(
161 URLRequest* request,
162 bool is_main_request) {
163 if (is_main_request)
164 return new AppCacheRequestHandler(this);
165
166 if (associated_cache() && associated_cache()->is_complete())
167 return new AppCacheRequestHandler(associated_cache());
168
169 return NULL;
170 }
171
172 Status AppCacheHost::GetStatus() {
173 // TODO(michaeln): determine a real status value
174 Status status = associated_cache() ? IDLE : UNCACHED;
175 return status;
176 }
177
178 void AppCacheHost::LoadOrCreateGroup(const GURL& manifest_url) {
179 DCHECK(manifest_url.is_valid());
180 pending_selected_manifest_url_ = manifest_url;
181 service_->LoadOrCreateGroup(manifest_url, this);
182 }
183
184 void AppCacheHost::GroupLoadedCallback(
185 AppCacheGroup* group, const GURL& manifest_url) {
186 DCHECK(manifest_url == pending_selected_manifest_url_);
187 pending_selected_manifest_url_ = GURL::EmptyGURL();
188 FinishCacheSelection(NULL, group);
189 }
190
191 void AppCacheHost::LoadCache(int64 cache_id) {
192 DCHECK(cache_id != kNoCacheId);
193 pending_selected_cache_id_ = cache_id;
194 service_->LoadCache(cache_id, this);
195 }
196
197 void AppCacheHost::CacheLoadedCallback(AppCache* cache, int64 cache_id) {
198 DCHECK(cache_id == pending_selected_cache_id_);
199 pending_selected_cache_id_ = kNoCacheId;
200 if (cache)
201 FinishCacheSelection(cache, NULL);
202 else
203 FinishCacheSelection(NULL, NULL);
204 }
205
206 void AppCacheHost::FinishCacheSelection(
207 AppCache *cache, AppCacheGroup* group) {
208 DCHECK(!associated_cache());
209
210 // 6.9.6 The application cache selection algorithm
211 if (cache) {
212 // If document was loaded from an application cache, Associate document
213 // with the application cache from which it was loaded. Invoke the
214 // application cache update process for that cache and with the browsing
215 // context being navigated.
216 DCHECK(cache->owning_group());
217 DCHECK(new_master_entry_url_.is_empty());
218 AssociateCache(cache);
219 cache->owning_group()->StartUpdateWithHost(this);
220
221 } else if (group) {
222 // If document was loaded using HTTP GET or equivalent, and, there is a
223 // manifest URL, and manifest URL has the same origin as document.
224 // Invoke the application cache update process for manifest URL, with
225 // the browsing context being navigated, and with document and the
226 // resource from which document was loaded as the new master resourse.
227 DCHECK(new_master_entry_url_.is_valid());
228 AssociateCache(NULL); // The UpdateJob may produce one for us later.
229 group->StartUpdateWithNewMasterEntry(this, new_master_entry_url_);
230
231 } else {
232 // Otherwise, the Document is not associated with any application cache.
233 AssociateCache(NULL);
234 }
235
236 // Respond to pending callbacks now that we have a selection.
237 if (pending_get_status_callback_)
238 DoPendingGetStatus();
239 else if (pending_start_update_callback_)
240 DoPendingStartUpdate();
241 else if (pending_swap_cache_callback_)
242 DoPendingSwapCache();
243 }
244
245 void AppCacheHost::AssociateCache(AppCache* cache) {
246 if (associated_cache_.get()) {
247 associated_cache_->UnassociateHost(this);
248 group_ = NULL;
249 }
250
251 associated_cache_ = cache;
32 252
33 if (cache) { 253 if (cache) {
34 cache->AssociateHost(this); 254 cache->AssociateHost(this);
35 group_ = cache->owning_group(); 255 group_ = cache->owning_group();
256 frontend_->OnCacheSelected(host_id_, cache->cache_id(), GetStatus());
36 } else { 257 } else {
37 group_ = NULL; 258 frontend_->OnCacheSelected(host_id_, kNoCacheId, UNCACHED);
38 } 259 }
39 } 260 }
40 261
41 } // namespace appcache 262 } // namespace appcache
OLDNEW
« no previous file with comments | « webkit/appcache/appcache_host.h ('k') | webkit/appcache/appcache_host_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698