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::checkIfLoadIsComplete() { ASSERT(m_cacheBeingUpdated); if (m_manifestHandle) return; if (!m_pendingEntries.isEmpty()) return; // We're done bool isUpgradeAttempt = m_newestCache; m_cacheBeingUpdated->setManifestResource(m_manifestResource.release()); Vector<RefPtr<DocumentLoader> > documentLoaders; if (isUpgradeAttempt) { ASSERT(m_cacheCandidates.isEmpty()); copyToVector(m_associatedDocumentLoaders, documentLoaders); } else { while (!m_cacheCandidates.isEmpty()) { HashSet<DocumentLoader*>::iterator it = m_cacheCandidates.begin(); DocumentLoader* loader = *it; ASSERT(!loader->applicationCache()); ASSERT(loader->candidateApplicationCacheGroup() == this); associateDocumentLoaderWithCache(loader, m_cacheBeingUpdated.get()); documentLoaders.append(loader); m_cacheCandidates.remove(it); } } setNewestCache(m_cacheBeingUpdated.release()); // Store the cache cacheStorage().storeNewestCache(this); callListeners(isUpgradeAttempt ? &DOMApplicationCache::callUpdateReadyListener : &DOMApplicationCache::callCachedListener, documentLoaders); m_status = Idle; m_frame = 0; }
void ApplicationCacheGroup::didFinishLoadingManifest() { bool isUpgradeAttempt = m_newestCache; if (!isUpgradeAttempt && !m_manifestResource) { // The server returned 304 Not Modified even though we didn't send a conditional request. m_frame->document()->addConsoleMessage(OtherMessageSource, ErrorMessageLevel, "Application Cache manifest could not be fetched because of an unexpected 304 Not Modified server response."); cacheUpdateFailed(); return; } m_manifestHandle = 0; // Check if the manifest was not modified. if (isUpgradeAttempt) { ApplicationCacheResource* newestManifest = m_newestCache->manifestResource(); ASSERT(newestManifest); 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; deliverDelayedMainResources(); return; } } Manifest manifest; if (!parseManifest(m_manifestURL, m_manifestResource->data()->data(), m_manifestResource->data()->size(), manifest)) { // At the time of this writing, lack of "CACHE MANIFEST" signature is the only reason for parseManifest to fail. m_frame->document()->addConsoleMessage(OtherMessageSource, ErrorMessageLevel, "Application Cache manifest could not be parsed. Does it start with CACHE MANIFEST?"); cacheUpdateFailed(); return; } ASSERT(!m_cacheBeingUpdated); m_cacheBeingUpdated = ApplicationCache::create(); m_cacheBeingUpdated->setGroup(this); HashSet<DocumentLoader*>::const_iterator masterEnd = m_pendingMasterResourceLoaders.end(); for (HashSet<DocumentLoader*>::const_iterator iter = m_pendingMasterResourceLoaders.begin(); iter != masterEnd; ++iter) associateDocumentLoaderWithCache(*iter, m_cacheBeingUpdated.get()); // We have the manifest, now download the resources. setUpdateStatus(Downloading); postListenerTask(ApplicationCacheHost::DOWNLOADING_EVENT, m_associatedDocumentLoaders); ASSERT(m_pendingEntries.isEmpty()); if (isUpgradeAttempt) { ApplicationCache::ResourceMap::const_iterator end = m_newestCache->end(); for (ApplicationCache::ResourceMap::const_iterator it = m_newestCache->begin(); it != end; ++it) { unsigned type = it->value->type(); if (type & ApplicationCacheResource::Master) addEntry(it->key, type); } } HashSet<String>::const_iterator end = manifest.explicitURLs.end(); for (HashSet<String>::const_iterator it = manifest.explicitURLs.begin(); it != end; ++it) addEntry(*it, ApplicationCacheResource::Explicit); size_t fallbackCount = manifest.fallbackURLs.size(); for (size_t i = 0; i < fallbackCount; ++i) addEntry(manifest.fallbackURLs[i].second, ApplicationCacheResource::Fallback); m_cacheBeingUpdated->setOnlineWhitelist(manifest.onlineWhitelistedURLs); m_cacheBeingUpdated->setFallbackURLs(manifest.fallbackURLs); m_cacheBeingUpdated->setAllowsAllNetworkRequests(manifest.allowAllNetworkRequests); m_progressTotal = m_pendingEntries.size(); m_progressDone = 0; recalculateAvailableSpaceInQuota(); startLoadingEntry(); }
void ApplicationCacheGroup::didFinishLoadingManifest() { 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; } m_manifestHandle = 0; // Check if the manifest was not modified. if (isUpgradeAttempt) { ApplicationCacheResource* newestManifest = m_newestCache->manifestResource(); ASSERT(newestManifest); 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; deliverDelayedMainResources(); return; } } Manifest manifest; if (!parseManifest(m_manifestURL, m_manifestResource->data()->data(), m_manifestResource->data()->size(), manifest)) { cacheUpdateFailed(); return; } ASSERT(!m_cacheBeingUpdated); m_cacheBeingUpdated = ApplicationCache::create(); m_cacheBeingUpdated->setGroup(this); HashSet<DocumentLoader*>::const_iterator masterEnd = m_pendingMasterResourceLoaders.end(); for (HashSet<DocumentLoader*>::const_iterator iter = m_pendingMasterResourceLoaders.begin(); iter != masterEnd; ++iter) associateDocumentLoaderWithCache(*iter, m_cacheBeingUpdated.get()); // We have the manifest, now download the resources. setUpdateStatus(Downloading); postListenerTask(ApplicationCacheHost::DOWNLOADING_EVENT, m_associatedDocumentLoaders); ASSERT(m_pendingEntries.isEmpty()); if (isUpgradeAttempt) { 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::Master) addEntry(it->first, type); } } HashSet<String>::const_iterator end = manifest.explicitURLs.end(); for (HashSet<String>::const_iterator it = manifest.explicitURLs.begin(); it != end; ++it) addEntry(*it, ApplicationCacheResource::Explicit); size_t fallbackCount = manifest.fallbackURLs.size(); for (size_t i = 0; i < fallbackCount; ++i) addEntry(manifest.fallbackURLs[i].second, ApplicationCacheResource::Fallback); m_cacheBeingUpdated->setOnlineWhitelist(manifest.onlineWhitelistedURLs); m_cacheBeingUpdated->setFallbackURLs(manifest.fallbackURLs); m_cacheBeingUpdated->setAllowsAllNetworkRequests(manifest.allowAllNetworkRequests); m_progressTotal = m_pendingEntries.size(); m_progressDone = 0; startLoadingEntry(); }
void ApplicationCacheGroup::didFinishLoadingManifest() { bool isUpgradeAttempt = m_newestCache; if (!isUpgradeAttempt && !m_manifestResource) { // The server returned 304 Not Modified even though we didn't send a conditional request. m_frame->document()->addConsoleMessage(MessageSource::AppCache, MessageLevel::Error, ASCIILiteral("Application Cache manifest could not be fetched because of an unexpected 304 Not Modified server response.")); cacheUpdateFailed(); return; } m_manifestHandle = nullptr; // Check if the manifest was not modified. if (isUpgradeAttempt) { ApplicationCacheResource* newestManifest = m_newestCache->manifestResource(); ASSERT(newestManifest); 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 = nullptr; deliverDelayedMainResources(); return; } } Manifest manifest; if (!parseManifest(m_manifestURL, m_manifestResource->data().data(), m_manifestResource->data().size(), manifest)) { // At the time of this writing, lack of "CACHE MANIFEST" signature is the only reason for parseManifest to fail. m_frame->document()->addConsoleMessage(MessageSource::AppCache, MessageLevel::Error, ASCIILiteral("Application Cache manifest could not be parsed. Does it start with CACHE MANIFEST?")); cacheUpdateFailed(); return; } ASSERT(!m_cacheBeingUpdated); m_cacheBeingUpdated = ApplicationCache::create(); m_cacheBeingUpdated->setGroup(this); for (auto& loader : m_pendingMasterResourceLoaders) associateDocumentLoaderWithCache(loader, m_cacheBeingUpdated.get()); // We have the manifest, now download the resources. setUpdateStatus(Downloading); postListenerTask(ApplicationCacheHost::DOWNLOADING_EVENT, m_associatedDocumentLoaders); ASSERT(m_pendingEntries.isEmpty()); if (isUpgradeAttempt) { for (const auto& urlAndResource : m_newestCache->resources()) { unsigned type = urlAndResource.value->type(); if (type & ApplicationCacheResource::Master) addEntry(urlAndResource.key, type); } } for (const auto& explicitURL : manifest.explicitURLs) addEntry(explicitURL, ApplicationCacheResource::Explicit); for (auto& fallbackURL : manifest.fallbackURLs) addEntry(fallbackURL.second, ApplicationCacheResource::Fallback); m_cacheBeingUpdated->setOnlineWhitelist(manifest.onlineWhitelistedURLs); m_cacheBeingUpdated->setFallbackURLs(manifest.fallbackURLs); m_cacheBeingUpdated->setAllowsAllNetworkRequests(manifest.allowAllNetworkRequests); m_progressTotal = m_pendingEntries.size(); m_progressDone = 0; recalculateAvailableSpaceInQuota(); startLoadingEntry(); }