Update V8 to version 4.6.61.
[chromium-blink-merge.git] / content / child / appcache / web_application_cache_host_impl.cc
blob7be7ee45b07c898b105ee16b9c72cd13ec4352ad
1 // Copyright 2013 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 #include "content/child/appcache/web_application_cache_host_impl.h"
7 #include "base/compiler_specific.h"
8 #include "base/id_map.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/stringprintf.h"
11 #include "third_party/WebKit/public/platform/WebString.h"
12 #include "third_party/WebKit/public/platform/WebURL.h"
13 #include "third_party/WebKit/public/platform/WebURLRequest.h"
14 #include "third_party/WebKit/public/platform/WebURLResponse.h"
16 using blink::WebApplicationCacheHost;
17 using blink::WebApplicationCacheHostClient;
18 using blink::WebString;
19 using blink::WebURLRequest;
20 using blink::WebURL;
21 using blink::WebURLResponse;
22 using blink::WebVector;
24 namespace content {
26 namespace {
28 // Note: the order of the elements in this array must match those
29 // of the EventID enum in appcache_interfaces.h.
30 const char* kEventNames[] = {
31 "Checking", "Error", "NoUpdate", "Downloading", "Progress",
32 "UpdateReady", "Cached", "Obsolete"
35 typedef IDMap<WebApplicationCacheHostImpl> HostsMap;
37 HostsMap* all_hosts() {
38 static HostsMap* map = new HostsMap;
39 return map;
42 GURL ClearUrlRef(const GURL& url) {
43 if (!url.has_ref())
44 return url;
45 GURL::Replacements replacements;
46 replacements.ClearRef();
47 return url.ReplaceComponents(replacements);
50 } // anon namespace
52 WebApplicationCacheHostImpl* WebApplicationCacheHostImpl::FromId(int id) {
53 return all_hosts()->Lookup(id);
56 WebApplicationCacheHostImpl::WebApplicationCacheHostImpl(
57 WebApplicationCacheHostClient* client,
58 AppCacheBackend* backend)
59 : client_(client),
60 backend_(backend),
61 host_id_(all_hosts()->Add(this)),
62 status_(APPCACHE_STATUS_UNCACHED),
63 is_scheme_supported_(false),
64 is_get_method_(false),
65 is_new_master_entry_(MAYBE),
66 was_select_cache_called_(false) {
67 DCHECK(client && backend && (host_id_ != kAppCacheNoHostId));
69 backend_->RegisterHost(host_id_);
72 WebApplicationCacheHostImpl::~WebApplicationCacheHostImpl() {
73 backend_->UnregisterHost(host_id_);
74 all_hosts()->Remove(host_id_);
77 void WebApplicationCacheHostImpl::OnCacheSelected(
78 const AppCacheInfo& info) {
79 cache_info_ = info;
80 client_->didChangeCacheAssociation();
83 void WebApplicationCacheHostImpl::OnStatusChanged(
84 AppCacheStatus status) {
85 // TODO(michaeln): delete me, not used
88 void WebApplicationCacheHostImpl::OnEventRaised(
89 AppCacheEventID event_id) {
90 DCHECK(event_id !=
91 APPCACHE_PROGRESS_EVENT); // See OnProgressEventRaised.
92 DCHECK(event_id != APPCACHE_ERROR_EVENT); // See OnErrorEventRaised.
94 // Emit logging output prior to calling out to script as we can get
95 // deleted within the script event handler.
96 const char* kFormatString = "Application Cache %s event";
97 std::string message = base::StringPrintf(kFormatString,
98 kEventNames[event_id]);
99 OnLogMessage(APPCACHE_LOG_INFO, message);
101 switch (event_id) {
102 case APPCACHE_CHECKING_EVENT:
103 status_ = APPCACHE_STATUS_CHECKING;
104 break;
105 case APPCACHE_DOWNLOADING_EVENT:
106 status_ = APPCACHE_STATUS_DOWNLOADING;
107 break;
108 case APPCACHE_UPDATE_READY_EVENT:
109 status_ = APPCACHE_STATUS_UPDATE_READY;
110 break;
111 case APPCACHE_CACHED_EVENT:
112 case APPCACHE_NO_UPDATE_EVENT:
113 status_ = APPCACHE_STATUS_IDLE;
114 break;
115 case APPCACHE_OBSOLETE_EVENT:
116 status_ = APPCACHE_STATUS_OBSOLETE;
117 break;
118 default:
119 NOTREACHED();
120 break;
123 client_->notifyEventListener(static_cast<EventID>(event_id));
126 void WebApplicationCacheHostImpl::OnProgressEventRaised(
127 const GURL& url, int num_total, int num_complete) {
128 // Emit logging output prior to calling out to script as we can get
129 // deleted within the script event handler.
130 const char* kFormatString = "Application Cache Progress event (%d of %d) %s";
131 std::string message = base::StringPrintf(kFormatString, num_complete,
132 num_total, url.spec().c_str());
133 OnLogMessage(APPCACHE_LOG_INFO, message);
134 status_ = APPCACHE_STATUS_DOWNLOADING;
135 client_->notifyProgressEventListener(url, num_total, num_complete);
138 void WebApplicationCacheHostImpl::OnErrorEventRaised(
139 const AppCacheErrorDetails& details) {
140 // Emit logging output prior to calling out to script as we can get
141 // deleted within the script event handler.
142 const char* kFormatString = "Application Cache Error event: %s";
143 std::string full_message =
144 base::StringPrintf(kFormatString, details.message.c_str());
145 OnLogMessage(APPCACHE_LOG_ERROR, full_message);
147 status_ = cache_info_.is_complete ? APPCACHE_STATUS_IDLE :
148 APPCACHE_STATUS_UNCACHED;
149 if (details.is_cross_origin) {
150 // Don't leak detailed information to script for cross-origin resources.
151 DCHECK_EQ(APPCACHE_RESOURCE_ERROR, details.reason);
152 client_->notifyErrorEventListener(
153 static_cast<ErrorReason>(details.reason), details.url, 0, WebString());
154 } else {
155 client_->notifyErrorEventListener(static_cast<ErrorReason>(details.reason),
156 details.url,
157 details.status,
158 WebString::fromUTF8(details.message));
162 void WebApplicationCacheHostImpl::willStartMainResourceRequest(
163 WebURLRequest& request, const WebApplicationCacheHost* spawning_host) {
164 request.setAppCacheHostID(host_id_);
166 original_main_resource_url_ = ClearUrlRef(request.url());
168 std::string method = request.httpMethod().utf8();
169 is_get_method_ = (method == kHttpGETMethod);
170 DCHECK(method == base::ToUpperASCII(method));
172 const WebApplicationCacheHostImpl* spawning_host_impl =
173 static_cast<const WebApplicationCacheHostImpl*>(spawning_host);
174 if (spawning_host_impl && (spawning_host_impl != this) &&
175 (spawning_host_impl->status_ != APPCACHE_STATUS_UNCACHED)) {
176 backend_->SetSpawningHostId(host_id_, spawning_host_impl->host_id());
180 void WebApplicationCacheHostImpl::willStartSubResourceRequest(
181 WebURLRequest& request) {
182 request.setAppCacheHostID(host_id_);
185 void WebApplicationCacheHostImpl::selectCacheWithoutManifest() {
186 if (was_select_cache_called_)
187 return;
188 was_select_cache_called_ = true;
190 status_ = (document_response_.appCacheID() == kAppCacheNoCacheId) ?
191 APPCACHE_STATUS_UNCACHED : APPCACHE_STATUS_CHECKING;
192 is_new_master_entry_ = NO;
193 backend_->SelectCache(host_id_, document_url_,
194 document_response_.appCacheID(),
195 GURL());
198 bool WebApplicationCacheHostImpl::selectCacheWithManifest(
199 const WebURL& manifest_url) {
200 if (was_select_cache_called_)
201 return true;
202 was_select_cache_called_ = true;
204 GURL manifest_gurl(ClearUrlRef(manifest_url));
206 // 6.9.6 The application cache selection algorithm
207 // Check for new 'master' entries.
208 if (document_response_.appCacheID() == kAppCacheNoCacheId) {
209 if (is_scheme_supported_ && is_get_method_ &&
210 (manifest_gurl.GetOrigin() == document_url_.GetOrigin())) {
211 status_ = APPCACHE_STATUS_CHECKING;
212 is_new_master_entry_ = YES;
213 } else {
214 status_ = APPCACHE_STATUS_UNCACHED;
215 is_new_master_entry_ = NO;
216 manifest_gurl = GURL();
218 backend_->SelectCache(
219 host_id_, document_url_, kAppCacheNoCacheId, manifest_gurl);
220 return true;
223 DCHECK_EQ(NO, is_new_master_entry_);
225 // 6.9.6 The application cache selection algorithm
226 // Check for 'foreign' entries.
227 GURL document_manifest_gurl(document_response_.appCacheManifestURL());
228 if (document_manifest_gurl != manifest_gurl) {
229 backend_->MarkAsForeignEntry(host_id_, document_url_,
230 document_response_.appCacheID());
231 status_ = APPCACHE_STATUS_UNCACHED;
232 return false; // the navigation will be restarted
235 status_ = APPCACHE_STATUS_CHECKING;
237 // Its a 'master' entry thats already in the cache.
238 backend_->SelectCache(host_id_, document_url_,
239 document_response_.appCacheID(),
240 manifest_gurl);
241 return true;
244 void WebApplicationCacheHostImpl::didReceiveResponseForMainResource(
245 const WebURLResponse& response) {
246 document_response_ = response;
247 document_url_ = ClearUrlRef(document_response_.url());
248 if (document_url_ != original_main_resource_url_)
249 is_get_method_ = true; // A redirect was involved.
250 original_main_resource_url_ = GURL();
252 is_scheme_supported_ = IsSchemeSupportedForAppCache(document_url_);
253 if ((document_response_.appCacheID() != kAppCacheNoCacheId) ||
254 !is_scheme_supported_ || !is_get_method_)
255 is_new_master_entry_ = NO;
258 void WebApplicationCacheHostImpl::didReceiveDataForMainResource(
259 const char* data, unsigned len) {
260 if (is_new_master_entry_ == NO)
261 return;
262 // TODO(michaeln): write me
265 void WebApplicationCacheHostImpl::didFinishLoadingMainResource(bool success) {
266 if (is_new_master_entry_ == NO)
267 return;
268 // TODO(michaeln): write me
271 WebApplicationCacheHost::Status WebApplicationCacheHostImpl::status() {
272 return static_cast<WebApplicationCacheHost::Status>(status_);
275 bool WebApplicationCacheHostImpl::startUpdate() {
276 if (!backend_->StartUpdate(host_id_))
277 return false;
278 if (status_ == APPCACHE_STATUS_IDLE ||
279 status_ == APPCACHE_STATUS_UPDATE_READY)
280 status_ = APPCACHE_STATUS_CHECKING;
281 else
282 status_ = backend_->GetStatus(host_id_);
283 return true;
286 bool WebApplicationCacheHostImpl::swapCache() {
287 if (!backend_->SwapCache(host_id_))
288 return false;
289 status_ = backend_->GetStatus(host_id_);
290 return true;
293 void WebApplicationCacheHostImpl::getAssociatedCacheInfo(
294 WebApplicationCacheHost::CacheInfo* info) {
295 info->manifestURL = cache_info_.manifest_url;
296 if (!cache_info_.is_complete)
297 return;
298 info->creationTime = cache_info_.creation_time.ToDoubleT();
299 info->updateTime = cache_info_.last_update_time.ToDoubleT();
300 info->totalSize = cache_info_.size;
303 void WebApplicationCacheHostImpl::getResourceList(
304 WebVector<ResourceInfo>* resources) {
305 if (!cache_info_.is_complete)
306 return;
307 std::vector<AppCacheResourceInfo> resource_infos;
308 backend_->GetResourceList(host_id_, &resource_infos);
310 WebVector<ResourceInfo> web_resources(resource_infos.size());
311 for (size_t i = 0; i < resource_infos.size(); ++i) {
312 web_resources[i].size = resource_infos[i].size;
313 web_resources[i].isMaster = resource_infos[i].is_master;
314 web_resources[i].isExplicit = resource_infos[i].is_explicit;
315 web_resources[i].isManifest = resource_infos[i].is_manifest;
316 web_resources[i].isForeign = resource_infos[i].is_foreign;
317 web_resources[i].isFallback = resource_infos[i].is_fallback;
318 web_resources[i].url = resource_infos[i].url;
320 resources->swap(web_resources);
323 } // namespace content