Commit 10f8ba69 authored by andersca@apple.com's avatar andersca@apple.com

2008-05-01 Anders Carlsson <andersca@apple.com>

        Reviewed by Darin.

        Move management of cache groups to ApplicationCacheStorage. Also,
        application caches now start out with a null group and will have their group set
        when the cache has finished loading. 

        * loader/appcache/ApplicationCache.cpp:
        (WebCore::ApplicationCache::ApplicationCache):
        Initialize m_group to 0.
        
        (WebCore::ApplicationCache::~ApplicationCache):
        Null check the group.
        
        (WebCore::ApplicationCache::setGroup):
        New method for setting the group.
        
        * loader/appcache/ApplicationCache.h:        
        (WebCore::ApplicationCache::create):
        Remove the group argument.
        
        * loader/appcache/ApplicationCacheGroup.cpp:
        (WebCore::ApplicationCacheGroup::~ApplicationCacheGroup):
        Let the storage know that the cache group has been destroyed.
        
        (WebCore::ApplicationCacheGroup::cacheForMainRequest):
        Call into the storage.
        
        (WebCore::ApplicationCacheGroup::selectCache):
        Call into the storage.
        
        (WebCore::ApplicationCacheGroup::documentLoaderDestroyed):
        When there are no document loaders associated with the cache group,
        set the newest cache to 0.
        
        (WebCore::ApplicationCacheGroup::cacheDestroyed):
        Delete the group if there are no associated caches.
        
        (WebCore::ApplicationCacheGroup::setNewestCache):
        New method that will set the newest cache and associate the group with the cache.
        
        (WebCore::ApplicationCacheGroup::checkIfLoadIsComplete):
        Call setNewestCache instead.
        
        * loader/appcache/ApplicationCacheStorage.cpp:
        (WebCore::urlHostHash):
        Move host hash method here.
        
        (WebCore::ApplicationCacheStorage::findOrCreateCacheGroup):
        New method that finds a cache group with a given manifest URL or creates a new one.

        (WebCore::ApplicationCacheStorage::cacheGroupForURL):
        New method that returns a cache group for a given URL.
        
        (WebCore::ApplicationCacheStorage::cacheGroupDestroyed):
        When the cache group has been destroyed, remove it from the hash map.
        
        * loader/appcache/ApplicationCacheStorage.h:
        Add new methods.I b



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@32762 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 2b08899d
2008-05-01 Anders Carlsson <andersca@apple.com>
Reviewed by Darin.
Move management of cache groups to ApplicationCacheStorage. Also,
application caches now start out with a null group and will have their group set
when the cache has finished loading.
* loader/appcache/ApplicationCache.cpp:
(WebCore::ApplicationCache::ApplicationCache):
Initialize m_group to 0.
(WebCore::ApplicationCache::~ApplicationCache):
Null check the group.
(WebCore::ApplicationCache::setGroup):
New method for setting the group.
* loader/appcache/ApplicationCache.h:
(WebCore::ApplicationCache::create):
Remove the group argument.
* loader/appcache/ApplicationCacheGroup.cpp:
(WebCore::ApplicationCacheGroup::~ApplicationCacheGroup):
Let the storage know that the cache group has been destroyed.
(WebCore::ApplicationCacheGroup::cacheForMainRequest):
Call into the storage.
(WebCore::ApplicationCacheGroup::selectCache):
Call into the storage.
(WebCore::ApplicationCacheGroup::documentLoaderDestroyed):
When there are no document loaders associated with the cache group,
set the newest cache to 0.
(WebCore::ApplicationCacheGroup::cacheDestroyed):
Delete the group if there are no associated caches.
(WebCore::ApplicationCacheGroup::setNewestCache):
New method that will set the newest cache and associate the group with the cache.
(WebCore::ApplicationCacheGroup::checkIfLoadIsComplete):
Call setNewestCache instead.
* loader/appcache/ApplicationCacheStorage.cpp:
(WebCore::urlHostHash):
Move host hash method here.
(WebCore::ApplicationCacheStorage::findOrCreateCacheGroup):
New method that finds a cache group with a given manifest URL or creates a new one.
(WebCore::ApplicationCacheStorage::cacheGroupForURL):
New method that returns a cache group for a given URL.
(WebCore::ApplicationCacheStorage::cacheGroupDestroyed):
When the cache group has been destroyed, remove it from the hash map.
* loader/appcache/ApplicationCacheStorage.h:
Add new methods.I b
2008-05-01 Dan Winship <danw@gnome.org>
Reviewed by Alp Toker.
......@@ -34,16 +34,22 @@
namespace WebCore {
ApplicationCache::ApplicationCache(ApplicationCacheGroup* group)
: m_group(group)
ApplicationCache::ApplicationCache()
: m_group(0)
, m_manifest(0)
{
ASSERT(group);
}
ApplicationCache::~ApplicationCache()
{
m_group->cacheDestroyed(this);
if (m_group)
m_group->cacheDestroyed(this);
}
void ApplicationCache::setGroup(ApplicationCacheGroup* group)
{
ASSERT(!m_group);
m_group = group;
}
void ApplicationCache::setManifestResource(PassRefPtr<ApplicationCacheResource> manifest)
......
......@@ -46,7 +46,7 @@ class ResourceRequest;
class ApplicationCache : public RefCounted<ApplicationCache> {
public:
static PassRefPtr<ApplicationCache> create(ApplicationCacheGroup* group) { return adoptRef(new ApplicationCache(group)); }
static PassRefPtr<ApplicationCache> create() { return adoptRef(new ApplicationCache); }
~ApplicationCache();
void addResource(PassRefPtr<ApplicationCacheResource> resource);
......@@ -55,6 +55,7 @@ public:
void setManifestResource(PassRefPtr<ApplicationCacheResource> manifest);
ApplicationCacheResource* manifestResource() const { return m_manifest; }
void setGroup(ApplicationCacheGroup*);
ApplicationCacheGroup* group() const { return m_group; }
ApplicationCacheResource* resourceForRequest(const ResourceRequest&);
......@@ -79,7 +80,7 @@ public:
static bool requestIsHTTPOrHTTPSGet(const ResourceRequest&);
private:
ApplicationCache(ApplicationCacheGroup*);
ApplicationCache();
ApplicationCacheGroup* m_group;
ResourceMap m_resources;
......
......@@ -30,6 +30,7 @@
#include "ApplicationCache.h"
#include "ApplicationCacheResource.h"
#include "ApplicationCacheStorage.h"
#include "DocumentLoader.h"
#include "DOMApplicationCache.h"
#include "DOMWindow.h"
......@@ -43,25 +44,6 @@
namespace WebCore {
typedef HashMap<String, ApplicationCacheGroup*> CacheGroupMap;
CacheGroupMap& cacheGroupMap()
{
static CacheGroupMap cacheGroupMap;
return cacheGroupMap;
}
// In order to quickly determinate if a given resource exists in an application cache,
// we keep a hash set of the hosts of the manifest URLs of all cache groups.
typedef HashSet<unsigned, AlreadyHashed> CacheHostSet;
CacheHostSet& cacheHostSet() {
static CacheHostSet cacheHostSet;
return cacheHostSet;
}
ApplicationCacheGroup::ApplicationCacheGroup(const KURL& manifestURL)
: m_manifestURL(manifestURL)
, m_status(Idle)
......@@ -70,12 +52,12 @@ ApplicationCacheGroup::ApplicationCacheGroup(const KURL& manifestURL)
{
}
static unsigned urlHostHash(const KURL& url)
ApplicationCacheGroup::~ApplicationCacheGroup()
{
unsigned hostStart = url.hostStart();
unsigned hostEnd = url.hostEnd();
ASSERT(!m_newestCache);
ASSERT(m_caches.isEmpty());
return AlreadyHashed::avoidDeletedValue(StringImpl::computeHash(url.string().characters() + hostStart, hostEnd - hostStart));
cacheStorage().cacheGroupDestroyed(this);
}
ApplicationCache* ApplicationCacheGroup::cacheForMainRequest(const ResourceRequest& request, DocumentLoader* loader)
......@@ -88,21 +70,10 @@ ApplicationCache* ApplicationCacheGroup::cacheForMainRequest(const ResourceReque
if (loader->frame() != loader->frame()->page()->mainFrame())
return 0;
const KURL& url = request.url();
if (!cacheHostSet().contains(urlHostHash(url)))
return 0;
CacheGroupMap::const_iterator end = cacheGroupMap().end();
for (CacheGroupMap::const_iterator it = cacheGroupMap().begin(); it != end; ++it) {
ApplicationCacheGroup* group = it->second;
if (ApplicationCacheGroup* group = cacheStorage().cacheGroupForURL(request.url())) {
ASSERT(group->newestCache());
if (!protocolHostAndPortAreEqual(url, group->manifestURL()))
continue;
if (ApplicationCache* cache = group->newestCache()) {
if (cache->resourceForURL(url))
return cache;
}
return group->newestCache();
}
return 0;
......@@ -166,19 +137,9 @@ void ApplicationCacheGroup::selectCache(Frame* frame, const KURL& manifestURL)
return;
}
ApplicationCache* cache = 0;
ApplicationCacheGroup* group = 0;
std::pair<CacheGroupMap::iterator, bool> result = cacheGroupMap().add(manifestURL, 0);
if (result.second) {
group = new ApplicationCacheGroup(manifestURL);
result.first->second = group;
cacheHostSet().add(urlHostHash(manifestURL));
} else {
group = result.first->second;
cache = group->newestCache();
}
ApplicationCacheGroup* group = cacheStorage().findOrCreateCacheGroup(manifestURL);
if (cache) {
if (ApplicationCache* cache = group->newestCache()) {
ASSERT(cache->manifestResource());
group->associateDocumentLoaderWithCache(frame->loader()->documentLoader(), cache);
......@@ -190,11 +151,8 @@ void ApplicationCacheGroup::selectCache(Frame* frame, const KURL& manifestURL)
} else {
bool isUpdating = group->m_cacheBeingUpdated;
if (!isUpdating) {
group->m_cacheBeingUpdated = ApplicationCache::create(group);
group->m_caches.add(group->m_cacheBeingUpdated.get());
}
if (!isUpdating)
group->m_cacheBeingUpdated = ApplicationCache::create();
documentLoader->setCandidateApplicationCacheGroup(group);
group->m_cacheCandidates.add(documentLoader);
......@@ -231,7 +189,7 @@ void ApplicationCacheGroup::selectCacheWithoutManifestURL(Frame* frame)
if (isMainFrame && mainResourceCache) {
mainResourceCache->group()->associateDocumentLoaderWithCache(documentLoader, mainResourceCache);
mainResourceCache->group()->update(frame);
}
}
}
void ApplicationCacheGroup::finishedLoadingMainResource(DocumentLoader* loader)
......@@ -269,23 +227,42 @@ void ApplicationCacheGroup::documentLoaderDestroyed(DocumentLoader* loader)
ASSERT(!m_cacheCandidates.contains(loader));
m_associatedDocumentLoaders.remove(it);
return;
} else {
ASSERT(m_cacheCandidates.contains(loader));
m_cacheCandidates.remove(loader);
}
ASSERT(m_cacheCandidates.contains(loader));
m_cacheCandidates.remove(loader);
// FIXME: Delete the group if the set of cache candidates is empty.
}
if (m_associatedDocumentLoaders.isEmpty() && m_cacheCandidates.isEmpty()) {
// We should only have the newest cache remaining.
ASSERT(m_caches.size() == 1);
ASSERT(m_caches.contains(m_newestCache.get()));
// This should cause us to be deleted.
m_newestCache = 0;
}
}
void ApplicationCacheGroup::cacheDestroyed(ApplicationCache* cache)
{
ASSERT(m_caches.contains(cache));
m_caches.remove(cache);
}
if (m_caches.isEmpty())
delete this;
}
void ApplicationCacheGroup::setNewestCache(PassRefPtr<ApplicationCache> newestCache)
{
ASSERT(!m_newestCache);
ASSERT(!m_caches.contains(newestCache.get()));
ASSERT(!newestCache->group());
m_newestCache = newestCache;
m_caches.add(m_newestCache.get());
m_newestCache->setGroup(this);
}
void ApplicationCacheGroup::update(Frame* frame)
{
if (m_status == Checking || m_status == Downloading)
......@@ -460,8 +437,7 @@ void ApplicationCacheGroup::didFinishLoadingManifest()
if (isUpgradeAttempt) {
ASSERT(!m_cacheBeingUpdated);
m_cacheBeingUpdated = ApplicationCache::create(this);
m_caches.add(m_cacheBeingUpdated.get());
m_cacheBeingUpdated = ApplicationCache::create();
ApplicationCache::ResourceMap::const_iterator end = m_newestCache->end();
for (ApplicationCache::ResourceMap::const_iterator it = m_newestCache->begin(); it != end; ++it) {
......@@ -488,13 +464,6 @@ void ApplicationCacheGroup::cacheUpdateFailed()
m_cacheBeingUpdated = 0;
m_manifestResource = 0;
bool isUpgradeAttempt = m_newestCache;
if (!isUpgradeAttempt) {
// If the cache attempt failed, setting m_cacheBeingUpdated to 0 should cause
// it to be deleted.
ASSERT(m_caches.isEmpty());
}
while (!m_cacheCandidates.isEmpty()) {
HashSet<DocumentLoader*>::iterator it = m_cacheCandidates.begin();
......@@ -544,7 +513,7 @@ void ApplicationCacheGroup::checkIfLoadIsComplete()
DocumentLoader* loader = *it;
ASSERT(!loader->applicationCache());
ASSERT(loader->candidateApplicationCacheGroup() == m_cacheBeingUpdated->group());
ASSERT(loader->candidateApplicationCacheGroup() == this);
associateDocumentLoaderWithCache(loader, m_cacheBeingUpdated.get());
......@@ -554,7 +523,7 @@ void ApplicationCacheGroup::checkIfLoadIsComplete()
}
}
m_newestCache = m_cacheBeingUpdated.release();
setNewestCache(m_cacheBeingUpdated.release());
callListeners(isUpgradeAttempt ? &DOMApplicationCache::callUpdateReadyListener : &DOMApplicationCache::callCachedListener,
documentLoaders);
......
......@@ -49,6 +49,9 @@ class Frame;
class ApplicationCacheGroup : Noncopyable, ResourceHandleClient {
public:
ApplicationCacheGroup(const KURL& manifestURL);
~ApplicationCacheGroup();
enum Status { Idle, Checking, Downloading };
static ApplicationCache* cacheForMainRequest(const ResourceRequest&, DocumentLoader*);
......@@ -67,9 +70,9 @@ public:
void finishedLoadingMainResource(DocumentLoader* loader);
void documentLoaderDestroyed(DocumentLoader* loader);
private:
ApplicationCacheGroup(const KURL& manifestURL);
void setNewestCache(PassRefPtr<ApplicationCache> newestCache);
private:
typedef void (DOMApplicationCache::*ListenerFunction)();
void callListenersOnAssociatedDocuments(ListenerFunction);
void callListeners(ListenerFunction, const Vector<RefPtr<DocumentLoader> >& loaders);
......
......@@ -25,12 +25,72 @@
#include "config.h"
#include "ApplicationCacheStorage.h"
#include "FileSystem.h"
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
#include "ApplicationCacheGroup.h"
#include "ApplicationCache.h"
#include "FileSystem.h"
#include "KURL.h"
namespace WebCore {
static unsigned urlHostHash(const KURL& url)
{
unsigned hostStart = url.hostStart();
unsigned hostEnd = url.hostEnd();
return AlreadyHashed::avoidDeletedValue(StringImpl::computeHash(url.string().characters() + hostStart, hostEnd - hostStart));
}
ApplicationCacheGroup* ApplicationCacheStorage::findOrCreateCacheGroup(const KURL& manifestURL)
{
std::pair<CacheGroupMap::iterator, bool> result = m_cachesInMemory.add(manifestURL, 0);
if (!result.second) {
ASSERT(result.first->second);
return result.first->second;
}
result.first->second = new ApplicationCacheGroup(manifestURL);
m_cacheHostSet.add(urlHostHash(manifestURL));
return result.first->second;
}
ApplicationCacheGroup* ApplicationCacheStorage::cacheGroupForURL(const KURL& url)
{
// Hash the host name and see if there's a manifest with the same host.
if (!m_cacheHostSet.contains(urlHostHash(url)))
return 0;
// Check if a cache already exists in memory.
CacheGroupMap::const_iterator end = m_cachesInMemory.end();
for (CacheGroupMap::const_iterator it = m_cachesInMemory.begin(); it != end; ++it) {
ApplicationCacheGroup* group = it->second;
if (!protocolHostAndPortAreEqual(url, group->manifestURL()))
continue;
if (ApplicationCache* cache = group->newestCache()) {
if (cache->resourceForURL(url))
return group;
}
}
return 0;
}
void ApplicationCacheStorage::cacheGroupDestroyed(ApplicationCacheGroup* group)
{
ASSERT(m_cachesInMemory.get(group->manifestURL()) == group);
m_cachesInMemory.remove(group->manifestURL());
if (!group->newestCache())
m_cacheHostSet.remove(urlHostHash(group->manifestURL()));
}
void ApplicationCacheStorage::setCacheDirectory(const String& cacheDirectory)
{
ASSERT(m_cacheDirectory.isNull());
......
......@@ -30,19 +30,37 @@
#include "PlatformString.h"
#include "SQLiteDatabase.h"
#include "StringHash.h"
#include <wtf/HashCountedSet.h>
namespace WebCore {
class ApplicationCacheGroup;
class KURL;
class ApplicationCacheStorage {
public:
void setCacheDirectory(const String&);
public:
ApplicationCacheGroup* cacheGroupForURL(const KURL&);
ApplicationCacheGroup* findOrCreateCacheGroup(const KURL& manifestURL);
void cacheGroupDestroyed(ApplicationCacheGroup*);
private:
void openDatabase(bool createIfDoesNotExist);
String m_cacheDirectory;
SQLiteDatabase m_database;
SQLiteDatabase m_database;
// In order to quickly determinate if a given resource exists in an application cache,
// we keep a hash set of the hosts of the manifest URLs of all cache groups.
HashCountedSet<unsigned, AlreadyHashed> m_cacheHostSet;
typedef HashMap<String, ApplicationCacheGroup*> CacheGroupMap;
CacheGroupMap m_cachesInMemory;
};
ApplicationCacheStorage& cacheStorage();
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment