📄 applicationcachestorage.cpp
字号:
ASSERT(group->storageID() == 0); SQLiteStatement statement(m_database, "INSERT INTO CacheGroups (manifestHostHash, manifestURL) VALUES (?, ?)"); if (statement.prepare() != SQLResultOk) return false; statement.bindInt64(1, urlHostHash(group->manifestURL())); statement.bindText(2, group->manifestURL()); if (!executeStatement(statement)) return false; group->setStorageID(static_cast<unsigned>(m_database.lastInsertRowID())); return true;} bool ApplicationCacheStorage::store(ApplicationCache* cache){ ASSERT(cache->storageID() == 0); ASSERT(cache->group()->storageID() != 0); SQLiteStatement statement(m_database, "INSERT INTO Caches (cacheGroup) VALUES (?)"); if (statement.prepare() != SQLResultOk) return false; statement.bindInt64(1, cache->group()->storageID()); if (!executeStatement(statement)) return false; unsigned cacheStorageID = static_cast<unsigned>(m_database.lastInsertRowID()); // Store all resources { ApplicationCache::ResourceMap::const_iterator end = cache->end(); for (ApplicationCache::ResourceMap::const_iterator it = cache->begin(); it != end; ++it) { if (!store(it->second.get(), cacheStorageID)) return false; } } // Store the online whitelist const Vector<KURL>& onlineWhitelist = cache->onlineWhitelist(); { size_t whitelistSize = onlineWhitelist.size(); for (size_t i = 0; i < whitelistSize; ++i) { SQLiteStatement statement(m_database, "INSERT INTO CacheWhitelistURLs (url, cache) VALUES (?, ?)"); statement.prepare(); statement.bindText(1, onlineWhitelist[i]); statement.bindInt64(2, cacheStorageID); if (!executeStatement(statement)) return false; } } // Store fallback URLs. const FallbackURLVector& fallbackURLs = cache->fallbackURLs(); { size_t fallbackCount = fallbackURLs.size(); for (size_t i = 0; i < fallbackCount; ++i) { SQLiteStatement statement(m_database, "INSERT INTO FallbackURLs (namespace, fallbackURL, cache) VALUES (?, ?, ?)"); statement.prepare(); statement.bindText(1, fallbackURLs[i].first); statement.bindText(2, fallbackURLs[i].second); statement.bindInt64(3, cacheStorageID); if (!executeStatement(statement)) return false; } } cache->setStorageID(cacheStorageID); return true;}bool ApplicationCacheStorage::store(ApplicationCacheResource* resource, unsigned cacheStorageID){ ASSERT(cacheStorageID); ASSERT(!resource->storageID()); openDatabase(true); // First, insert the data SQLiteStatement dataStatement(m_database, "INSERT INTO CacheResourceData (data) VALUES (?)"); if (dataStatement.prepare() != SQLResultOk) return false; if (resource->data()->size()) dataStatement.bindBlob(1, resource->data()->data(), resource->data()->size()); if (!dataStatement.executeCommand()) return false; unsigned dataId = static_cast<unsigned>(m_database.lastInsertRowID()); // Then, insert the resource // Serialize the headers Vector<UChar> stringBuilder; HTTPHeaderMap::const_iterator end = resource->response().httpHeaderFields().end(); for (HTTPHeaderMap::const_iterator it = resource->response().httpHeaderFields().begin(); it!= end; ++it) { stringBuilder.append(it->first.characters(), it->first.length()); stringBuilder.append((UChar)':'); stringBuilder.append(it->second.characters(), it->second.length()); stringBuilder.append((UChar)'\n'); } String headers = String::adopt(stringBuilder); SQLiteStatement resourceStatement(m_database, "INSERT INTO CacheResources (url, statusCode, responseURL, headers, data, mimeType, textEncodingName) VALUES (?, ?, ?, ?, ?, ?, ?)"); if (resourceStatement.prepare() != SQLResultOk) return false; resourceStatement.bindText(1, resource->url()); resourceStatement.bindInt64(2, resource->response().httpStatusCode()); resourceStatement.bindText(3, resource->response().url()); resourceStatement.bindText(4, headers); resourceStatement.bindInt64(5, dataId); resourceStatement.bindText(6, resource->response().mimeType()); resourceStatement.bindText(7, resource->response().textEncodingName()); if (!executeStatement(resourceStatement)) return false; unsigned resourceId = static_cast<unsigned>(m_database.lastInsertRowID()); // Finally, insert the cache entry SQLiteStatement entryStatement(m_database, "INSERT INTO CacheEntries (cache, type, resource) VALUES (?, ?, ?)"); if (entryStatement.prepare() != SQLResultOk) return false; entryStatement.bindInt64(1, cacheStorageID); entryStatement.bindInt64(2, resource->type()); entryStatement.bindInt64(3, resourceId); if (!executeStatement(entryStatement)) return false; resource->setStorageID(resourceId); return true;}bool ApplicationCacheStorage::storeUpdatedType(ApplicationCacheResource* resource, ApplicationCache* cache){ ASSERT_UNUSED(cache, cache->storageID()); ASSERT(resource->storageID()); // FIXME: If the resource gained a Dynamic bit, it should be re-inserted at the end for correct order. ASSERT(!(resource->type() & ApplicationCacheResource::Dynamic)); // First, insert the data SQLiteStatement entryStatement(m_database, "UPDATE CacheEntries SET type=? WHERE resource=?"); if (entryStatement.prepare() != SQLResultOk) return false; entryStatement.bindInt64(1, resource->type()); entryStatement.bindInt64(2, resource->storageID()); return executeStatement(entryStatement);}void ApplicationCacheStorage::store(ApplicationCacheResource* resource, ApplicationCache* cache){ ASSERT(cache->storageID()); openDatabase(true); SQLiteTransaction storeResourceTransaction(m_database); storeResourceTransaction.begin(); if (!store(resource, cache->storageID())) return; storeResourceTransaction.commit();}bool ApplicationCacheStorage::storeNewestCache(ApplicationCacheGroup* group){ openDatabase(true); SQLiteTransaction storeCacheTransaction(m_database); storeCacheTransaction.begin(); if (!group->storageID()) { // Store the group if (!store(group)) return false; } ASSERT(group->newestCache()); ASSERT(!group->isObsolete()); ASSERT(!group->newestCache()->storageID()); // Store the newest cache if (!store(group->newestCache())) return false; // Update the newest cache in the group. SQLiteStatement statement(m_database, "UPDATE CacheGroups SET newestCache=? WHERE id=?"); if (statement.prepare() != SQLResultOk) return false; statement.bindInt64(1, group->newestCache()->storageID()); statement.bindInt64(2, group->storageID()); if (!executeStatement(statement)) return false; storeCacheTransaction.commit(); return true;}static inline void parseHeader(const UChar* header, size_t headerLength, ResourceResponse& response){ int pos = find(header, headerLength, ':'); ASSERT(pos != -1); AtomicString headerName = AtomicString(header, pos); String headerValue = String(header + pos + 1, headerLength - pos - 1); response.setHTTPHeaderField(headerName, headerValue);}static inline void parseHeaders(const String& headers, ResourceResponse& response){ int startPos = 0; int endPos; while ((endPos = headers.find('\n', startPos)) != -1) { ASSERT(startPos != endPos); parseHeader(headers.characters() + startPos, endPos - startPos, response); startPos = endPos + 1; } if (startPos != static_cast<int>(headers.length())) parseHeader(headers.characters(), headers.length(), response);} PassRefPtr<ApplicationCache> ApplicationCacheStorage::loadCache(unsigned storageID){ SQLiteStatement cacheStatement(m_database, "SELECT url, type, mimeType, textEncodingName, headers, CacheResourceData.data FROM CacheEntries INNER JOIN CacheResources ON CacheEntries.resource=CacheResources.id " "INNER JOIN CacheResourceData ON CacheResourceData.id=CacheResources.data WHERE CacheEntries.cache=?"); if (cacheStatement.prepare() != SQLResultOk) { LOG_ERROR("Could not prepare cache statement, error \"%s\"", m_database.lastErrorMsg()); return 0; } cacheStatement.bindInt64(1, storageID); RefPtr<ApplicationCache> cache = ApplicationCache::create(); int result; while ((result = cacheStatement.step()) == SQLResultRow) { KURL url(cacheStatement.getColumnText(0)); unsigned type = static_cast<unsigned>(cacheStatement.getColumnInt64(1)); Vector<char> blob; cacheStatement.getColumnBlobAsVector(5, blob); RefPtr<SharedBuffer> data = SharedBuffer::adoptVector(blob); String mimeType = cacheStatement.getColumnText(2); String textEncodingName = cacheStatement.getColumnText(3); ResourceResponse response(url, mimeType, data->size(), textEncodingName, ""); String headers = cacheStatement.getColumnText(4); parseHeaders(headers, response); RefPtr<ApplicationCacheResource> resource = ApplicationCacheResource::create(url, response, type, data.release()); if (type & ApplicationCacheResource::Manifest) cache->setManifestResource(resource.release()); else cache->addResource(resource.release()); } if (result != SQLResultDone) LOG_ERROR("Could not load cache resources, error \"%s\"", m_database.lastErrorMsg()); // Load the online whitelist SQLiteStatement whitelistStatement(m_database, "SELECT url FROM CacheWhitelistURLs WHERE cache=?"); if (whitelistStatement.prepare() != SQLResultOk) return 0; whitelistStatement.bindInt64(1, storageID); Vector<KURL> whitelist; while ((result = whitelistStatement.step()) == SQLResultRow) whitelist.append(whitelistStatement.getColumnText(0)); if (result != SQLResultDone) LOG_ERROR("Could not load cache online whitelist, error \"%s\"", m_database.lastErrorMsg()); cache->setOnlineWhitelist(whitelist); // Load fallback URLs. SQLiteStatement fallbackStatement(m_database, "SELECT namespace, fallbackURL FROM FallbackURLs WHERE cache=?"); if (fallbackStatement.prepare() != SQLResultOk) return 0; fallbackStatement.bindInt64(1, storageID); FallbackURLVector fallbackURLs; while ((result = fallbackStatement.step()) == SQLResultRow) fallbackURLs.append(make_pair(fallbackStatement.getColumnText(0), fallbackStatement.getColumnText(1))); if (result != SQLResultDone) LOG_ERROR("Could not load fallback URLs, error \"%s\"", m_database.lastErrorMsg()); cache->setFallbackURLs(fallbackURLs); cache->setStorageID(storageID); return cache.release();} void ApplicationCacheStorage::remove(ApplicationCache* cache){ if (!cache->storageID()) return; openDatabase(false); if (!m_database.isOpen()) return; ASSERT(cache->group()); ASSERT(cache->group()->storageID()); // All associated data will be deleted by database triggers. SQLiteStatement statement(m_database, "DELETE FROM Caches WHERE id=?"); if (statement.prepare() != SQLResultOk) return; statement.bindInt64(1, cache->storageID()); executeStatement(statement); cache->clearStorageID(); if (cache->group()->newestCache() == cache) { // Currently, there are no triggers on the cache group, which is why the cache had to be removed separately above. SQLiteStatement groupStatement(m_database, "DELETE FROM CacheGroups WHERE id=?"); if (groupStatement.prepare() != SQLResultOk) return; groupStatement.bindInt64(1, cache->group()->storageID()); executeStatement(groupStatement); cache->group()->clearStorageID(); }} void ApplicationCacheStorage::empty(){ openDatabase(false); if (!m_database.isOpen()) return; // Clear cache groups, caches and cache resources. executeSQLCommand("DELETE FROM CacheGroups"); executeSQLCommand("DELETE FROM Caches"); // Clear the storage IDs for the caches in memory. // The caches will still work, but cached resources will not be saved to disk // until a cache update process has been initiated. CacheGroupMap::const_iterator end = m_cachesInMemory.end(); for (CacheGroupMap::const_iterator it = m_cachesInMemory.begin(); it != end; ++it) it->second->clearStorageID();} bool ApplicationCacheStorage::storeCopyOfCache(const String& cacheDirectory, ApplicationCache* cache){ // Create a new cache. RefPtr<ApplicationCache> cacheCopy = ApplicationCache::create(); cacheCopy->setOnlineWhitelist(cache->onlineWhitelist()); cacheCopy->setFallbackURLs(cache->fallbackURLs()); // Traverse the cache and add copies of all resources. ApplicationCache::ResourceMap::const_iterator end = cache->end(); for (ApplicationCache::ResourceMap::const_iterator it = cache->begin(); it != end; ++it) { ApplicationCacheResource* resource = it->second.get(); RefPtr<ApplicationCacheResource> resourceCopy = ApplicationCacheResource::create(resource->url(), resource->response(), resource->type(), resource->data()); cacheCopy->addResource(resourceCopy.release()); } // Now create a new cache group. OwnPtr<ApplicationCacheGroup> groupCopy(new ApplicationCacheGroup(cache->group()->manifestURL(), true)); groupCopy->setNewestCache(cacheCopy); ApplicationCacheStorage copyStorage; copyStorage.setCacheDirectory(cacheDirectory); // Empty the cache in case something was there before. copyStorage.empty(); return copyStorage.storeNewestCache(groupCopy.get());} ApplicationCacheStorage& cacheStorage(){ DEFINE_STATIC_LOCAL(ApplicationCacheStorage, storage, ()); return storage;}} // namespace WebCore#endif // ENABLE(OFFLINE_WEB_APPLICATIONS)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -