diff options
Diffstat (limited to 'WebCore/loader/appcache/ApplicationCacheGroup.cpp')
-rw-r--r-- | WebCore/loader/appcache/ApplicationCacheGroup.cpp | 136 |
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); |