📄 applicationcachegroup.cpp
字号:
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. m_updateStatus = Downloading; postListenerTask(&DOMApplicationCache::callDownloadingListener, 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 | ApplicationCacheResource::Dynamic)) 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); startLoadingEntry();}void ApplicationCacheGroup::cacheUpdateFailed(){ stopLoading(); m_manifestResource = 0; // Wait for master resource loads to finish. m_completionType = Failure; deliverDelayedMainResources();} void ApplicationCacheGroup::manifestNotFound(){ makeObsolete(); postListenerTask(&DOMApplicationCache::callObsoleteListener, m_associatedDocumentLoaders); postListenerTask(&DOMApplicationCache::callErrorListener, m_pendingMasterResourceLoaders); stopLoading(); ASSERT(m_pendingEntries.isEmpty()); m_manifestResource = 0; while (!m_pendingMasterResourceLoaders.isEmpty()) { HashSet<DocumentLoader*>::iterator it = m_pendingMasterResourceLoaders.begin(); ASSERT((*it)->candidateApplicationCacheGroup() == this); ASSERT(!(*it)->applicationCache()); (*it)->setCandidateApplicationCacheGroup(0); m_pendingMasterResourceLoaders.remove(it); } m_updateStatus = Idle; m_frame = 0; if (m_caches.isEmpty()) { ASSERT(m_associatedDocumentLoaders.isEmpty()); ASSERT(!m_cacheBeingUpdated); delete this; }}void ApplicationCacheGroup::checkIfLoadIsComplete(){ if (m_manifestHandle || !m_pendingEntries.isEmpty() || !m_pendingMasterResourceLoaders.isEmpty()) return; // We're done, all resources have finished downloading (successfully or not). bool isUpgradeAttempt = m_newestCache; switch (m_completionType) { case None: ASSERT_NOT_REACHED(); return; case NoUpdate: ASSERT(isUpgradeAttempt); ASSERT(!m_cacheBeingUpdated); ASSERT(m_storageID); postListenerTask(&DOMApplicationCache::callNoUpdateListener, m_associatedDocumentLoaders); break; case Failure: ASSERT(!m_cacheBeingUpdated); postListenerTask(&DOMApplicationCache::callErrorListener, m_associatedDocumentLoaders); if (m_caches.isEmpty()) { ASSERT(m_associatedDocumentLoaders.isEmpty()); delete this; return; } break; case Completed: { // FIXME: Fetch the resource from manifest URL again, and check whether it is identical to the one used for update (in case the application was upgraded server-side in the meanwhile). (<rdar://problem/6467625>) ASSERT(m_cacheBeingUpdated); m_cacheBeingUpdated->setManifestResource(m_manifestResource.release()); RefPtr<ApplicationCache> oldNewestCache = (m_newestCache == m_cacheBeingUpdated) ? 0 : m_newestCache; setNewestCache(m_cacheBeingUpdated.release()); cacheStorage().storeNewestCache(this); if (oldNewestCache) cacheStorage().remove(oldNewestCache.get()); postListenerTask(isUpgradeAttempt ? &DOMApplicationCache::callUpdateReadyListener : &DOMApplicationCache::callCachedListener, m_associatedDocumentLoaders); break; } } m_completionType = None; m_updateStatus = Idle; m_frame = 0;}void ApplicationCacheGroup::startLoadingEntry(){ ASSERT(m_cacheBeingUpdated); if (m_pendingEntries.isEmpty()) { m_completionType = Completed; deliverDelayedMainResources(); return; } EntryMap::const_iterator it = m_pendingEntries.begin(); postListenerTask(&DOMApplicationCache::callProgressListener, m_associatedDocumentLoaders); ASSERT(!m_currentHandle); m_currentHandle = createResourceHandle(KURL(it->first), m_newestCache ? m_newestCache->resourceForURL(it->first) : 0);}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::addEntry(const String& url, unsigned type){ ASSERT(m_cacheBeingUpdated); // 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::Master); ASSERT(!m_frame->loader()->documentLoader()->isLoadingMainResource()); resource->addType(type); return; } // Don't add the URL if it's the same as the manifest URL. ASSERT(m_manifestResource); if (m_manifestResource->url() == url) { m_manifestResource->addType(type); return; } pair<EntryMap::iterator, bool> result = m_pendingEntries.add(url, type); if (!result.second) result.first->second |= type;}void ApplicationCacheGroup::associateDocumentLoaderWithCache(DocumentLoader* loader, ApplicationCache* cache){ // If teardown started already, revive the group. if (!m_newestCache && !m_cacheBeingUpdated) m_newestCache = cache; ASSERT(!m_isObsolete); loader->setApplicationCache(cache); ASSERT(!m_associatedDocumentLoaders.contains(loader)); m_associatedDocumentLoaders.add(loader);} class CallCacheListenerTask : public ScriptExecutionContext::Task { typedef void (DOMApplicationCache::*ListenerFunction)();public: static PassRefPtr<CallCacheListenerTask> create(ListenerFunction listenerFunction) { return adoptRef(new CallCacheListenerTask(listenerFunction)); } virtual void performTask(ScriptExecutionContext* context) { ASSERT(context->isDocument()); if (DOMWindow* window = static_cast<Document*>(context)->domWindow()) { if (DOMApplicationCache* domCache = window->optionalApplicationCache()) (domCache->*m_listenerFunction)(); } }private: CallCacheListenerTask(ListenerFunction listenerFunction) : m_listenerFunction(listenerFunction) { } ListenerFunction m_listenerFunction;};void ApplicationCacheGroup::postListenerTask(ListenerFunction listenerFunction, const HashSet<DocumentLoader*>& loaderSet){ HashSet<DocumentLoader*>::const_iterator loaderSetEnd = loaderSet.end(); for (HashSet<DocumentLoader*>::const_iterator iter = loaderSet.begin(); iter != loaderSetEnd; ++iter) postListenerTask(listenerFunction, *iter);}void ApplicationCacheGroup::postListenerTask(ListenerFunction listenerFunction, DocumentLoader* loader){ Frame* frame = loader->frame(); if (!frame) return; ASSERT(frame->loader()->documentLoader() == loader); frame->document()->postTask(CallCacheListenerTask::create(listenerFunction));}void ApplicationCacheGroup::clearStorageID(){ m_storageID = 0; HashSet<ApplicationCache*>::const_iterator end = m_caches.end(); for (HashSet<ApplicationCache*>::const_iterator it = m_caches.begin(); it != end; ++it) (*it)->clearStorageID();} }#endif // ENABLE(OFFLINE_WEB_APPLICATIONS)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -