summaryrefslogtreecommitdiffstats
path: root/WebCore/loader/appcache/ApplicationCacheGroup.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/loader/appcache/ApplicationCacheGroup.cpp')
-rw-r--r--WebCore/loader/appcache/ApplicationCacheGroup.cpp136
1 files changed, 92 insertions, 44 deletions
diff --git a/WebCore/loader/appcache/ApplicationCacheGroup.cpp b/WebCore/loader/appcache/ApplicationCacheGroup.cpp
index 2367e79..1b16b50 100644
--- a/WebCore/loader/appcache/ApplicationCacheGroup.cpp
+++ b/WebCore/loader/appcache/ApplicationCacheGroup.cpp
@@ -154,7 +154,14 @@ void ApplicationCacheGroup::selectCache(Frame* frame, const KURL& manifestURL)
// Check that the resource URL has the same scheme/host/port as the manifest URL.
if (!protocolHostAndPortAreEqual(manifestURL, request.url()))
return;
-
+
+ // Don't change anything on disk if private browsing is enabled.
+ if (!frame->settings() || frame->settings()->privateBrowsingEnabled()) {
+ postListenerTask(&DOMApplicationCache::callCheckingListener, documentLoader);
+ postListenerTask(&DOMApplicationCache::callErrorListener, documentLoader);
+ return;
+ }
+
ApplicationCacheGroup* group = cacheStorage().findOrCreateCacheGroup(manifestURL);
documentLoader->setCandidateApplicationCacheGroup(group);
@@ -184,7 +191,7 @@ void ApplicationCacheGroup::finishedLoadingMainResource(DocumentLoader* loader)
{
ASSERT(m_pendingMasterResourceLoaders.contains(loader));
ASSERT(m_completionType == None || m_pendingEntries.isEmpty());
- const KURL& url = loader->originalURL();
+ const KURL& url = loader->url();
switch (m_completionType) {
case None:
@@ -195,12 +202,12 @@ void ApplicationCacheGroup::finishedLoadingMainResource(DocumentLoader* loader)
associateDocumentLoaderWithCache(loader, m_newestCache.get());
if (ApplicationCacheResource* resource = m_newestCache->resourceForURL(url)) {
- if (!(resource->type() & ApplicationCacheResource::Implicit)) {
- resource->addType(ApplicationCacheResource::Implicit);
+ if (!(resource->type() & ApplicationCacheResource::Master)) {
+ resource->addType(ApplicationCacheResource::Master);
ASSERT(!resource->storageID());
}
} else
- m_newestCache->addResource(ApplicationCacheResource::create(url, loader->response(), ApplicationCacheResource::Implicit, loader->mainResourceData()));
+ m_newestCache->addResource(ApplicationCacheResource::create(url, loader->response(), ApplicationCacheResource::Master, loader->mainResourceData()));
break;
case Failure:
@@ -215,12 +222,12 @@ void ApplicationCacheGroup::finishedLoadingMainResource(DocumentLoader* loader)
ASSERT(m_associatedDocumentLoaders.contains(loader));
if (ApplicationCacheResource* resource = m_cacheBeingUpdated->resourceForURL(url)) {
- if (!(resource->type() & ApplicationCacheResource::Implicit)) {
- resource->addType(ApplicationCacheResource::Implicit);
+ if (!(resource->type() & ApplicationCacheResource::Master)) {
+ resource->addType(ApplicationCacheResource::Master);
ASSERT(!resource->storageID());
}
} else
- m_cacheBeingUpdated->addResource(ApplicationCacheResource::create(url, loader->response(), ApplicationCacheResource::Implicit, loader->mainResourceData()));
+ m_cacheBeingUpdated->addResource(ApplicationCacheResource::create(url, loader->response(), ApplicationCacheResource::Master, loader->mainResourceData()));
// The "cached" event will be posted to all associated documents once update is complete.
break;
}
@@ -369,6 +376,16 @@ void ApplicationCacheGroup::update(Frame* frame, ApplicationCacheUpdateOption up
return;
}
+ // Don't change anything on disk if private browsing is enabled.
+ if (!frame->settings() || frame->settings()->privateBrowsingEnabled()) {
+ ASSERT(m_pendingMasterResourceLoaders.isEmpty());
+ ASSERT(m_pendingEntries.isEmpty());
+ ASSERT(!m_cacheBeingUpdated);
+ postListenerTask(&DOMApplicationCache::callCheckingListener, frame->loader()->documentLoader());
+ postListenerTask(&DOMApplicationCache::callNoUpdateListener, frame->loader()->documentLoader());
+ return;
+ }
+
ASSERT(!m_frame);
m_frame = frame;
@@ -385,14 +402,29 @@ void ApplicationCacheGroup::update(Frame* frame, ApplicationCacheUpdateOption up
ASSERT(m_completionType == None);
// FIXME: Handle defer loading
-
- ResourceRequest request(m_manifestURL);
+ m_manifestHandle = createResourceHandle(m_manifestURL, m_newestCache ? m_newestCache->manifestResource() : 0);
+}
+
+PassRefPtr<ResourceHandle> ApplicationCacheGroup::createResourceHandle(const KURL& url, ApplicationCacheResource* newestCachedResource)
+{
+ ResourceRequest request(url);
m_frame->loader()->applyUserAgent(request);
- // FIXME: Should ask to revalidate from origin.
+ request.setHTTPHeaderField("Cache-Control", "max-age=0");
+
+ if (newestCachedResource) {
+ const String& lastModified = newestCachedResource->response().httpHeaderField("Last-Modified");
+ const String& eTag = newestCachedResource->response().httpHeaderField("ETag");
+ if (!lastModified.isEmpty() || !eTag.isEmpty()) {
+ if (!lastModified.isEmpty())
+ request.setHTTPHeaderField("If-Modified-Since", lastModified);
+ if (!eTag.isEmpty())
+ request.setHTTPHeaderField("If-None-Match", eTag);
+ }
+ }
- m_manifestHandle = ResourceHandle::create(request, this, m_frame, false, true, false);
+ return ResourceHandle::create(request, this, m_frame, false, true, false);
}
-
+
void ApplicationCacheGroup::didReceiveResponse(ResourceHandle* handle, const ResourceResponse& response)
{
if (handle == m_manifestHandle) {
@@ -409,11 +441,24 @@ void ApplicationCacheGroup::didReceiveResponse(ResourceHandle* handle, const Res
unsigned type = m_pendingEntries.get(url);
- // If this is an initial cache attempt, we should not get implicit resources delivered here.
+ // If this is an initial cache attempt, we should not get master resources delivered here.
if (!m_newestCache)
- ASSERT(!(type & ApplicationCacheResource::Implicit));
+ ASSERT(!(type & ApplicationCacheResource::Master));
+
+ if (m_newestCache && response.httpStatusCode() == 304) { // Not modified.
+ ApplicationCacheResource* newestCachedResource = m_newestCache->resourceForURL(handle->request().url());
+ if (newestCachedResource) {
+ m_cacheBeingUpdated->addResource(ApplicationCacheResource::create(url, newestCachedResource->response(), type, newestCachedResource->data()));
+ m_currentHandle->cancel();
+ m_currentHandle = 0;
+ // Load the next resource, if any.
+ startLoadingEntry();
+ return;
+ }
+ // The server could return 304 for an unconditional request - in this case, we handle the response as a normal error.
+ }
- if (response.httpStatusCode() / 100 != 2 || response.url() != m_currentHandle->request().url()) {
+ if (response.httpStatusCode() / 100 != 2 || response.url() != m_currentHandle->request().url()) {
if ((type & ApplicationCacheResource::Explicit) || (type & ApplicationCacheResource::Fallback)) {
// Note that cacheUpdateFailed() can cause the cache group to be deleted.
cacheUpdateFailed();
@@ -428,12 +473,12 @@ void ApplicationCacheGroup::didReceiveResponse(ResourceHandle* handle, const Res
// Copy the resource and its metadata from the newest application cache in cache group whose completeness flag is complete, and act
// as if that was the fetched resource, ignoring the resource obtained from the network.
ASSERT(m_newestCache);
- ApplicationCacheResource* resource = m_newestCache->resourceForURL(handle->request().url());
- ASSERT(resource);
- m_cacheBeingUpdated->addResource(ApplicationCacheResource::create(handle->request().url(), resource->response(), resource->type(), resource->data()));
- // Load the next resource, if any.
+ ApplicationCacheResource* newestCachedResource = m_newestCache->resourceForURL(handle->request().url());
+ ASSERT(newestCachedResource);
+ m_cacheBeingUpdated->addResource(ApplicationCacheResource::create(url, newestCachedResource->response(), type, newestCachedResource->data()));
m_currentHandle->cancel();
m_currentHandle = 0;
+ // Load the next resource, if any.
startLoadingEntry();
}
return;
@@ -484,10 +529,11 @@ void ApplicationCacheGroup::didFail(ResourceHandle* handle, const ResourceError&
}
unsigned type = m_currentResource ? m_currentResource->type() : m_pendingEntries.get(handle->request().url());
+ const KURL& url = handle->request().url();
- ASSERT(!m_currentResource || !m_pendingEntries.contains(handle->request().url()));
+ ASSERT(!m_currentResource || !m_pendingEntries.contains(url));
m_currentResource = 0;
- m_pendingEntries.remove(handle->request().url());
+ m_pendingEntries.remove(url);
if ((type & ApplicationCacheResource::Explicit) || (type & ApplicationCacheResource::Fallback)) {
// Note that cacheUpdateFailed() can cause the cache group to be deleted.
@@ -496,9 +542,9 @@ void ApplicationCacheGroup::didFail(ResourceHandle* handle, const ResourceError&
// Copy the resource and its metadata from the newest application cache in cache group whose completeness flag is complete, and act
// as if that was the fetched resource, ignoring the resource obtained from the network.
ASSERT(m_newestCache);
- ApplicationCacheResource* resource = m_newestCache->resourceForURL(handle->request().url());
- ASSERT(resource);
- m_cacheBeingUpdated->addResource(ApplicationCacheResource::create(handle->request().url(), resource->response(), resource->type(), resource->data()));
+ ApplicationCacheResource* newestCachedResource = m_newestCache->resourceForURL(url);
+ ASSERT(newestCachedResource);
+ m_cacheBeingUpdated->addResource(ApplicationCacheResource::create(url, newestCachedResource->response(), type, newestCachedResource->data()));
// Load the next resource, if any.
startLoadingEntry();
}
@@ -514,6 +560,9 @@ void ApplicationCacheGroup::didReceiveManifestResponse(const ResourceResponse& r
return;
}
+ if (response.httpStatusCode() == 304)
+ return;
+
if (response.httpStatusCode() / 100 != 2 || response.url() != m_manifestHandle->request().url() || !equalIgnoringCase(response.mimeType(), "text/cache-manifest")) {
cacheUpdateFailed();
return;
@@ -525,28 +574,29 @@ void ApplicationCacheGroup::didReceiveManifestResponse(const ResourceResponse& r
void ApplicationCacheGroup::didReceiveManifestData(const char* data, int length)
{
- ASSERT(m_manifestResource);
- m_manifestResource->data()->append(data, length);
+ if (m_manifestResource)
+ m_manifestResource->data()->append(data, length);
}
void ApplicationCacheGroup::didFinishLoadingManifest()
{
- if (!m_manifestResource) {
+ bool isUpgradeAttempt = m_newestCache;
+
+ if (!isUpgradeAttempt && !m_manifestResource) {
+ // The server returned 304 Not Modified even though we didn't send a conditional request.
cacheUpdateFailed();
return;
}
- bool isUpgradeAttempt = m_newestCache;
-
m_manifestHandle = 0;
- // Check if the manifest is byte-for-byte identical.
+ // Check if the manifest was not modified.
if (isUpgradeAttempt) {
ApplicationCacheResource* newestManifest = m_newestCache->manifestResource();
ASSERT(newestManifest);
- if (newestManifest->data()->size() == m_manifestResource->data()->size() &&
- !memcmp(newestManifest->data()->data(), m_manifestResource->data()->data(), newestManifest->data()->size())) {
+ if (!m_manifestResource || // The resource will be null if HTTP response was 304 Not Modified.
+ newestManifest->data()->size() == m_manifestResource->data()->size() && !memcmp(newestManifest->data()->data(), m_manifestResource->data()->data(), newestManifest->data()->size())) {
m_completionType = NoUpdate;
m_manifestResource = 0;
@@ -581,7 +631,7 @@ void ApplicationCacheGroup::didFinishLoadingManifest()
ApplicationCache::ResourceMap::const_iterator end = m_newestCache->end();
for (ApplicationCache::ResourceMap::const_iterator it = m_newestCache->begin(); it != end; ++it) {
unsigned type = it->second->type();
- if (type & (ApplicationCacheResource::Implicit | ApplicationCacheResource::Dynamic))
+ if (type & (ApplicationCacheResource::Master | ApplicationCacheResource::Dynamic))
addEntry(it->first, type);
}
}
@@ -657,7 +707,11 @@ void ApplicationCacheGroup::checkIfLoadIsComplete()
case NoUpdate:
ASSERT(isUpgradeAttempt);
ASSERT(!m_cacheBeingUpdated);
- ASSERT(m_storageID);
+
+ // The storage could have been manually emptied by the user.
+ if (!m_storageID)
+ cacheStorage().storeNewestCache(this);
+
postListenerTask(&DOMApplicationCache::callNoUpdateListener, m_associatedDocumentLoaders);
break;
case Failure:
@@ -707,15 +761,9 @@ void ApplicationCacheGroup::startLoadingEntry()
postListenerTask(&DOMApplicationCache::callProgressListener, m_associatedDocumentLoaders);
- // FIXME: If this is an upgrade attempt, the newest cache should be used as an HTTP cache.
-
ASSERT(!m_currentHandle);
- ResourceRequest request(it->first);
- m_frame->loader()->applyUserAgent(request);
- // FIXME: Should ask to revalidate from origin.
-
- m_currentHandle = ResourceHandle::create(request, this, m_frame, false, true, false);
+ m_currentHandle = createResourceHandle(KURL(it->first), m_newestCache ? m_newestCache->resourceForURL(it->first) : 0);
}
void ApplicationCacheGroup::deliverDelayedMainResources()
@@ -743,10 +791,10 @@ void ApplicationCacheGroup::addEntry(const String& url, unsigned type)
{
ASSERT(m_cacheBeingUpdated);
- // Don't add the URL if we already have an implicit resource in the cache
+ // Don't add the URL if we already have an master resource in the cache
// (i.e., the main resource finished loading before the manifest).
if (ApplicationCacheResource* resource = m_cacheBeingUpdated->resourceForURL(url)) {
- ASSERT(resource->type() & ApplicationCacheResource::Implicit);
+ ASSERT(resource->type() & ApplicationCacheResource::Master);
ASSERT(!m_frame->loader()->documentLoader()->isLoadingMainResource());
resource->addType(type);