void ApplicationCacheGroup::didFinishLoading(ResourceHandle* handle) { if (handle == m_manifestHandle) { didFinishLoadingManifest(); return; } ASSERT(m_currentHandle == handle); ASSERT(m_pendingEntries.contains(handle->request().url())); m_pendingEntries.remove(handle->request().url()); ASSERT(m_cacheBeingUpdated); m_cacheBeingUpdated->addResource(m_currentResource.release()); m_currentHandle = 0; // Load the next file. if (!m_pendingEntries.isEmpty()) { startLoadingEntry(); return; } checkIfLoadIsComplete(); }
void ApplicationCacheGroup::finishedLoadingMainResource(DocumentLoader* loader) { const KURL& url = loader->originalURL(); if (ApplicationCache* cache = loader->applicationCache()) { RefPtr<ApplicationCacheResource> resource = ApplicationCacheResource::create(url, loader->response(), ApplicationCacheResource::Implicit, loader->mainResourceData()); cache->addResource(resource.release()); if (!m_cacheBeingUpdated) return; } ASSERT(m_pendingEntries.contains(url)); EntryMap::iterator it = m_pendingEntries.find(url); ASSERT(it->second & ApplicationCacheResource::Implicit); RefPtr<ApplicationCacheResource> resource = ApplicationCacheResource::create(url, loader->response(), it->second, loader->mainResourceData()); ASSERT(m_cacheBeingUpdated); m_cacheBeingUpdated->addResource(resource.release()); m_pendingEntries.remove(it); checkIfLoadIsComplete(); }
void ApplicationCacheGroup::didReachMaxAppCacheSize() { ASSERT(m_frame); ASSERT(m_cacheBeingUpdated); m_frame->page()->chrome().client().reachedMaxAppCacheSize(cacheStorage().spaceNeeded(m_cacheBeingUpdated->estimatedSizeInStorage())); m_calledReachedMaxAppCacheSize = true; checkIfLoadIsComplete(); }
void ApplicationCacheGroup::finishedLoadingMainResource(DocumentLoader* loader) { ASSERT(m_pendingMasterResourceLoaders.contains(loader)); ASSERT(m_completionType == None || m_pendingEntries.isEmpty()); URL url = loader->url(); if (url.hasFragmentIdentifier()) url.removeFragmentIdentifier(); switch (m_completionType) { case None: // The main resource finished loading before the manifest was ready. It will be handled via dispatchMainResources() later. return; case NoUpdate: ASSERT(!m_cacheBeingUpdated); associateDocumentLoaderWithCache(loader, m_newestCache.get()); if (ApplicationCacheResource* resource = m_newestCache->resourceForURL(url)) { if (!(resource->type() & ApplicationCacheResource::Master)) { resource->addType(ApplicationCacheResource::Master); ASSERT(!resource->storageID()); } } else { RefPtr<ResourceBuffer> buffer = loader->mainResourceData(); m_newestCache->addResource(ApplicationCacheResource::create(url, loader->response(), ApplicationCacheResource::Master, buffer ? buffer->sharedBuffer() : 0)); } break; case Failure: // Cache update has been a failure, so there is no reason to keep the document associated with the incomplete cache // (its main resource was not cached yet, so it is likely that the application changed significantly server-side). ASSERT(!m_cacheBeingUpdated); // Already cleared out by stopLoading(). loader->applicationCacheHost()->setApplicationCache(0); // Will unset candidate, too. m_associatedDocumentLoaders.remove(loader); postListenerTask(ApplicationCacheHost::ERROR_EVENT, loader); break; case Completed: ASSERT(m_associatedDocumentLoaders.contains(loader)); if (ApplicationCacheResource* resource = m_cacheBeingUpdated->resourceForURL(url)) { if (!(resource->type() & ApplicationCacheResource::Master)) { resource->addType(ApplicationCacheResource::Master); ASSERT(!resource->storageID()); } } else { RefPtr<ResourceBuffer> buffer = loader->mainResourceData(); m_cacheBeingUpdated->addResource(ApplicationCacheResource::create(url, loader->response(), ApplicationCacheResource::Master, buffer ? buffer->sharedBuffer() : 0)); } // The "cached" event will be posted to all associated documents once update is complete. break; } ASSERT(m_downloadingPendingMasterResourceLoadersCount > 0); m_downloadingPendingMasterResourceLoadersCount--; checkIfLoadIsComplete(); }
void ApplicationCacheGroup::failedLoadingMainResource(DocumentLoader* loader) { ASSERT(m_pendingMasterResourceLoaders.contains(loader)); ASSERT(m_completionType == None || m_pendingEntries.isEmpty()); switch (m_completionType) { case None: // The main resource finished loading before the manifest was ready. It will be handled via dispatchMainResources() later. return; case NoUpdate: ASSERT(!m_cacheBeingUpdated); // The manifest didn't change, and we have a relevant cache - but the main resource download failed mid-way, so it cannot be stored to the cache, // and the loader does not get associated to it. If there are other main resources being downloaded for this cache group, they may still succeed. postListenerTask(ApplicationCacheHost::ERROR_EVENT, loader); break; case Failure: // Cache update failed, too. ASSERT(!m_cacheBeingUpdated); // Already cleared out by stopLoading(). ASSERT(!loader->applicationCacheHost()->applicationCache() || loader->applicationCacheHost()->applicationCache() == m_cacheBeingUpdated); loader->applicationCacheHost()->setApplicationCache(0); // Will unset candidate, too. m_associatedDocumentLoaders.remove(loader); postListenerTask(ApplicationCacheHost::ERROR_EVENT, loader); break; case Completed: // The cache manifest didn't list this main resource, and all cache entries were already updated successfully - but the main resource failed to load, // so it cannot be stored to the cache. If there are other main resources being downloaded for this cache group, they may still succeed. ASSERT(m_associatedDocumentLoaders.contains(loader)); ASSERT(loader->applicationCacheHost()->applicationCache() == m_cacheBeingUpdated); ASSERT(!loader->applicationCacheHost()->candidateApplicationCacheGroup()); m_associatedDocumentLoaders.remove(loader); loader->applicationCacheHost()->setApplicationCache(0); postListenerTask(ApplicationCacheHost::ERROR_EVENT, loader); break; } ASSERT(m_downloadingPendingMasterResourceLoadersCount > 0); m_downloadingPendingMasterResourceLoadersCount--; checkIfLoadIsComplete(); }
void ApplicationCacheGroup::deliverDelayedMainResources() { // Need to copy loaders, because the cache group may be destroyed at the end of iteration. Vector<DocumentLoader*> loaders; copyToVector(m_pendingMasterResourceLoaders, loaders); size_t count = loaders.size(); for (size_t i = 0; i != count; ++i) { DocumentLoader* loader = loaders[i]; if (loader->isLoadingMainResource()) continue; const ResourceError& error = loader->mainDocumentError(); if (error.isNull()) finishedLoadingMainResource(loader); else failedLoadingMainResource(loader); } if (!count) checkIfLoadIsComplete(); }
void ApplicationCacheGroup::startLoadingEntry() { ASSERT(m_cacheBeingUpdated); if (m_pendingEntries.isEmpty()) { checkIfLoadIsComplete(); return; } EntryMap::const_iterator it = m_pendingEntries.begin(); // If this is an initial cache attempt, we do not want to fetch any implicit entries, // since those are fed to us by the normal loader machinery. if (!m_newestCache) { // Get the first URL in the entry table that is not implicit EntryMap::const_iterator end = m_pendingEntries.end(); while (it->second & ApplicationCacheResource::Implicit) { ++it; if (it == end) return; } } callListenersOnAssociatedDocuments(&DOMApplicationCache::callProgressListener); // 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); m_currentHandle = ResourceHandle::create(request, this, m_frame, false, true, false); }