summaryrefslogtreecommitdiffstats
path: root/WebCore/loader
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2009-08-11 17:01:47 +0100
committerBen Murdoch <benm@google.com>2009-08-11 18:21:02 +0100
commit0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5 (patch)
tree2943df35f62d885c89d01063cc528dd73b480fea /WebCore/loader
parent7e7a70bfa49a1122b2597a1e6367d89eb4035eca (diff)
downloadexternal_webkit-0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5.zip
external_webkit-0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5.tar.gz
external_webkit-0bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5.tar.bz2
Merge in WebKit r47029.
Diffstat (limited to 'WebCore/loader')
-rw-r--r--WebCore/loader/Cache.h2
-rw-r--r--WebCore/loader/CachedCSSStyleSheet.cpp4
-rw-r--r--WebCore/loader/CachedCSSStyleSheet.h2
-rw-r--r--WebCore/loader/CachedFont.cpp20
-rw-r--r--WebCore/loader/CachedFont.h2
-rw-r--r--WebCore/loader/CachedImage.cpp4
-rw-r--r--WebCore/loader/CachedImage.h2
-rw-r--r--WebCore/loader/CachedResource.cpp54
-rw-r--r--WebCore/loader/CachedResource.h7
-rw-r--r--WebCore/loader/CachedScript.cpp3
-rw-r--r--WebCore/loader/CachedScript.h2
-rw-r--r--WebCore/loader/CachedXSLStyleSheet.cpp6
-rw-r--r--WebCore/loader/CachedXSLStyleSheet.h2
-rw-r--r--WebCore/loader/CrossOriginPreflightResultCache.h4
-rw-r--r--WebCore/loader/DocLoader.cpp2
-rw-r--r--WebCore/loader/DocumentLoader.cpp137
-rw-r--r--WebCore/loader/DocumentLoader.h30
-rw-r--r--WebCore/loader/DocumentThreadableLoader.cpp15
-rw-r--r--WebCore/loader/DocumentThreadableLoader.h6
-rw-r--r--WebCore/loader/EmptyClients.h26
-rw-r--r--WebCore/loader/FrameLoader.cpp302
-rw-r--r--WebCore/loader/FrameLoader.h27
-rw-r--r--WebCore/loader/FrameLoaderClient.h17
-rw-r--r--WebCore/loader/FrameLoaderTypes.h7
-rw-r--r--WebCore/loader/MainResourceLoader.cpp60
-rw-r--r--WebCore/loader/MainResourceLoader.h12
-rw-r--r--WebCore/loader/PlaceholderDocument.cpp47
-rw-r--r--WebCore/loader/PlaceholderDocument.h48
-rw-r--r--WebCore/loader/PluginDocument.cpp6
-rw-r--r--WebCore/loader/ProgressTracker.h2
-rw-r--r--WebCore/loader/ResourceLoader.cpp32
-rw-r--r--WebCore/loader/ResourceLoader.h8
-rw-r--r--WebCore/loader/TextDocument.cpp2
-rw-r--r--WebCore/loader/TextResourceDecoder.cpp6
-rw-r--r--WebCore/loader/ThreadableLoader.cpp8
-rw-r--r--WebCore/loader/ThreadableLoader.h10
-rw-r--r--WebCore/loader/WorkerThreadableLoader.cpp16
-rw-r--r--WebCore/loader/WorkerThreadableLoader.h12
-rw-r--r--WebCore/loader/appcache/ApplicationCache.cpp33
-rw-r--r--WebCore/loader/appcache/ApplicationCache.h12
-rw-r--r--WebCore/loader/appcache/ApplicationCacheGroup.cpp202
-rw-r--r--WebCore/loader/appcache/ApplicationCacheGroup.h10
-rw-r--r--WebCore/loader/appcache/ApplicationCacheHost.cpp381
-rw-r--r--WebCore/loader/appcache/ApplicationCacheHost.h152
-rw-r--r--WebCore/loader/appcache/ApplicationCacheResource.cpp2
-rw-r--r--WebCore/loader/appcache/ApplicationCacheResource.h4
-rw-r--r--WebCore/loader/appcache/ApplicationCacheStorage.cpp189
-rw-r--r--WebCore/loader/appcache/ApplicationCacheStorage.h3
-rw-r--r--WebCore/loader/appcache/DOMApplicationCache.cpp208
-rw-r--r--WebCore/loader/appcache/DOMApplicationCache.h88
-rw-r--r--WebCore/loader/appcache/DOMApplicationCache.idl11
-rw-r--r--WebCore/loader/appcache/ManifestParser.cpp12
-rw-r--r--WebCore/loader/archive/ArchiveResourceCollection.h2
-rw-r--r--WebCore/loader/icon/IconDatabase.cpp4
-rw-r--r--WebCore/loader/icon/IconDatabase.h6
-rw-r--r--WebCore/loader/icon/IconDatabaseNone.cpp21
-rw-r--r--WebCore/loader/icon/IconLoader.h2
-rw-r--r--WebCore/loader/icon/PageURLRecord.h2
-rw-r--r--WebCore/loader/icon/wince/IconDatabaseWince.cpp81
-rw-r--r--WebCore/loader/loader.cpp52
-rw-r--r--WebCore/loader/loader.h11
61 files changed, 1601 insertions, 839 deletions
diff --git a/WebCore/loader/Cache.h b/WebCore/loader/Cache.h
index 9d81dc6..68be2d6 100644
--- a/WebCore/loader/Cache.h
+++ b/WebCore/loader/Cache.h
@@ -55,7 +55,7 @@ class KURL;
// -------|-----+++++++++++++++|
// -------|-----+++++++++++++++|+++++
-class Cache : Noncopyable {
+class Cache : public Noncopyable {
public:
friend Cache* cache();
diff --git a/WebCore/loader/CachedCSSStyleSheet.cpp b/WebCore/loader/CachedCSSStyleSheet.cpp
index 11d1213..4c466fa 100644
--- a/WebCore/loader/CachedCSSStyleSheet.cpp
+++ b/WebCore/loader/CachedCSSStyleSheet.cpp
@@ -49,10 +49,8 @@ CachedCSSStyleSheet::~CachedCSSStyleSheet()
{
}
-void CachedCSSStyleSheet::addClient(CachedResourceClient *c)
+void CachedCSSStyleSheet::didAddClient(CachedResourceClient *c)
{
- CachedResource::addClient(c);
-
if (!m_loading)
c->setCSSStyleSheet(m_url, m_decoder->encoding().name(), this);
}
diff --git a/WebCore/loader/CachedCSSStyleSheet.h b/WebCore/loader/CachedCSSStyleSheet.h
index fa0b31a..e782f2e 100644
--- a/WebCore/loader/CachedCSSStyleSheet.h
+++ b/WebCore/loader/CachedCSSStyleSheet.h
@@ -42,7 +42,7 @@ namespace WebCore {
const String sheetText(bool enforceMIMEType = true) const;
- virtual void addClient(CachedResourceClient*);
+ virtual void didAddClient(CachedResourceClient*);
virtual void allClientsRemoved();
diff --git a/WebCore/loader/CachedFont.cpp b/WebCore/loader/CachedFont.cpp
index 922fc91..7edaf4b 100644
--- a/WebCore/loader/CachedFont.cpp
+++ b/WebCore/loader/CachedFont.cpp
@@ -31,7 +31,11 @@
#include "CachedResourceClientWalker.h"
#include "DOMImplementation.h"
#include "FontPlatformData.h"
+#ifdef MANUAL_MERGE_REQUIRED
#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) || (PLATFORM(CHROMIUM) && PLATFORM(WIN_OS)) || PLATFORM(SGL)
+#else // MANUAL_MERGE_REQUIRED
+#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) || (PLATFORM(CHROMIUM) && (PLATFORM(WIN_OS) || PLATFORM(LINUX)))
+#endif // MANUAL_MERGE_REQUIRED
#include "FontCustomPlatformData.h"
#endif
#include "TextResourceDecoder.h"
@@ -60,7 +64,7 @@ CachedFont::CachedFont(const String &url)
CachedFont::~CachedFont()
{
-#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) || (PLATFORM(CHROMIUM) && PLATFORM(WIN_OS))
+#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) || (PLATFORM(CHROMIUM) && (PLATFORM(WIN_OS) || PLATFORM(LINUX)))
delete m_fontData;
#endif
}
@@ -71,10 +75,8 @@ void CachedFont::load(DocLoader*)
m_loading = true;
}
-void CachedFont::addClient(CachedResourceClient* c)
+void CachedFont::didAddClient(CachedResourceClient* c)
{
- CachedResource::addClient(c);
-
if (!m_loading)
c->fontLoaded(this);
}
@@ -100,7 +102,11 @@ void CachedFont::beginLoadIfNeeded(DocLoader* dl)
bool CachedFont::ensureCustomFontData()
{
+#ifdef MANUAL_MERGE_REQUIRED
#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) || (PLATFORM(CHROMIUM) && PLATFORM(WIN_OS)) || PLATFORM(SGL)
+#else // MANUAL_MERGE_REQUIRED
+#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) || (PLATFORM(CHROMIUM) && (PLATFORM(WIN_OS) || PLATFORM(LINUX)))
+#endif // MANUAL_MERGE_REQUIRED
#if ENABLE(SVG_FONTS)
ASSERT(!m_isSVGFont);
#endif
@@ -119,7 +125,11 @@ FontPlatformData CachedFont::platformDataFromCustomData(float size, bool bold, b
if (m_externalSVGDocument)
return FontPlatformData(size, bold, italic);
#endif
+#ifdef MANUAL_MERGE_REQUIRED
#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) || (PLATFORM(CHROMIUM) && PLATFORM(WIN_OS)) || PLATFORM(SGL)
+#else // MANUAL_MERGE_REQUIRED
+#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) || (PLATFORM(CHROMIUM) && (PLATFORM(WIN_OS) || PLATFORM(LINUX)))
+#endif // MANUAL_MERGE_REQUIRED
ASSERT(m_fontData);
return m_fontData->fontPlatformData(static_cast<int>(size), bold, italic, renderingMode);
#else
@@ -175,7 +185,7 @@ SVGFontElement* CachedFont::getSVGFontById(const String& fontName) const
void CachedFont::allClientsRemoved()
{
-#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) || (PLATFORM(CHROMIUM) && PLATFORM(WIN_OS))
+#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) || (PLATFORM(CHROMIUM) && (PLATFORM(WIN_OS) || PLATFORM(LINUX)))
if (m_fontData) {
delete m_fontData;
m_fontData = 0;
diff --git a/WebCore/loader/CachedFont.h b/WebCore/loader/CachedFont.h
index e4414c6..05b28f3 100644
--- a/WebCore/loader/CachedFont.h
+++ b/WebCore/loader/CachedFont.h
@@ -51,7 +51,7 @@ public:
virtual void load(DocLoader* docLoader);
- virtual void addClient(CachedResourceClient*);
+ virtual void didAddClient(CachedResourceClient*);
virtual void data(PassRefPtr<SharedBuffer> data, bool allDataReceived);
virtual void error();
diff --git a/WebCore/loader/CachedImage.cpp b/WebCore/loader/CachedImage.cpp
index eac02dc..a91f126 100644
--- a/WebCore/loader/CachedImage.cpp
+++ b/WebCore/loader/CachedImage.cpp
@@ -90,10 +90,8 @@ void CachedImage::load(DocLoader* docLoader)
m_loading = false;
}
-void CachedImage::addClient(CachedResourceClient* c)
+void CachedImage::didAddClient(CachedResourceClient* c)
{
- CachedResource::addClient(c);
-
if (m_decodedDataDeletionTimer.isActive())
m_decodedDataDeletionTimer.stop();
diff --git a/WebCore/loader/CachedImage.h b/WebCore/loader/CachedImage.h
index 22a3774..2aa35ac 100644
--- a/WebCore/loader/CachedImage.h
+++ b/WebCore/loader/CachedImage.h
@@ -60,7 +60,7 @@ public:
IntSize imageSize(float multiplier) const; // returns the size of the complete image.
IntRect imageRect(float multiplier) const; // The size of the currently decoded portion of the image.
- virtual void addClient(CachedResourceClient*);
+ virtual void didAddClient(CachedResourceClient*);
virtual void allClientsRemoved();
virtual void destroyDecodedData();
diff --git a/WebCore/loader/CachedResource.cpp b/WebCore/loader/CachedResource.cpp
index a2eaa2c..478873f 100644
--- a/WebCore/loader/CachedResource.cpp
+++ b/WebCore/loader/CachedResource.cpp
@@ -173,7 +173,13 @@ void CachedResource::setRequest(Request* request)
delete this;
}
-void CachedResource::addClient(CachedResourceClient *c)
+void CachedResource::addClient(CachedResourceClient* client)
+{
+ addClientToSet(client);
+ didAddClient(client);
+}
+
+void CachedResource::addClientToSet(CachedResourceClient* client)
{
ASSERT(!isPurgeable());
@@ -187,21 +193,28 @@ void CachedResource::addClient(CachedResourceClient *c)
}
if (!hasClients() && inCache())
cache()->addToLiveResourcesSize(this);
- m_clients.add(c);
+ m_clients.add(client);
}
-void CachedResource::removeClient(CachedResourceClient *c)
+void CachedResource::removeClient(CachedResourceClient* client)
{
- ASSERT(m_clients.contains(c));
- m_clients.remove(c);
+ ASSERT(m_clients.contains(client));
+ m_clients.remove(client);
+
if (canDelete() && !inCache())
delete this;
else if (!hasClients() && inCache()) {
cache()->removeFromLiveResourcesSize(this);
cache()->removeFromLiveDecodedResourcesList(this);
allClientsRemoved();
- cache()->prune();
+ if (response().cacheControlContainsNoStore()) {
+ // RFC2616 14.9.2:
+ // "no-store: ...MUST make a best-effort attempt to remove the information from volatile storage as promptly as possible"
+ cache()->remove(this);
+ } else
+ cache()->prune();
}
+ // This object may be dead here.
}
void CachedResource::deleteIfPossible()
@@ -330,10 +343,15 @@ void CachedResource::switchClientsToRevalidatedResource()
}
// Equivalent of calling removeClient() for all clients
m_clients.clear();
-
+
unsigned moveCount = clientsToMove.size();
for (unsigned n = 0; n < moveCount; ++n)
- m_resourceToRevalidate->addClient(clientsToMove[n]);
+ m_resourceToRevalidate->addClientToSet(clientsToMove[n]);
+ for (unsigned n = 0; n < moveCount; ++n) {
+ // Calling didAddClient for a client may end up removing another client. In that case it won't be in the set anymore.
+ if (m_resourceToRevalidate->m_clients.contains(clientsToMove[n]))
+ m_resourceToRevalidate->didAddClient(clientsToMove[n]);
+ }
}
void CachedResource::updateResponseAfterRevalidation(const ResourceResponse& validatingResponse)
@@ -355,18 +373,32 @@ void CachedResource::updateResponseAfterRevalidation(const ResourceResponse& val
bool CachedResource::canUseCacheValidator() const
{
- return !m_loading && (!m_response.httpHeaderField("Last-Modified").isEmpty() || !m_response.httpHeaderField("ETag").isEmpty());
+ if (m_loading || m_errorOccurred)
+ return false;
+
+ if (m_response.cacheControlContainsNoStore())
+ return false;
+
+ DEFINE_STATIC_LOCAL(const AtomicString, lastModifiedHeader, ("last-modified"));
+ DEFINE_STATIC_LOCAL(const AtomicString, eTagHeader, ("etag"));
+ return !m_response.httpHeaderField(lastModifiedHeader).isEmpty() || !m_response.httpHeaderField(eTagHeader).isEmpty();
}
bool CachedResource::mustRevalidate(CachePolicy cachePolicy) const
{
+ if (m_errorOccurred)
+ return true;
+
if (m_loading)
return false;
+
+ if (m_response.cacheControlContainsNoCache() || m_response.cacheControlContainsNoStore())
+ return true;
if (cachePolicy == CachePolicyCache)
- return m_response.cacheControlContainsNoCache() || (isExpired() && m_response.cacheControlContainsMustRevalidate());
+ return m_response.cacheControlContainsMustRevalidate() && isExpired();
- return isExpired() || m_response.cacheControlContainsNoCache();
+ return isExpired();
}
bool CachedResource::isSafeToMakePurgeable() const
diff --git a/WebCore/loader/CachedResource.h b/WebCore/loader/CachedResource.h
index 16cce26..babdf89 100644
--- a/WebCore/loader/CachedResource.h
+++ b/WebCore/loader/CachedResource.h
@@ -87,7 +87,7 @@ public:
const String &url() const { return m_url; }
Type type() const { return m_type; }
- virtual void addClient(CachedResourceClient*);
+ void addClient(CachedResourceClient*);
void removeClient(CachedResourceClient*);
bool hasClients() const { return !m_clients.isEmpty(); }
void deleteIfPossible();
@@ -100,7 +100,8 @@ public:
};
PreloadResult preloadResult() const { return m_preloadResult; }
void setRequestedFromNetworkingLayer() { m_requestedFromNetworkingLayer = true; }
-
+
+ virtual void didAddClient(CachedResourceClient*) = 0;
virtual void allClientsRemoved() { }
unsigned count() const { return m_clients.size(); }
@@ -204,6 +205,8 @@ protected:
bool m_errorOccurred;
private:
+ void addClientToSet(CachedResourceClient*);
+
// These are called by the friendly Cache only
void setResourceToRevalidate(CachedResource*);
void switchClientsToRevalidatedResource();
diff --git a/WebCore/loader/CachedScript.cpp b/WebCore/loader/CachedScript.cpp
index ebf0898..31483d6 100644
--- a/WebCore/loader/CachedScript.cpp
+++ b/WebCore/loader/CachedScript.cpp
@@ -49,9 +49,8 @@ CachedScript::~CachedScript()
{
}
-void CachedScript::addClient(CachedResourceClient* c)
+void CachedScript::didAddClient(CachedResourceClient* c)
{
- CachedResource::addClient(c);
if (!m_loading)
c->notifyFinished(this);
}
diff --git a/WebCore/loader/CachedScript.h b/WebCore/loader/CachedScript.h
index e1c3ee0..13afa89 100644
--- a/WebCore/loader/CachedScript.h
+++ b/WebCore/loader/CachedScript.h
@@ -41,7 +41,7 @@ namespace WebCore {
const String& script();
- virtual void addClient(CachedResourceClient*);
+ virtual void didAddClient(CachedResourceClient*);
virtual void allClientsRemoved();
virtual void setEncoding(const String&);
diff --git a/WebCore/loader/CachedXSLStyleSheet.cpp b/WebCore/loader/CachedXSLStyleSheet.cpp
index f221664..5da0abf 100644
--- a/WebCore/loader/CachedXSLStyleSheet.cpp
+++ b/WebCore/loader/CachedXSLStyleSheet.cpp
@@ -45,10 +45,8 @@ CachedXSLStyleSheet::CachedXSLStyleSheet(const String &url)
setAccept("text/xml, application/xml, application/xhtml+xml, text/xsl, application/rss+xml, application/atom+xml");
}
-void CachedXSLStyleSheet::addClient(CachedResourceClient *c)
-{
- CachedResource::addClient(c);
-
+void CachedXSLStyleSheet::didAddClient(CachedResourceClient* c)
+{
if (!m_loading)
c->setXSLStyleSheet(m_url, m_sheet);
}
diff --git a/WebCore/loader/CachedXSLStyleSheet.h b/WebCore/loader/CachedXSLStyleSheet.h
index 9eca098..b6b0585 100644
--- a/WebCore/loader/CachedXSLStyleSheet.h
+++ b/WebCore/loader/CachedXSLStyleSheet.h
@@ -41,7 +41,7 @@ namespace WebCore {
const String& sheet() const { return m_sheet; }
- virtual void addClient(CachedResourceClient*);
+ virtual void didAddClient(CachedResourceClient*);
virtual void setEncoding(const String&);
virtual String encoding() const;
diff --git a/WebCore/loader/CrossOriginPreflightResultCache.h b/WebCore/loader/CrossOriginPreflightResultCache.h
index 39c3cd1..f71d1c8 100644
--- a/WebCore/loader/CrossOriginPreflightResultCache.h
+++ b/WebCore/loader/CrossOriginPreflightResultCache.h
@@ -32,7 +32,7 @@ namespace WebCore {
class HTTPHeaderMap;
class ResourceResponse;
- class CrossOriginPreflightResultCacheItem : Noncopyable {
+ class CrossOriginPreflightResultCacheItem : public Noncopyable {
public:
CrossOriginPreflightResultCacheItem(bool credentials)
: m_absoluteExpiryTime(0)
@@ -57,7 +57,7 @@ namespace WebCore {
HeadersSet m_headers;
};
- class CrossOriginPreflightResultCache : Noncopyable {
+ class CrossOriginPreflightResultCache : public Noncopyable {
public:
static CrossOriginPreflightResultCache& shared();
diff --git a/WebCore/loader/DocLoader.cpp b/WebCore/loader/DocLoader.cpp
index 7b62074..9c11a88 100644
--- a/WebCore/loader/DocLoader.cpp
+++ b/WebCore/loader/DocLoader.cpp
@@ -254,7 +254,7 @@ void DocLoader::printAccessDeniedMessage(const KURL& url) const
m_doc->url().string().utf8().data());
// FIXME: provide a real line number and source URL.
- frame()->domWindow()->console()->addMessage(OtherMessageSource, ErrorMessageLevel, message, 1, String());
+ frame()->domWindow()->console()->addMessage(OtherMessageSource, LogMessageType, ErrorMessageLevel, message, 1, String());
}
void DocLoader::setAutoLoadImages(bool enable)
diff --git a/WebCore/loader/DocumentLoader.cpp b/WebCore/loader/DocumentLoader.cpp
index ffc61df..ddab04f 100644
--- a/WebCore/loader/DocumentLoader.cpp
+++ b/WebCore/loader/DocumentLoader.cpp
@@ -29,12 +29,16 @@
#include "config.h"
#include "DocumentLoader.h"
+#ifdef MANUAL_MERGE_REQUIRED
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
#include "ApplicationCache.h"
#include "ApplicationCacheGroup.h"
#include "ApplicationCacheResource.h"
#endif
#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size
+#else // MANUAL_MERGE_REQUIRED
+#include "ApplicationCacheHost.h"
+#endif // MANUAL_MERGE_REQUIRED
#include "ArchiveFactory.h"
#include "ArchiveResourceCollection.h"
#else
@@ -157,7 +161,7 @@ DocumentLoader::DocumentLoader(const ResourceRequest& req, const SubstituteData&
, m_substituteResourceDeliveryTimer(this, &DocumentLoader::substituteResourceDeliveryTimerFired)
, m_didCreateGlobalHistoryEntry(false)
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- , m_candidateApplicationCacheGroup(0)
+ , m_applicationCacheHost(new ApplicationCacheHost(this))
#endif
{
}
@@ -172,13 +176,6 @@ FrameLoader* DocumentLoader::frameLoader() const
DocumentLoader::~DocumentLoader()
{
ASSERT(!m_frame || frameLoader()->activeDocumentLoader() != this || !frameLoader()->isLoading());
-
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- if (m_applicationCache)
- m_applicationCache->group()->disassociateDocumentLoader(this);
- else if (m_candidateApplicationCacheGroup)
- m_candidateApplicationCacheGroup->disassociateDocumentLoader(this);
-#endif
}
PassRefPtr<SharedBuffer> DocumentLoader::mainResourceData() const
@@ -262,14 +259,7 @@ void DocumentLoader::mainReceivedError(const ResourceError& error, bool isComple
ASSERT(!error.isNull());
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- ApplicationCacheGroup* group = m_candidateApplicationCacheGroup;
- if (!group && m_applicationCache) {
- ASSERT(!mainResourceApplicationCache()); // If the main resource were loaded from a cache, it wouldn't fail.
- group = m_applicationCache->group();
- }
-
- if (group)
- group->failedLoadingMainResource(this);
+ m_applicationCacheHost->failedLoadingMainResource();
#endif
if (!frameLoader())
@@ -436,6 +426,9 @@ void DocumentLoader::attachToFrame()
void DocumentLoader::detachFromFrame()
{
ASSERT(m_frame);
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+ m_applicationCacheHost->setDOMApplicationCache(0);
+#endif
m_frame = 0;
}
@@ -457,9 +450,6 @@ void DocumentLoader::setPrimaryLoadComplete(bool flag)
if (flag) {
if (m_mainResourceLoader) {
m_mainResourceData = m_mainResourceLoader->resourceData();
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- m_mainResourceApplicationCache = m_mainResourceLoader->applicationCache();
-#endif
m_mainResourceLoader = 0;
}
@@ -857,113 +847,4 @@ void DocumentLoader::iconLoadDecisionAvailable()
m_frame->loader()->iconLoadDecisionAvailable();
}
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
-void DocumentLoader::setCandidateApplicationCacheGroup(ApplicationCacheGroup* group)
-{
- ASSERT(!m_applicationCache);
- m_candidateApplicationCacheGroup = group;
-}
-
-void DocumentLoader::setApplicationCache(PassRefPtr<ApplicationCache> applicationCache)
-{
- if (m_candidateApplicationCacheGroup) {
- ASSERT(!m_applicationCache);
- m_candidateApplicationCacheGroup = 0;
- }
-
- m_applicationCache = applicationCache;
-}
-
-ApplicationCache* DocumentLoader::mainResourceApplicationCache() const
-{
- if (m_mainResourceApplicationCache)
- return m_mainResourceApplicationCache.get();
- if (m_mainResourceLoader)
- return m_mainResourceLoader->applicationCache();
- return 0;
-}
-
-bool DocumentLoader::shouldLoadResourceFromApplicationCache(const ResourceRequest& request, ApplicationCacheResource*& resource)
-{
- ApplicationCache* cache = applicationCache();
- if (!cache || !cache->isComplete())
- return false;
-
- // If the resource is not a HTTP/HTTPS GET, then abort
- if (!ApplicationCache::requestIsHTTPOrHTTPSGet(request))
- return false;
-
- // If the resource's URL is an master entry, the manifest, an explicit entry, a fallback entry, or a dynamic entry
- // in the application cache, then get the resource from the cache (instead of fetching it).
- resource = cache->resourceForURL(request.url());
-
- // Resources that match fallback namespaces or online whitelist entries are fetched from the network,
- // unless they are also cached.
- if (!resource && (cache->urlMatchesFallbackNamespace(request.url()) || cache->isURLInOnlineWhitelist(request.url())))
- return false;
-
- // Resources that are not present in the manifest will always fail to load (at least, after the
- // cache has been primed the first time), making the testing of offline applications simpler.
- return true;
-}
-
-bool DocumentLoader::getApplicationCacheFallbackResource(const ResourceRequest& request, ApplicationCacheResource*& resource, ApplicationCache* cache)
-{
- if (!cache) {
- cache = applicationCache();
- if (!cache)
- return false;
- }
- if (!cache->isComplete())
- return false;
-
- // If the resource is not a HTTP/HTTPS GET, then abort
- if (!ApplicationCache::requestIsHTTPOrHTTPSGet(request))
- return false;
-
- KURL fallbackURL;
- if (!cache->urlMatchesFallbackNamespace(request.url(), &fallbackURL))
- return false;
-
- resource = cache->resourceForURL(fallbackURL);
- ASSERT(resource);
-
- return true;
-}
-
-bool DocumentLoader::scheduleApplicationCacheLoad(ResourceLoader* loader, const ResourceRequest& request, const KURL& originalURL)
-{
- if (!frameLoader()->frame()->settings() || !frameLoader()->frame()->settings()->offlineWebApplicationCacheEnabled())
- return false;
-
- if (request.url() != originalURL)
- return false;
-
- ApplicationCacheResource* resource;
- if (!shouldLoadResourceFromApplicationCache(request, resource))
- return false;
-
- m_pendingSubstituteResources.set(loader, resource);
- deliverSubstituteResourcesAfterDelay();
-
- return true;
-}
-
-bool DocumentLoader::scheduleLoadFallbackResourceFromApplicationCache(ResourceLoader* loader, const ResourceRequest& request, ApplicationCache* cache)
-{
- if (!frameLoader()->frame()->settings() || !frameLoader()->frame()->settings()->offlineWebApplicationCacheEnabled())
- return false;
-
- ApplicationCacheResource* resource;
- if (!getApplicationCacheFallbackResource(request, resource, cache))
- return false;
-
- m_pendingSubstituteResources.set(loader, resource);
- deliverSubstituteResourcesAfterDelay();
-
- return true;
-}
-
-#endif // ENABLE(OFFLINE_WEB_APPLICATIONS)
-
}
diff --git a/WebCore/loader/DocumentLoader.h b/WebCore/loader/DocumentLoader.h
index 4493e22..e4cf2c7 100644
--- a/WebCore/loader/DocumentLoader.h
+++ b/WebCore/loader/DocumentLoader.h
@@ -38,10 +38,14 @@
namespace WebCore {
+#ifdef MANUAL_MERGE_REQUIRED
class ApplicationCache;
class ApplicationCacheGroup;
class ApplicationCacheResource;
#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size
+#else // MANUAL_MERGE_REQUIRED
+ class ApplicationCacheHost;
+#endif // MANUAL_MERGE_REQUIRED
class Archive;
class ArchiveResource;
class ArchiveResourceCollection;
@@ -211,18 +215,7 @@ namespace WebCore {
void takeMemoryCacheLoadsForClientNotification(Vector<String>& loads);
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- bool scheduleApplicationCacheLoad(ResourceLoader*, const ResourceRequest&, const KURL& originalURL);
- bool scheduleLoadFallbackResourceFromApplicationCache(ResourceLoader*, const ResourceRequest&, ApplicationCache* = 0);
- bool shouldLoadResourceFromApplicationCache(const ResourceRequest&, ApplicationCacheResource*&);
- bool getApplicationCacheFallbackResource(const ResourceRequest&, ApplicationCacheResource*&, ApplicationCache* = 0);
-
- void setCandidateApplicationCacheGroup(ApplicationCacheGroup* group);
- ApplicationCacheGroup* candidateApplicationCacheGroup() const { return m_candidateApplicationCacheGroup; }
-
- void setApplicationCache(PassRefPtr<ApplicationCache> applicationCache);
- ApplicationCache* applicationCache() const { return m_applicationCache.get(); }
-
- ApplicationCache* mainResourceApplicationCache() const;
+ ApplicationCacheHost* applicationCacheHost() const { return m_applicationCacheHost.get(); }
#endif
protected:
@@ -312,16 +305,9 @@ namespace WebCore {
String m_clientRedirectSourceForHistory;
bool m_didCreateGlobalHistoryEntry;
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- // The application cache that the document loader is associated with (if any).
- RefPtr<ApplicationCache> m_applicationCache;
-
- // Before an application cache has finished loading, this will be the candidate application
- // group that the document loader is associated with.
- ApplicationCacheGroup* m_candidateApplicationCacheGroup;
-
- // Once the main resource has finished loading, this is the application cache it was loaded from (if any).
- RefPtr<ApplicationCache> m_mainResourceApplicationCache;
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+ friend class ApplicationCacheHost; // for substitute resource delivery
+ OwnPtr<ApplicationCacheHost> m_applicationCacheHost;
#endif
};
diff --git a/WebCore/loader/DocumentThreadableLoader.cpp b/WebCore/loader/DocumentThreadableLoader.cpp
index 0de62ce..dd5ca76 100644
--- a/WebCore/loader/DocumentThreadableLoader.cpp
+++ b/WebCore/loader/DocumentThreadableLoader.cpp
@@ -77,26 +77,26 @@ void DocumentThreadableLoader::loadResourceSynchronously(Document* document, con
client.didFinishLoading(identifier);
}
-PassRefPtr<DocumentThreadableLoader> DocumentThreadableLoader::create(Document* document, ThreadableLoaderClient* client, const ResourceRequest& request, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials, RedirectOriginCheck redirectOriginCheck)
+PassRefPtr<DocumentThreadableLoader> DocumentThreadableLoader::create(Document* document, ThreadableLoaderClient* client, const ResourceRequest& request, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials, CrossOriginRedirectPolicy crossOriginRedirectPolicy)
{
ASSERT(document);
- RefPtr<DocumentThreadableLoader> loader = adoptRef(new DocumentThreadableLoader(document, client, request, callbacksSetting, contentSniff, storedCredentials, redirectOriginCheck));
+ RefPtr<DocumentThreadableLoader> loader = adoptRef(new DocumentThreadableLoader(document, client, request, callbacksSetting, contentSniff, storedCredentials, crossOriginRedirectPolicy));
if (!loader->m_loader)
loader = 0;
return loader.release();
}
-DocumentThreadableLoader::DocumentThreadableLoader(Document* document, ThreadableLoaderClient* client, const ResourceRequest& request, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials, RedirectOriginCheck redirectOriginCheck)
+DocumentThreadableLoader::DocumentThreadableLoader(Document* document, ThreadableLoaderClient* client, const ResourceRequest& request, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials, CrossOriginRedirectPolicy crossOriginRedirectPolicy)
: m_client(client)
, m_document(document)
, m_allowStoredCredentials(storedCredentials == AllowStoredCredentials)
, m_sameOriginRequest(document->securityOrigin()->canRequest(request.url()))
- , m_checkRedirectOrigin(redirectOriginCheck == RequireSameRedirectOrigin)
+ , m_denyCrossOriginRedirect(crossOriginRedirectPolicy == DenyCrossOriginRedirect)
{
ASSERT(document);
ASSERT(client);
ASSERT(storedCredentials == AllowStoredCredentials || storedCredentials == DoNotAllowStoredCredentials);
- ASSERT(redirectOriginCheck == RequireSameRedirectOrigin || redirectOriginCheck == AllowDifferentRedirectOrigin);
+ ASSERT(crossOriginRedirectPolicy == DenyCrossOriginRedirect || crossOriginRedirectPolicy == AllowCrossOriginRedirect);
m_loader = SubresourceLoader::create(document->frame(), this, request, false, callbacksSetting == SendLoadCallbacks, contentSniff == SniffContent);
}
@@ -123,7 +123,7 @@ void DocumentThreadableLoader::willSendRequest(SubresourceLoader* loader, Resour
ASSERT_UNUSED(loader, loader == m_loader);
// FIXME: This needs to be fixed to follow the redirect correctly even for cross-domain requests.
- if (m_checkRedirectOrigin && !m_document->securityOrigin()->canRequest(request.url())) {
+ if (m_denyCrossOriginRedirect && !m_document->securityOrigin()->canRequest(request.url())) {
RefPtr<DocumentThreadableLoader> protect(this);
m_client->didFailRedirectCheck();
request = ResourceRequest();
@@ -164,7 +164,8 @@ void DocumentThreadableLoader::didFinishLoading(SubresourceLoader* loader)
void DocumentThreadableLoader::didFail(SubresourceLoader* loader, const ResourceError& error)
{
ASSERT(m_client);
- ASSERT_UNUSED(loader, loader == m_loader);
+ // m_loader may be null if we arrive here via SubresourceLoader::create in the ctor
+ ASSERT_UNUSED(loader, loader == m_loader || !m_loader);
m_client->didFail(error);
}
diff --git a/WebCore/loader/DocumentThreadableLoader.h b/WebCore/loader/DocumentThreadableLoader.h
index 079c725..465475f 100644
--- a/WebCore/loader/DocumentThreadableLoader.h
+++ b/WebCore/loader/DocumentThreadableLoader.h
@@ -45,7 +45,7 @@ namespace WebCore {
class DocumentThreadableLoader : public RefCounted<DocumentThreadableLoader>, public ThreadableLoader, private SubresourceLoaderClient {
public:
static void loadResourceSynchronously(Document*, const ResourceRequest&, ThreadableLoaderClient&, StoredCredentials);
- static PassRefPtr<DocumentThreadableLoader> create(Document*, ThreadableLoaderClient*, const ResourceRequest&, LoadCallbacks, ContentSniff, StoredCredentials, RedirectOriginCheck);
+ static PassRefPtr<DocumentThreadableLoader> create(Document*, ThreadableLoaderClient*, const ResourceRequest&, LoadCallbacks, ContentSniff, StoredCredentials, CrossOriginRedirectPolicy);
virtual ~DocumentThreadableLoader();
virtual void cancel();
@@ -58,7 +58,7 @@ namespace WebCore {
virtual void derefThreadableLoader() { deref(); }
private:
- DocumentThreadableLoader(Document*, ThreadableLoaderClient*, const ResourceRequest&, LoadCallbacks, ContentSniff, StoredCredentials, RedirectOriginCheck);
+ DocumentThreadableLoader(Document*, ThreadableLoaderClient*, const ResourceRequest&, LoadCallbacks, ContentSniff, StoredCredentials, CrossOriginRedirectPolicy);
virtual void willSendRequest(SubresourceLoader*, ResourceRequest&, const ResourceResponse& redirectResponse);
virtual void didSendData(SubresourceLoader*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent);
@@ -76,7 +76,7 @@ namespace WebCore {
Document* m_document;
bool m_allowStoredCredentials;
bool m_sameOriginRequest;
- bool m_checkRedirectOrigin;
+ bool m_denyCrossOriginRedirect;
};
} // namespace WebCore
diff --git a/WebCore/loader/EmptyClients.h b/WebCore/loader/EmptyClients.h
index f93a878..3f70c43 100644
--- a/WebCore/loader/EmptyClients.h
+++ b/WebCore/loader/EmptyClients.h
@@ -95,7 +95,7 @@ public:
virtual void setResizable(bool) { }
- virtual void addMessageToConsole(MessageSource, MessageLevel, const String&, unsigned, const String&) { }
+ virtual void addMessageToConsole(MessageSource, MessageType, MessageLevel, const String&, unsigned, const String&) { }
virtual bool canRunBeforeUnloadConfirmPanel() { return false; }
virtual bool runBeforeUnloadConfirmPanel(const String&, Frame*) { return true; }
@@ -125,7 +125,7 @@ public:
virtual void mouseDidMoveOverElement(const HitTestResult&, unsigned) { }
- virtual void setToolTip(const String&) { }
+ virtual void setToolTip(const String&, TextDirection) { }
virtual void print(Frame*) { }
@@ -141,6 +141,9 @@ public:
virtual void formStateDidChange(const Node*) { }
+ virtual void formDidFocus(const Node*) { }
+ virtual void formDidBlur(const Node*) { }
+
virtual PassOwnPtr<HTMLParserQuirks> createHTMLParserQuirks() { return 0; }
virtual bool setCursor(PlatformCursorHandle) { return false; }
@@ -148,6 +151,12 @@ public:
virtual void scrollRectIntoView(const IntRect&, const ScrollView*) const {}
virtual void requestGeolocationPermissionForFrame(Frame*, Geolocation*) {}
+
+#if USE(ACCELERATED_COMPOSITING)
+ virtual void attachRootGraphicsLayer(Frame*, GraphicsLayer*) {};
+ virtual void setNeedsOneShotDrawingSynchronization() {};
+ virtual void scheduleCompositingLayerSync() {};
+#endif
};
class EmptyFrameLoaderClient : public FrameLoaderClient {
@@ -273,8 +282,8 @@ public:
virtual bool canCachePage() const { return false; }
virtual PassRefPtr<Frame> createFrame(const KURL&, const String&, HTMLFrameOwnerElement*, const String&, bool, int, int) { return 0; }
- virtual Widget* createPlugin(const IntSize&, HTMLPlugInElement*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool) { return 0; }
- virtual Widget* createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const KURL&, const Vector<String>&, const Vector<String>&) { return 0; }
+ virtual PassRefPtr<Widget> createPlugin(const IntSize&, HTMLPlugInElement*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool) { return 0; }
+ virtual PassRefPtr<Widget> createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const KURL&, const Vector<String>&, const Vector<String>&) { return 0; }
virtual ObjectContentType objectContentType(const KURL&, const String&) { return ObjectContentType(); }
virtual String overrideMediaType() const { return String(); }
@@ -286,6 +295,12 @@ public:
virtual void registerForIconNotification(bool) { }
+#if USE(V8)
+ virtual void didCreateScriptContextForFrame() { }
+ virtual void didDestroyScriptContextForFrame() { }
+ virtual void didCreateIsolatedScriptContext() { }
+#endif
+
#if PLATFORM(MAC)
virtual NSCachedURLResponse* willCacheResponse(DocumentLoader*, unsigned long, NSCachedURLResponse* response) const { return response; }
#endif
@@ -411,6 +426,7 @@ public:
virtual void copyImageToClipboard(const HitTestResult&) { }
virtual void searchWithGoogle(const Frame*) { }
virtual void lookUpInDictionary(Frame*) { }
+ virtual bool isSpeaking() { return false; }
virtual void speak(const String&) { }
virtual void stopSpeaking() { }
@@ -458,6 +474,8 @@ public:
virtual void populateSetting(const String&, InspectorController::Setting&) { }
virtual void storeSetting(const String&, const InspectorController::Setting&) { }
virtual void removeSetting(const String&) { }
+
+ virtual void inspectorWindowObjectCleared() { }
};
}
diff --git a/WebCore/loader/FrameLoader.cpp b/WebCore/loader/FrameLoader.cpp
index af0fdad..bffe8af 100644
--- a/WebCore/loader/FrameLoader.cpp
+++ b/WebCore/loader/FrameLoader.cpp
@@ -31,7 +31,11 @@
#include "config.h"
#include "FrameLoader.h"
+#ifdef MANUAL_MERGE_REQUIRED
#if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size
+#else // MANUAL_MERGE_REQUIRED
+#include "ApplicationCacheHost.h"
+#endif // MANUAL_MERGE_REQUIRED
#include "Archive.h"
#include "ArchiveFactory.h"
#endif
@@ -56,7 +60,6 @@
#include "FrameLoaderClient.h"
#include "FrameTree.h"
#include "FrameView.h"
-#include "HTMLAnchorElement.h"
#include "HTMLAppletElement.h"
#include "HTMLFormElement.h"
#include "HTMLFrameElement.h"
@@ -73,6 +76,7 @@
#include "Page.h"
#include "PageCache.h"
#include "PageGroup.h"
+#include "PlaceholderDocument.h"
#include "PluginData.h"
#include "PluginDocument.h"
#include "ProgressTracker.h"
@@ -92,13 +96,10 @@
#include "WindowFeatures.h"
#include "XMLHttpRequest.h"
#include "XMLTokenizer.h"
+#include "XSSAuditor.h"
#include <wtf/CurrentTime.h>
#include <wtf/StdLibExtras.h>
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
-#include "ApplicationCache.h"
-#include "ApplicationCacheResource.h"
-#endif
#if ENABLE(SVG)
#include "SVGDocument.h"
@@ -126,35 +127,6 @@ using namespace SVGNames;
#endif
using namespace HTMLNames;
-typedef HashSet<String, CaseFoldingHash> URLSchemesMap;
-
-static URLSchemesMap& localSchemes()
-{
- DEFINE_STATIC_LOCAL(URLSchemesMap, localSchemes, ());
-
- if (localSchemes.isEmpty()) {
- localSchemes.add("file");
-#if PLATFORM(MAC)
- localSchemes.add("applewebdata");
-#endif
-#if PLATFORM(QT)
- localSchemes.add("qrc");
-#endif
- }
-
- return localSchemes;
-}
-
-static URLSchemesMap& noAccessSchemes()
-{
- DEFINE_STATIC_LOCAL(URLSchemesMap, noAccessSchemes, ());
-
- if (noAccessSchemes.isEmpty())
- noAccessSchemes.add("data");
-
- return noAccessSchemes;
-}
-
struct ScheduledRedirection {
enum Type { redirection, locationChange, historyNavigation, formSubmission };
@@ -252,6 +224,7 @@ bool isBackForwardLoadType(FrameLoadType type)
case FrameLoadTypeReplace:
return false;
case FrameLoadTypeBack:
+ case FrameLoadTypeBackWMLDeckNotAccessible:
case FrameLoadTypeForward:
case FrameLoadTypeIndexedBackForward:
return true;
@@ -310,9 +283,6 @@ FrameLoader::FrameLoader(Frame* frame, FrameLoaderClient* client)
#ifndef NDEBUG
, m_didDispatchDidCommitLoad(false)
#endif
-#if ENABLE(WML)
- , m_forceReloadWmlDeck(false)
-#endif
{
}
@@ -463,7 +433,7 @@ bool FrameLoader::requestFrame(HTMLFrameOwnerElement* ownerElement, const String
Frame* frame = ownerElement->contentFrame();
if (frame)
- frame->loader()->scheduleLocationChange(url.string(), m_outgoingReferrer, true, true, userGestureHint());
+ frame->loader()->scheduleLocationChange(url.string(), m_outgoingReferrer, true, true, isProcessingUserGesture());
else
frame = loadSubframe(ownerElement, url, frameName, m_outgoingReferrer);
@@ -506,7 +476,7 @@ Frame* FrameLoader::loadSubframe(HTMLFrameOwnerElement* ownerElement, const KURL
RenderObject* renderer = ownerElement->renderer();
FrameView* view = frame->view();
if (renderer && renderer->isWidget() && view)
- static_cast<RenderWidget*>(renderer)->setWidget(view);
+ toRenderWidget(renderer)->setWidget(view);
checkCallImplicitClose();
@@ -526,7 +496,7 @@ Frame* FrameLoader::loadSubframe(HTMLFrameOwnerElement* ownerElement, const KURL
void FrameLoader::submitForm(const char* action, const String& url, PassRefPtr<FormData> formData,
const String& target, const String& contentType, const String& boundary,
- bool lockHistory, bool lockBackForwardList, PassRefPtr<Event> event, PassRefPtr<FormState> formState)
+ bool lockHistory, PassRefPtr<Event> event, PassRefPtr<FormState> formState)
{
ASSERT(action);
ASSERT(strcmp(action, "GET") == 0 || strcmp(action, "POST") == 0);
@@ -598,6 +568,7 @@ void FrameLoader::submitForm(const char* action, const String& url, PassRefPtr<F
frameRequest.resourceRequest().setURL(u);
addHTTPOriginIfNeeded(frameRequest.resourceRequest(), outgoingOrigin());
+#ifdef MANUAL_MERGE_REQUIRED
// Navigation of a subframe during loading of the main frame does not create a new back/forward item.
// Strangely, we only implement this rule for form submission; time will tell if we need it for other types of navigation.
// The definition of "during load" is any time before the load event has been handled.
@@ -612,6 +583,9 @@ void FrameLoader::submitForm(const char* action, const String& url, PassRefPtr<F
}
targetFrame->loader()->scheduleFormSubmission(frameRequest, lockHistory, lockBackForwardList, event, formState);
+#else // MANUAL_MERGE_REQUIRED
+ targetFrame->loader()->scheduleFormSubmission(frameRequest, lockHistory, event, formState);
+#endif // MANUAL_MERGE_REQUIRED
}
void FrameLoader::stopLoading(bool sendUnload, DatabasePolicy databasePolicy)
@@ -780,15 +754,16 @@ bool FrameLoader::executeIfJavaScriptURL(const KURL& url, bool userGesture, bool
if (m_frame->page() && !m_frame->page()->javaScriptURLsAreAllowed())
return true;
- String script = decodeURLEscapeSequences(url.string().substring(strlen("javascript:")));
+ const int javascriptSchemeLength = sizeof("javascript:") - 1;
+
+ String script = decodeURLEscapeSequences(url.string().substring(javascriptSchemeLength));
ScriptValue result = executeScript(script, userGesture);
String scriptResult;
if (!result.getString(scriptResult))
return true;
- SecurityOrigin* currentSecurityOrigin = 0;
- currentSecurityOrigin = m_frame->document()->securityOrigin();
+ SecurityOrigin* currentSecurityOrigin = m_frame->document()->securityOrigin();
// FIXME: We should always replace the document, but doing so
// synchronously can cause crashes:
@@ -949,6 +924,8 @@ void FrameLoader::begin(const KURL& url, bool dispatch, SecurityOrigin* origin)
// Create a new document before clearing the frame, because it may need to inherit an aliased security context.
if (!m_isDisplayingInitialEmptyDocument && m_client->shouldUsePluginDocument(m_responseMIMEType))
document = PluginDocument::create(m_frame);
+ else if (!m_client->hasHTMLView())
+ document = PlaceholderDocument::create(m_frame);
else
document = DOMImplementation::createDocument(m_responseMIMEType, m_frame, m_frame->inViewSourceMode());
@@ -966,7 +943,7 @@ void FrameLoader::begin(const KURL& url, bool dispatch, SecurityOrigin* origin)
KURL ref(url);
ref.setUser(String());
ref.setPass(String());
- ref.setRef(String());
+ ref.removeFragmentIdentifier();
m_outgoingReferrer = ref.string();
m_URL = url;
@@ -1007,8 +984,8 @@ void FrameLoader::begin(const KURL& url, bool dispatch, SecurityOrigin* origin)
restoreDocumentState();
document->implicitOpen();
-
- if (m_frame->view())
+
+ if (m_frame->view() && m_client->hasHTMLView())
m_frame->view()->setContentsSize(IntSize());
}
@@ -1170,6 +1147,12 @@ void FrameLoader::startIconLoader()
}
}
+ // People who want to avoid loading images generally want to avoid loading all images.
+ // Now that we've accounted for URL mapping, avoid starting the network load if images aren't set to display automatically.
+ Settings* settings = m_frame->settings();
+ if (settings && !settings->loadsImagesAutomatically())
+ return;
+
// This is either a reload or the icon database said "yes, load the icon", so kick off the load!
if (!m_iconLoader)
m_iconLoader.set(IconLoader::create(m_frame).release());
@@ -1213,6 +1196,7 @@ void FrameLoader::restoreDocumentState()
case FrameLoadTypeReplace:
break;
case FrameLoadTypeBack:
+ case FrameLoadTypeBackWMLDeckNotAccessible:
case FrameLoadTypeForward:
case FrameLoadTypeIndexedBackForward:
case FrameLoadTypeRedirectWithLockedBackForwardList:
@@ -1233,16 +1217,16 @@ void FrameLoader::gotoAnchor()
// OTOH If CSS target was set previously, we want to set it to 0, recalc
// and possibly repaint because :target pseudo class may have been
// set (see bug 11321).
- if (!m_URL.hasRef() && !m_frame->document()->cssTarget())
+ if (!m_URL.hasFragmentIdentifier() && !m_frame->document()->cssTarget())
return;
- String ref = m_URL.ref();
- if (gotoAnchor(ref))
+ String fragmentIdentifier = m_URL.fragmentIdentifier();
+ if (gotoAnchor(fragmentIdentifier))
return;
// Try again after decoding the ref, based on the document's encoding.
if (m_decoder)
- gotoAnchor(decodeURLEscapeSequences(ref, m_decoder->encoding()));
+ gotoAnchor(decodeURLEscapeSequences(fragmentIdentifier, m_decoder->encoding()));
}
void FrameLoader::finishedParsing()
@@ -1378,6 +1362,20 @@ void FrameLoader::scheduleHTTPRedirection(double delay, const String& url)
scheduleRedirection(new ScheduledRedirection(delay, url, true, delay <= 1, false, false));
}
+static bool mustLockBackForwardList(Frame* targetFrame)
+{
+ // Navigation of a subframe during loading of an ancestor frame does not create a new back/forward item.
+ // The definition of "during load" is any time before all handlers for the load event have been run.
+ // See https://bugs.webkit.org/show_bug.cgi?id=14957 for the original motivation for this.
+
+ for (Frame* ancestor = targetFrame->tree()->parent(); ancestor; ancestor = ancestor->tree()->parent()) {
+ Document* document = ancestor->document();
+ if (!ancestor->loader()->isComplete() || document && document->processingLoadEvent())
+ return true;
+ }
+ return false;
+}
+
void FrameLoader::scheduleLocationChange(const String& url, const String& referrer, bool lockHistory, bool lockBackForwardList, bool wasUserGesture)
{
if (!m_frame->page())
@@ -1386,10 +1384,12 @@ void FrameLoader::scheduleLocationChange(const String& url, const String& referr
if (url.isEmpty())
return;
+ lockBackForwardList = lockBackForwardList || mustLockBackForwardList(m_frame);
+
// If the URL we're going to navigate to is the same as the current one, except for the
// fragment part, we don't need to schedule the location change.
KURL parsedURL(url);
- if (parsedURL.hasRef() && equalIgnoringRef(m_URL, parsedURL)) {
+ if (parsedURL.hasFragmentIdentifier() && equalIgnoringFragmentIdentifier(m_URL, parsedURL)) {
changeLocation(completeURL(url), referrer, lockHistory, lockBackForwardList, wasUserGesture);
return;
}
@@ -1402,7 +1402,7 @@ void FrameLoader::scheduleLocationChange(const String& url, const String& referr
}
void FrameLoader::scheduleFormSubmission(const FrameLoadRequest& frameRequest,
- bool lockHistory, bool lockBackForwardList, PassRefPtr<Event> event, PassRefPtr<FormState> formState)
+ bool lockHistory, PassRefPtr<Event> event, PassRefPtr<FormState> formState)
{
ASSERT(m_frame->page());
ASSERT(!frameRequest.isEmpty());
@@ -1414,7 +1414,7 @@ void FrameLoader::scheduleFormSubmission(const FrameLoadRequest& frameRequest,
// This may happen when a frame changes the location of another frame.
bool duringLoad = !m_committedFirstRealDocumentLoad;
- scheduleRedirection(new ScheduledRedirection(frameRequest, lockHistory, lockBackForwardList, event, formState, duringLoad));
+ scheduleRedirection(new ScheduledRedirection(frameRequest, lockHistory, mustLockBackForwardList(m_frame), event, formState, duringLoad));
}
void FrameLoader::scheduleRefresh(bool wasUserGesture)
@@ -1632,6 +1632,7 @@ bool FrameLoader::gotoAnchor(const String& name)
if (!anchorNode && !(name.isEmpty() || equalIgnoringCase(name, "top")))
return false;
+#ifdef MANUAL_MERGE_REQUIRED
// We need to update the layout before scrolling, otherwise we could
// really mess things up if an anchor scroll comes at a bad moment.
m_frame->document()->updateStyleIfNeeded();
@@ -1660,6 +1661,10 @@ bool FrameLoader::gotoAnchor(const String& name)
#ifdef ANDROID_SCROLL_ON_GOTO_ANCHOR
android::WebFrame::getWebFrame(m_frame)->setUserInitiatedClick(false);
#endif
+#else // MANUAL_MERGE_REQUIRED
+ if (FrameView* view = m_frame->view())
+ view->maintainScrollPositionAtAnchor(anchorNode ? static_cast<Node*>(anchorNode) : m_frame->document());
+#endif // MANUAL_MERGE_REQUIRED
return true;
}
@@ -1669,6 +1674,11 @@ bool FrameLoader::requestObject(RenderPart* renderer, const String& url, const A
{
if (url.isEmpty() && mimeType.isEmpty())
return false;
+
+ if (!m_frame->script()->xssAuditor()->canLoadObject(url)) {
+ // It is unsafe to honor the request for this object.
+ return false;
+ }
KURL completedURL;
if (!url.isEmpty())
@@ -1733,7 +1743,7 @@ static HTMLPlugInElement* toPlugInElement(Node* node)
bool FrameLoader::loadPlugin(RenderPart* renderer, const KURL& url, const String& mimeType,
const Vector<String>& paramNames, const Vector<String>& paramValues, bool useFallback)
{
- Widget* widget = 0;
+ RefPtr<Widget> widget;
if (renderer && !useFallback) {
HTMLPlugInElement* element = toPlugInElement(renderer->node());
@@ -1819,7 +1829,7 @@ void FrameLoader::provisionalLoadStarted()
m_client->provisionalLoadStarted();
}
-bool FrameLoader::userGestureHint()
+bool FrameLoader::isProcessingUserGesture()
{
Frame* frame = m_frame->tree()->top();
if (!frame->script()->isEnabled())
@@ -1848,6 +1858,17 @@ void FrameLoader::addData(const char* bytes, int length)
write(bytes, length);
}
+#if ENABLE(WML)
+static inline bool frameContainsWMLContent(Frame* frame)
+{
+ Document* document = frame ? frame->document() : 0;
+ if (!document)
+ return false;
+
+ return document->containsWMLContent() || document->isWMLDocument();
+}
+#endif
+
bool FrameLoader::canCachePageContainingThisFrame()
{
return m_documentLoader
@@ -1873,8 +1894,10 @@ bool FrameLoader::canCachePageContainingThisFrame()
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
// FIXME: We should investigating caching frames that have an associated
// application cache. <rdar://problem/5917899> tracks that work.
- && !m_documentLoader->applicationCache()
- && !m_documentLoader->candidateApplicationCacheGroup()
+ && m_documentLoader->applicationCacheHost()->canCacheInPageCache()
+#endif
+#if ENABLE(WML)
+ && !frameContainsWMLContent(m_frame)
#endif
&& m_client->canCachePage()
;
@@ -2021,10 +2044,8 @@ bool FrameLoader::logCanCacheFrameDecision(int indentLevel)
if (!m_frame->document()->canSuspendActiveDOMObjects())
{ PCLOG(" -The document cannot suspect its active DOM Objects"); cannotCache = true; }
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- if (m_documentLoader->applicationCache())
- { PCLOG(" -The DocumentLoader has an active application cache"); cannotCache = true; }
- if (m_documentLoader->candidateApplicationCacheGroup())
- { PCLOG(" -The DocumentLoader has a candidateApplicationCacheGroup"); cannotCache = true; }
+ if (!m_documentLoader->applicationCacheHost()->canCacheInPageCache())
+ { PCLOG(" -The DocumentLoader uses an application cache"); cannotCache = true; }
#endif
if (!m_client->canCachePage())
{ PCLOG(" -The client says this frame cannot be cached"); cannotCache = true; }
@@ -2056,10 +2077,39 @@ void FrameLoader::setFirstPartyForCookies(const KURL& url)
child->loader()->setFirstPartyForCookies(url);
}
+class HashChangeEventTask : public ScriptExecutionContext::Task {
+public:
+ static PassRefPtr<HashChangeEventTask> create(PassRefPtr<Document> document)
+ {
+ return adoptRef(new HashChangeEventTask(document));
+ }
+
+ virtual void performTask(ScriptExecutionContext* context)
+ {
+ ASSERT_UNUSED(context, context->isDocument());
+ m_document->dispatchWindowEvent(eventNames().hashchangeEvent, false, false);
+ }
+
+private:
+ HashChangeEventTask(PassRefPtr<Document> document)
+ : m_document(document)
+ {
+ ASSERT(m_document);
+ }
+
+ RefPtr<Document> m_document;
+};
+
// This does the same kind of work that didOpenURL does, except it relies on the fact
// that a higher level already checked that the URLs match and the scrolling is the right thing to do.
void FrameLoader::scrollToAnchor(const KURL& url)
{
+ ASSERT(equalIgnoringFragmentIdentifier(url, m_URL));
+ if (equalIgnoringFragmentIdentifier(url, m_URL) && !equalIgnoringNullity(url.fragmentIdentifier(), m_URL.fragmentIdentifier())) {
+ Document* currentDocument = frame()->document();
+ currentDocument->postTask(HashChangeEventTask::create(currentDocument));
+ }
+
m_URL = url;
updateHistoryForAnchorScroll();
@@ -2162,7 +2212,7 @@ void FrameLoader::completed()
if (Frame* parent = m_frame->tree()->parent())
parent->loader()->checkCompleted();
if (m_frame->view())
- m_frame->view()->setLockedToAnchor(false);
+ m_frame->view()->maintainScrollPositionAtAnchor(0);
}
void FrameLoader::started()
@@ -2224,7 +2274,7 @@ void FrameLoader::loadFrameRequest(const FrameLoadRequest& request, bool lockHis
referrer = m_outgoingReferrer;
ASSERT(frame()->document());
- if (shouldTreatURLAsLocal(url.string()) && !isFeedWithNestedProtocolInHTTPFamily(url)) {
+ if (SecurityOrigin::shouldTreatURLAsLocal(url.string()) && !isFeedWithNestedProtocolInHTTPFamily(url)) {
if (!canLoad(url, String(), frame()->document()) && !canLoad(url, referrer)) {
FrameLoader::reportLocalLoadFailed(m_frame, url.string());
return;
@@ -2439,7 +2489,7 @@ bool FrameLoader::canLoad(const KURL& url, const String& referrer, const Documen
bool FrameLoader::canLoad(const KURL& url, const String& referrer, const SecurityOrigin* securityOrigin)
{
// We can always load any URL that isn't considered local (e.g. http URLs).
- if (!shouldTreatURLAsLocal(url.string()))
+ if (!SecurityOrigin::shouldTreatURLAsLocal(url.string()))
return true;
// If we were provided a document, we let its local file policy dictate the result,
@@ -2447,7 +2497,7 @@ bool FrameLoader::canLoad(const KURL& url, const String& referrer, const Securit
if (securityOrigin)
return securityOrigin->canLoadLocalResources();
if (!referrer.isEmpty())
- return shouldTreatURLAsLocal(referrer);
+ return SecurityOrigin::shouldTreatURLAsLocal(referrer);
return false;
}
@@ -2457,7 +2507,7 @@ void FrameLoader::reportLocalLoadFailed(Frame* frame, const String& url)
if (!frame)
return;
- frame->domWindow()->console()->addMessage(JSMessageSource, ErrorMessageLevel, "Not allowed to load local resource: " + url, 0, String());
+ frame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, "Not allowed to load local resource: " + url, 0, String());
}
bool FrameLoader::shouldHideReferrer(const KURL& url, const String& referrer)
@@ -2674,7 +2724,7 @@ bool FrameLoader::shouldAllowNavigation(Frame* targetFrame) const
targetDocument->url().string().utf8().data(), activeDocument->url().string().utf8().data());
// FIXME: should we print to the console of the activeFrame as well?
- targetFrame->domWindow()->console()->addMessage(JSMessageSource, ErrorMessageLevel, message, 1, String());
+ targetFrame->domWindow()->console()->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, message, 1, String());
}
return false;
@@ -2933,6 +2983,7 @@ void FrameLoader::transitionToCommitted(PassRefPtr<CachedPage> cachedPage)
switch (m_loadType) {
case FrameLoadTypeForward:
case FrameLoadTypeBack:
+ case FrameLoadTypeBackWMLDeckNotAccessible:
case FrameLoadTypeIndexedBackForward:
if (Page* page = m_frame->page())
if (page->backForwardList()) {
@@ -2990,10 +3041,12 @@ void FrameLoader::transitionToCommitted(PassRefPtr<CachedPage> cachedPage)
m_committedFirstRealDocumentLoad = true;
- // For non-cached HTML pages, these methods are called in FrameLoader::begin.
- if (cachedPage || !m_client->hasHTMLView()) {
- dispatchDidCommitLoad();
-
+ if (!m_client->hasHTMLView())
+ receivedFirstData();
+ else if (cachedPage) {
+ // For non-cached HTML pages, these methods are called in receivedFirstData().
+ dispatchDidCommitLoad();
+
// If we have a title let the WebView know about it.
if (!ptitle.isNull())
m_client->dispatchDidReceiveTitle(ptitle);
@@ -3028,27 +3081,20 @@ void FrameLoader::clientRedirected(const KURL& url, double seconds, double fireD
m_quickRedirectComing = lockBackForwardList && m_documentLoader && !m_isExecutingJavaScriptFormAction;
}
-#if ENABLE(WML)
-void FrameLoader::setForceReloadWmlDeck(bool reload)
-{
- m_forceReloadWmlDeck = reload;
-}
-#endif
-
bool FrameLoader::shouldReload(const KURL& currentURL, const KURL& destinationURL)
{
#if ENABLE(WML)
- // As for WML deck, sometimes it's supposed to be reloaded even if the same URL with fragment
- if (m_forceReloadWmlDeck)
+ // All WML decks are supposed to be reloaded, even within the same URL fragment
+ if (frameContainsWMLContent(m_frame))
return true;
#endif
// This function implements the rule: "Don't reload if navigating by fragment within
// the same URL, but do reload if going to a new URL or to the same URL with no
// fragment identifier at all."
- if (!destinationURL.hasRef())
+ if (!destinationURL.hasFragmentIdentifier())
return true;
- return !equalIgnoringRef(currentURL, destinationURL);
+ return !equalIgnoringFragmentIdentifier(currentURL, destinationURL);
}
void FrameLoader::closeOldDataSources()
@@ -3083,6 +3129,7 @@ void FrameLoader::open(CachedPage& cachedPage)
}
open(*cachedPage.cachedMainFrame());
+ cachedPage.restore(m_frame->page());
checkCompleted();
}
@@ -3753,30 +3800,11 @@ unsigned long FrameLoader::loadResourceSynchronously(const ResourceRequest& requ
ASSERT(!newRequest.isNull());
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- ApplicationCacheResource* resource;
- if (documentLoader()->shouldLoadResourceFromApplicationCache(newRequest, resource)) {
- if (resource) {
- response = resource->response();
- data.append(resource->data()->data(), resource->data()->size());
- } else
- error = cannotShowURLError(newRequest);
- } else {
+ if (!documentLoader()->applicationCacheHost()->maybeLoadSynchronously(newRequest, error, response, data)) {
#endif
ResourceHandle::loadResourceSynchronously(newRequest, storedCredentials, error, response, data, m_frame);
-
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- // If normal loading results in a redirect to a resource with another origin (indicative of a captive portal), or a 4xx or 5xx status code or equivalent,
- // or if there were network errors (but not if the user canceled the download), then instead get, from the cache, the resource of the fallback entry
- // corresponding to the matched namespace.
- if ((!error.isNull() && !error.isCancellation())
- || response.httpStatusCode() / 100 == 4 || response.httpStatusCode() / 100 == 5
- || !protocolHostAndPortAreEqual(newRequest.url(), response.url())) {
- if (documentLoader()->getApplicationCacheFallbackResource(newRequest, resource)) {
- response = resource->response();
- data.clear();
- data.append(resource->data()->data(), resource->data()->size());
- }
- }
+ documentLoader()->applicationCacheHost()->maybeLoadFallbackSynchronously(newRequest, error, response, data);
}
#endif
}
@@ -4505,7 +4533,8 @@ void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType)
bool shouldScroll = !formData && !(m_currentHistoryItem && m_currentHistoryItem->formData()) && urlsMatchItem(item);
#if ENABLE(WML)
- if (m_frame->document()->isWMLDocument())
+ // All WML decks should go through the real load mechanism, not the scroll-to-anchor code
+ if (frameContainsWMLContent(m_frame))
shouldScroll = false;
#endif
@@ -4591,7 +4620,7 @@ void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType)
// have the item vanish when we try to use it in the ensuing nav. This should be
// extremely rare, but in that case the user will get an error on the navigation.
- if (ResourceHandle::willLoadFromCache(request))
+ if (ResourceHandle::willLoadFromCache(request, m_frame))
action = NavigationAction(itemURL, loadType, false);
else {
request.setCachePolicy(ReloadIgnoringCacheData);
@@ -4604,6 +4633,7 @@ void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType)
request.setCachePolicy(ReloadIgnoringCacheData);
break;
case FrameLoadTypeBack:
+ case FrameLoadTypeBackWMLDeckNotAccessible:
case FrameLoadTypeForward:
case FrameLoadTypeIndexedBackForward:
if (itemURL.protocol() != "https")
@@ -4632,7 +4662,7 @@ void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType)
bool FrameLoader::urlsMatchItem(HistoryItem* item) const
{
const KURL& currentURL = documentLoader()->url();
- if (!equalIgnoringRef(currentURL, item->url()))
+ if (!equalIgnoringFragmentIdentifier(currentURL, item->url()))
return false;
const HistoryItemVector& childItems = item->children();
@@ -5130,7 +5160,7 @@ void FrameLoader::dispatchWindowObjectAvailable()
}
}
-Widget* FrameLoader::createJavaAppletWidget(const IntSize& size, HTMLAppletElement* element, const HashMap<String, String>& args)
+PassRefPtr<Widget> FrameLoader::createJavaAppletWidget(const IntSize& size, HTMLAppletElement* element, const HashMap<String, String>& args)
{
String baseURLString;
String codeBaseURLString;
@@ -5158,7 +5188,7 @@ Widget* FrameLoader::createJavaAppletWidget(const IntSize& size, HTMLAppletEleme
baseURLString = m_frame->document()->baseURL().string();
KURL baseURL = completeURL(baseURLString);
- Widget* widget = m_client->createJavaAppletWidget(size, element, baseURL, paramNames, paramValues);
+ RefPtr<Widget> widget = m_client->createJavaAppletWidget(size, element, baseURL, paramNames, paramValues);
if (!widget)
return 0;
@@ -5170,8 +5200,7 @@ void FrameLoader::didChangeTitle(DocumentLoader* loader)
{
m_client->didChangeTitle(loader);
- // The title doesn't get communicated to the WebView until we are committed.
- if (loader->isCommitted()) {
+ if (loader == m_documentLoader) {
// Must update the entries in the back-forward list too.
if (m_currentHistoryItem)
m_currentHistoryItem->setTitle(loader->title());
@@ -5182,59 +5211,6 @@ void FrameLoader::didChangeTitle(DocumentLoader* loader)
}
}
-void FrameLoader::registerURLSchemeAsLocal(const String& scheme)
-{
- localSchemes().add(scheme);
-}
-
-bool FrameLoader::shouldTreatURLAsLocal(const String& url)
-{
- // This avoids an allocation of another String and the HashSet contains()
- // call for the file: and http: schemes.
- if (url.length() >= 5) {
- const UChar* s = url.characters();
- if (s[0] == 'h' && s[1] == 't' && s[2] == 't' && s[3] == 'p' && s[4] == ':')
- return false;
- if (s[0] == 'f' && s[1] == 'i' && s[2] == 'l' && s[3] == 'e' && s[4] == ':')
- return true;
- }
-
- int loc = url.find(':');
- if (loc == -1)
- return false;
-
- String scheme = url.left(loc);
- return localSchemes().contains(scheme);
-}
-
-bool FrameLoader::shouldTreatURLSchemeAsLocal(const String& scheme)
-{
- // This avoids an allocation of another String and the HashSet contains()
- // call for the file: and http: schemes.
- if (scheme.length() == 4) {
- const UChar* s = scheme.characters();
- if (s[0] == 'h' && s[1] == 't' && s[2] == 't' && s[3] == 'p')
- return false;
- if (s[0] == 'f' && s[1] == 'i' && s[2] == 'l' && s[3] == 'e')
- return true;
- }
-
- if (scheme.isEmpty())
- return false;
-
- return localSchemes().contains(scheme);
-}
-
-void FrameLoader::registerURLSchemeAsNoAccess(const String& scheme)
-{
- noAccessSchemes().add(scheme);
-}
-
-bool FrameLoader::shouldTreatURLSchemeAsNoAccess(const String& scheme)
-{
- return noAccessSchemes().contains(scheme);
-}
-
void FrameLoader::dispatchDidCommitLoad()
{
if (m_creatingInitialEmptyDocument)
diff --git a/WebCore/loader/FrameLoader.h b/WebCore/loader/FrameLoader.h
index 6a63382..5a8ee91 100644
--- a/WebCore/loader/FrameLoader.h
+++ b/WebCore/loader/FrameLoader.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
- * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -113,7 +113,7 @@ namespace WebCore {
void* m_argument;
};
- class FrameLoader : Noncopyable {
+ class FrameLoader : public Noncopyable {
public:
FrameLoader(Frame*, FrameLoaderClient*);
~FrameLoader();
@@ -241,10 +241,6 @@ namespace WebCore {
void didFirstVisuallyNonEmptyLayout();
-#if ENABLE(WML)
- void setForceReloadWmlDeck(bool);
-#endif
-
void loadedResourceFromMemoryCache(const CachedResource*);
void tellClientAboutPastMemoryCacheLoads();
@@ -266,7 +262,7 @@ namespace WebCore {
void submitForm(const char* action, const String& url,
PassRefPtr<FormData>, const String& target, const String& contentType, const String& boundary,
- bool lockHistory, bool lockBackForwardList, PassRefPtr<Event>, PassRefPtr<FormState>);
+ bool lockHistory, PassRefPtr<Event>, PassRefPtr<FormState>);
void stop();
void stopLoading(bool sendUnload, DatabasePolicy = DatabasePolicyStop);
@@ -310,7 +306,7 @@ namespace WebCore {
void handledOnloadEvents();
String userAgent(const KURL&) const;
- Widget* createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const HashMap<String, String>& args);
+ PassRefPtr<Widget> createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const HashMap<String, String>& args);
void dispatchWindowObjectAvailable();
void dispatchDocumentElementAvailable();
@@ -321,7 +317,7 @@ namespace WebCore {
bool openedByDOM() const;
void setOpenedByDOM();
- bool userGestureHint();
+ bool isProcessingUserGesture();
void resetMultipleFormSubmissionProtection();
@@ -370,13 +366,6 @@ namespace WebCore {
static bool restrictAccessToLocal();
static bool allowSubstituteDataAccessToLocal();
- static void registerURLSchemeAsLocal(const String&);
- static bool shouldTreatURLAsLocal(const String&);
- static bool shouldTreatURLSchemeAsLocal(const String&);
-
- static void registerURLSchemeAsNoAccess(const String&);
- static bool shouldTreatURLSchemeAsNoAccess(const String&);
-
bool committingFirstRealLoad() const { return !m_creatingInitialEmptyDocument && !m_committedFirstRealDocumentLoad; }
void iconLoadDecisionAvailable();
@@ -504,7 +493,7 @@ namespace WebCore {
void dispatchDidFinishLoading(DocumentLoader*, unsigned long identifier);
static bool isLocationChange(const ScheduledRedirection&);
- void scheduleFormSubmission(const FrameLoadRequest&, bool lockHistory, bool lockBackForwardList, PassRefPtr<Event>, PassRefPtr<FormState>);
+ void scheduleFormSubmission(const FrameLoadRequest&, bool lockHistory, PassRefPtr<Event>, PassRefPtr<FormState>);
void loadWithDocumentLoader(DocumentLoader*, FrameLoadType, PassRefPtr<FormState>); // Calls continueLoadAfterNavigationPolicy
void load(DocumentLoader*); // Calls loadWithDocumentLoader
@@ -637,10 +626,6 @@ namespace WebCore {
#ifndef NDEBUG
bool m_didDispatchDidCommitLoad;
#endif
-
-#if ENABLE(WML)
- bool m_forceReloadWmlDeck;
-#endif
};
} // namespace WebCore
diff --git a/WebCore/loader/FrameLoaderClient.h b/WebCore/loader/FrameLoaderClient.h
index e64dee9..db38f01 100644
--- a/WebCore/loader/FrameLoaderClient.h
+++ b/WebCore/loader/FrameLoaderClient.h
@@ -59,6 +59,7 @@ namespace WebCore {
class IntSize;
class KURL;
class NavigationAction;
+ class PluginView;
class ResourceError;
class ResourceHandle;
class ResourceLoader;
@@ -209,10 +210,12 @@ namespace WebCore {
virtual PassRefPtr<Frame> createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement,
const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight) = 0;
- virtual Widget* createPlugin(const IntSize&, HTMLPlugInElement*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool loadManually) = 0;
+ virtual PassRefPtr<Widget> createPlugin(const IntSize&, HTMLPlugInElement*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool loadManually) = 0;
virtual void redirectDataToPlugin(Widget* pluginWidget) = 0;
-
- virtual Widget* createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const KURL& baseURL, const Vector<String>& paramNames, const Vector<String>& paramValues) = 0;
+
+ virtual PassRefPtr<Widget> createJavaAppletWidget(const IntSize&, HTMLAppletElement*, const KURL& baseURL, const Vector<String>& paramNames, const Vector<String>& paramValues) = 0;
+
+ virtual void dispatchDidFailToStartPlugin(const PluginView*) const { }
virtual ObjectContentType objectContentType(const KURL& url, const String& mimeType) = 0;
virtual String overrideMediaType() const = 0;
@@ -220,7 +223,13 @@ namespace WebCore {
virtual void windowObjectCleared() = 0;
virtual void documentElementAvailable() = 0;
virtual void didPerformFirstNavigation() const = 0; // "Navigation" here means a transition from one page to another that ends up in the back/forward list.
-
+
+#if USE(V8)
+ virtual void didCreateScriptContextForFrame() = 0;
+ virtual void didDestroyScriptContextForFrame() = 0;
+ virtual void didCreateIsolatedScriptContext() = 0;
+#endif
+
virtual void registerForIconNotification(bool listen = true) = 0;
#ifdef ANDROID_APPLE_TOUCH_ICON
virtual void dispatchDidReceiveTouchIconURL(const String& url) = 0;
diff --git a/WebCore/loader/FrameLoaderTypes.h b/WebCore/loader/FrameLoaderTypes.h
index c264b47..940bb7f 100644
--- a/WebCore/loader/FrameLoaderTypes.h
+++ b/WebCore/loader/FrameLoaderTypes.h
@@ -45,16 +45,19 @@ namespace WebCore {
PolicyIgnore,
};
+ // NOTE: Keep in sync with WebKit/mac/WebView/WebFramePrivate.h and WebKit/win/Interfaces/IWebFramePrivate.idl
enum FrameLoadType {
FrameLoadTypeStandard,
FrameLoadTypeBack,
FrameLoadTypeForward,
FrameLoadTypeIndexedBackForward, // a multi-item hop in the backforward list
FrameLoadTypeReload,
- FrameLoadTypeSame, // user loads same URL again (but not reload button)
+ // Skipped value: 'FrameLoadTypeReloadAllowingStaleData', still present in mac/win public API. Ready to be reused
+ FrameLoadTypeSame = FrameLoadTypeReload + 2, // user loads same URL again (but not reload button)
FrameLoadTypeRedirectWithLockedBackForwardList, // FIXME: Merge "lockBackForwardList", "lockHistory", "quickRedirect" and "clientRedirect" into a single concept of redirect.
FrameLoadTypeReplace,
- FrameLoadTypeReloadFromOrigin
+ FrameLoadTypeReloadFromOrigin,
+ FrameLoadTypeBackWMLDeckNotAccessible
};
enum NavigationType {
diff --git a/WebCore/loader/MainResourceLoader.cpp b/WebCore/loader/MainResourceLoader.cpp
index 39e5b90..6c843e9 100644
--- a/WebCore/loader/MainResourceLoader.cpp
+++ b/WebCore/loader/MainResourceLoader.cpp
@@ -30,6 +30,7 @@
#include "config.h"
#include "MainResourceLoader.h"
+#include "ApplicationCacheHost.h"
#include "DocumentLoader.h"
#include "FormState.h"
#include "Frame.h"
@@ -41,12 +42,6 @@
#include "ResourceHandle.h"
#include "Settings.h"
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
-#include "ApplicationCache.h"
-#include "ApplicationCacheGroup.h"
-#include "ApplicationCacheResource.h"
-#endif
-
// FIXME: More that is in common with SubresourceLoader should move up into ResourceLoader.
namespace WebCore {
@@ -283,15 +278,8 @@ void MainResourceLoader::continueAfterContentPolicy(PolicyAction policy)
void MainResourceLoader::didReceiveResponse(const ResourceResponse& r)
{
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- if (r.httpStatusCode() / 100 == 4 || r.httpStatusCode() / 100 == 5) {
- ASSERT(!m_applicationCache);
- if (m_frame->settings() && m_frame->settings()->offlineWebApplicationCacheEnabled()) {
- m_applicationCache = ApplicationCacheGroup::fallbackCacheForMainRequest(request(), documentLoader());
-
- if (scheduleLoadFallbackResourceFromApplicationCache(m_applicationCache.get()))
- return;
- }
- }
+ if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForMainResponse(request(), r))
+ return;
#endif
HTTPHeaderMap::const_iterator it = r.httpHeaderFields().find(AtomicString("x-frame-options"));
@@ -353,6 +341,10 @@ void MainResourceLoader::didReceiveData(const char* data, int length, long long
ASSERT(!defersLoading());
#endif
+ #if ENABLE(OFFLINE_WEB_APPLICATIONS)
+ documentLoader()->applicationCacheHost()->mainResourceDataReceived(data, length, lengthReceived, allAtOnce);
+#endif
+
// The additional processing can do anything including possibly removing the last
// reference to this object; one example of this is 3266216.
RefPtr<MainResourceLoader> protect(this);
@@ -380,27 +372,15 @@ void MainResourceLoader::didFinishLoading()
ResourceLoader::didFinishLoading();
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- ApplicationCacheGroup* group = dl->candidateApplicationCacheGroup();
- if (!group && dl->applicationCache() && !dl->mainResourceApplicationCache())
- group = dl->applicationCache()->group();
-
- if (group)
- group->finishedLoadingMainResource(dl.get());
+ dl->applicationCacheHost()->finishedLoadingMainResource();
#endif
}
void MainResourceLoader::didFail(const ResourceError& error)
{
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- if (!error.isCancellation()) {
- ASSERT(!m_applicationCache);
- if (m_frame->settings() && m_frame->settings()->offlineWebApplicationCacheEnabled()) {
- m_applicationCache = ApplicationCacheGroup::fallbackCacheForMainRequest(request(), documentLoader());
-
- if (scheduleLoadFallbackResourceFromApplicationCache(m_applicationCache.get()))
- return;
- }
- }
+ if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForMainError(request(), error))
+ return;
#endif
// There is a bug in CFNetwork where callbacks can be dispatched even when loads are deferred.
@@ -495,27 +475,15 @@ bool MainResourceLoader::load(const ResourceRequest& r, const SubstituteData& su
m_substituteData = substituteData;
+ ResourceRequest request(r);
+
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- // Check if this request should be loaded from the application cache
- if (!m_substituteData.isValid() && frameLoader()->frame()->settings() && frameLoader()->frame()->settings()->offlineWebApplicationCacheEnabled()) {
- ASSERT(!m_applicationCache);
-
- m_applicationCache = ApplicationCacheGroup::cacheForMainRequest(r, m_documentLoader.get());
-
- if (m_applicationCache) {
- // Get the resource from the application cache. By definition, cacheForMainRequest() returns a cache that contains the resource.
- ApplicationCacheResource* resource = m_applicationCache->resourceForRequest(r);
- m_substituteData = SubstituteData(resource->data(),
- resource->response().mimeType(),
- resource->response().textEncodingName(), KURL());
- }
- }
+ documentLoader()->applicationCacheHost()->maybeLoadMainResource(request, m_substituteData);
#endif
- ResourceRequest request(r);
bool defer = defersLoading();
if (defer) {
- bool shouldLoadEmpty = shouldLoadAsEmptyDocument(r.url());
+ bool shouldLoadEmpty = shouldLoadAsEmptyDocument(request.url());
if (shouldLoadEmpty)
defer = false;
}
diff --git a/WebCore/loader/MainResourceLoader.h b/WebCore/loader/MainResourceLoader.h
index d9ce2f9..d3f411b 100644
--- a/WebCore/loader/MainResourceLoader.h
+++ b/WebCore/loader/MainResourceLoader.h
@@ -39,9 +39,6 @@
namespace WebCore {
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- class ApplicationCache;
-#endif
class FormState;
struct ResourceRequest;
@@ -71,10 +68,6 @@ namespace WebCore {
bool isLoadingMultipartContent() const { return m_loadingMultipartContent; }
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- ApplicationCache* applicationCache() const { return m_applicationCache.get(); }
-#endif
-
private:
MainResourceLoader(Frame*);
@@ -105,11 +98,6 @@ namespace WebCore {
MainResourceLoaderTimer m_dataLoadTimer;
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- // The application cache that the main resource was loaded from (if any).
- RefPtr<ApplicationCache> m_applicationCache;
-#endif
-
bool m_loadingMultipartContent;
bool m_waitingForContentPolicy;
};
diff --git a/WebCore/loader/PlaceholderDocument.cpp b/WebCore/loader/PlaceholderDocument.cpp
new file mode 100644
index 0000000..e071aa8
--- /dev/null
+++ b/WebCore/loader/PlaceholderDocument.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "PlaceholderDocument.h"
+
+#include "CSSStyleSelector.h"
+#include "StyleSheetList.h"
+
+namespace WebCore {
+
+void PlaceholderDocument::attach()
+{
+ ASSERT(!attached());
+
+ if (!styleSelector()) {
+ RefPtr<StyleSheetList> styleSheetList = StyleSheetList::create(this);
+ setStyleSelector(new CSSStyleSelector(this, userStyleSheet(), styleSheetList.get(), 0, true, false));
+ }
+
+ // Skipping Document::attach().
+ ContainerNode::attach();
+}
+
+} // namespace WebCore
diff --git a/WebCore/loader/PlaceholderDocument.h b/WebCore/loader/PlaceholderDocument.h
new file mode 100644
index 0000000..c542370
--- /dev/null
+++ b/WebCore/loader/PlaceholderDocument.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef PlaceholderDocument_h
+#define PlaceholderDocument_h
+
+#include "Document.h"
+
+namespace WebCore {
+
+class PlaceholderDocument : public Document {
+public:
+ static PassRefPtr<PlaceholderDocument> create(Frame* frame)
+ {
+ return new PlaceholderDocument(frame);
+ }
+
+ virtual void attach();
+
+private:
+ PlaceholderDocument(Frame* frame) : Document(frame, false) { }
+};
+
+} // namespace WebCore
+
+#endif // PlaceholderDocument_h
diff --git a/WebCore/loader/PluginDocument.cpp b/WebCore/loader/PluginDocument.cpp
index 373126f..3500c98 100644
--- a/WebCore/loader/PluginDocument.cpp
+++ b/WebCore/loader/PluginDocument.cpp
@@ -106,12 +106,12 @@ bool PluginTokenizer::writeRawData(const char*, int)
Settings* settings = frame->settings();
if (settings && settings->arePluginsEnabled()) {
m_doc->updateLayout();
-
- if (RenderWidget* renderer = static_cast<RenderWidget*>(m_embedElement->renderer())) {
+
+ if (RenderWidget* renderer = toRenderWidget(m_embedElement->renderer())) {
frame->loader()->client()->redirectDataToPlugin(renderer->widget());
frame->loader()->activeDocumentLoader()->mainResourceLoader()->setShouldBufferData(false);
}
-
+
finish();
}
}
diff --git a/WebCore/loader/ProgressTracker.h b/WebCore/loader/ProgressTracker.h
index b8d4532..744e101 100644
--- a/WebCore/loader/ProgressTracker.h
+++ b/WebCore/loader/ProgressTracker.h
@@ -36,7 +36,7 @@ class Frame;
class ResourceResponse;
struct ProgressItem;
-class ProgressTracker : Noncopyable {
+class ProgressTracker : public Noncopyable {
public:
ProgressTracker();
~ProgressTracker();
diff --git a/WebCore/loader/ResourceLoader.cpp b/WebCore/loader/ResourceLoader.cpp
index 4f55981..5ad181b 100644
--- a/WebCore/loader/ResourceLoader.cpp
+++ b/WebCore/loader/ResourceLoader.cpp
@@ -30,6 +30,7 @@
#include "config.h"
#include "ResourceLoader.h"
+#include "ApplicationCacheHost.h"
#include "DocumentLoader.h"
#include "Frame.h"
#include "FrameLoader.h"
@@ -121,7 +122,7 @@ bool ResourceLoader::load(const ResourceRequest& r)
#endif
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- if (m_documentLoader->scheduleApplicationCacheLoad(this, clientRequest, r.url()))
+ if (m_documentLoader->applicationCacheHost()->maybeLoadResource(this, clientRequest, r.url()))
return true;
#endif
@@ -192,17 +193,6 @@ void ResourceLoader::clearResourceData()
m_resourceData->clear();
}
-#if ENABLE(OFFLINE_WEB_APPLICATIONS)
-bool ResourceLoader::scheduleLoadFallbackResourceFromApplicationCache(ApplicationCache* cache)
-{
- if (documentLoader()->scheduleLoadFallbackResourceFromApplicationCache(this, m_request, cache)) {
- handle()->cancel();
- return true;
- }
- return false;
-}
-#endif
-
void ResourceLoader::willSendRequest(ResourceRequest& request, const ResourceResponse& redirectResponse)
{
// Protect this in this delegate method since the additional processing can do
@@ -384,10 +374,8 @@ ResourceError ResourceLoader::cannotShowURLError()
void ResourceLoader::willSendRequest(ResourceHandle*, ResourceRequest& request, const ResourceResponse& redirectResponse)
{
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- if (!redirectResponse.isNull() && !protocolHostAndPortAreEqual(request.url(), redirectResponse.url())) {
- if (scheduleLoadFallbackResourceFromApplicationCache())
- return;
- }
+ if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForRedirect(this, request, redirectResponse))
+ return;
#endif
willSendRequest(request, redirectResponse);
}
@@ -400,10 +388,8 @@ void ResourceLoader::didSendData(ResourceHandle*, unsigned long long bytesSent,
void ResourceLoader::didReceiveResponse(ResourceHandle*, const ResourceResponse& response)
{
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- if (response.httpStatusCode() / 100 == 4 || response.httpStatusCode() / 100 == 5) {
- if (scheduleLoadFallbackResourceFromApplicationCache())
- return;
- }
+ if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForResponse(this, response))
+ return;
#endif
didReceiveResponse(response);
}
@@ -421,10 +407,8 @@ void ResourceLoader::didFinishLoading(ResourceHandle*)
void ResourceLoader::didFail(ResourceHandle*, const ResourceError& error)
{
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- if (!error.isCancellation()) {
- if (documentLoader()->scheduleLoadFallbackResourceFromApplicationCache(this, m_request))
- return;
- }
+ if (documentLoader()->applicationCacheHost()->maybeLoadFallbackForError(this, error))
+ return;
#endif
didFail(error);
}
diff --git a/WebCore/loader/ResourceLoader.h b/WebCore/loader/ResourceLoader.h
index d3e7b80..5239289 100644
--- a/WebCore/loader/ResourceLoader.h
+++ b/WebCore/loader/ResourceLoader.h
@@ -40,7 +40,7 @@
namespace WebCore {
- class ApplicationCache;
+ class ApplicationCacheHost;
class DocumentLoader;
class Frame;
class FrameLoader;
@@ -119,7 +119,7 @@ namespace WebCore {
ResourceLoader(Frame*, bool sendResourceLoadCallbacks, bool shouldContentSniff);
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
- bool scheduleLoadFallbackResourceFromApplicationCache(ApplicationCache* = 0);
+ friend class ApplicationCacheHost; // for access to request()
#endif
virtual void didCancel(const ResourceError&);
@@ -133,13 +133,13 @@ namespace WebCore {
RefPtr<ResourceHandle> m_handle;
RefPtr<Frame> m_frame;
RefPtr<DocumentLoader> m_documentLoader;
- ResourceResponse m_response;
+ ResourceResponse m_response;
private:
ResourceRequest m_request;
RefPtr<SharedBuffer> m_resourceData;
- unsigned long m_identifier;
+ unsigned long m_identifier;
bool m_reachedTerminalState;
bool m_cancelled;
diff --git a/WebCore/loader/TextDocument.cpp b/WebCore/loader/TextDocument.cpp
index 0d86c1b..a3d7061 100644
--- a/WebCore/loader/TextDocument.cpp
+++ b/WebCore/loader/TextDocument.cpp
@@ -162,6 +162,8 @@ void TextTokenizer::write(const SegmentedString& s, bool)
void TextTokenizer::finish()
{
+ if (!m_preElement)
+ write(SegmentedString(), true); // Create document structure for an empty text document.
m_preElement = 0;
fastFree(m_buffer);
m_buffer = 0;
diff --git a/WebCore/loader/TextResourceDecoder.cpp b/WebCore/loader/TextResourceDecoder.cpp
index ee81326..db68441 100644
--- a/WebCore/loader/TextResourceDecoder.cpp
+++ b/WebCore/loader/TextResourceDecoder.cpp
@@ -509,11 +509,13 @@ bool TextResourceDecoder::checkForCSSCharset(const char* data, size_t len, bool&
static inline void skipComment(const char*& ptr, const char* pEnd)
{
const char* p = ptr;
+ if (p == pEnd)
+ return;
// Allow <!-->; other browsers do.
if (*p == '>') {
p++;
} else {
- while (p != pEnd) {
+ while (p + 2 < pEnd) {
if (*p == '-') {
// This is the real end of comment, "-->".
if (p[1] == '-' && p[2] == '>') {
@@ -521,7 +523,7 @@ static inline void skipComment(const char*& ptr, const char* pEnd)
break;
}
// This is the incorrect end of comment that other browsers allow, "--!>".
- if (p[1] == '-' && p[2] == '!' && p[3] == '>') {
+ if (p + 3 < pEnd && p[1] == '-' && p[2] == '!' && p[3] == '>') {
p += 4;
break;
}
diff --git a/WebCore/loader/ThreadableLoader.cpp b/WebCore/loader/ThreadableLoader.cpp
index 7b9c6c6..b174af7 100644
--- a/WebCore/loader/ThreadableLoader.cpp
+++ b/WebCore/loader/ThreadableLoader.cpp
@@ -40,18 +40,18 @@
namespace WebCore {
-PassRefPtr<ThreadableLoader> ThreadableLoader::create(ScriptExecutionContext* context, ThreadableLoaderClient* client, const ResourceRequest& request, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials, RedirectOriginCheck redirectOriginCheck)
+PassRefPtr<ThreadableLoader> ThreadableLoader::create(ScriptExecutionContext* context, ThreadableLoaderClient* client, const ResourceRequest& request, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials, CrossOriginRedirectPolicy crossOriginRedirectPolicy)
{
ASSERT(client);
ASSERT(context);
#if ENABLE(WORKERS)
if (context->isWorkerContext())
- return WorkerThreadableLoader::create(static_cast<WorkerContext*>(context), client, WorkerRunLoop::defaultMode(), request, callbacksSetting, contentSniff, storedCredentials, redirectOriginCheck);
+ return WorkerThreadableLoader::create(static_cast<WorkerContext*>(context), client, WorkerRunLoop::defaultMode(), request, callbacksSetting, contentSniff, storedCredentials, crossOriginRedirectPolicy);
#endif // ENABLE(WORKERS)
ASSERT(context->isDocument());
- return DocumentThreadableLoader::create(static_cast<Document*>(context), client, request, callbacksSetting, contentSniff, storedCredentials, redirectOriginCheck);
+ return DocumentThreadableLoader::create(static_cast<Document*>(context), client, request, callbacksSetting, contentSniff, storedCredentials, crossOriginRedirectPolicy);
}
void ThreadableLoader::loadResourceSynchronously(ScriptExecutionContext* context, const ResourceRequest& request, ThreadableLoaderClient& client, StoredCredentials storedCredentials)
@@ -60,7 +60,7 @@ void ThreadableLoader::loadResourceSynchronously(ScriptExecutionContext* context
#if ENABLE(WORKERS)
if (context->isWorkerContext()) {
- WorkerThreadableLoader::loadResourceSynchronously(static_cast<WorkerContext*>(context), request, client, storedCredentials, RequireSameRedirectOrigin);
+ WorkerThreadableLoader::loadResourceSynchronously(static_cast<WorkerContext*>(context), request, client, storedCredentials, DenyCrossOriginRedirect);
return;
}
#endif // ENABLE(WORKERS)
diff --git a/WebCore/loader/ThreadableLoader.h b/WebCore/loader/ThreadableLoader.h
index 0a4c4e3..1ac12cb 100644
--- a/WebCore/loader/ThreadableLoader.h
+++ b/WebCore/loader/ThreadableLoader.h
@@ -58,17 +58,17 @@ namespace WebCore {
DoNotAllowStoredCredentials
};
- enum RedirectOriginCheck {
- RequireSameRedirectOrigin,
- AllowDifferentRedirectOrigin
+ enum CrossOriginRedirectPolicy {
+ DenyCrossOriginRedirect,
+ AllowCrossOriginRedirect
};
// Useful for doing loader operations from any thread (not threadsafe,
// just able to run on threads other than the main thread).
- class ThreadableLoader : Noncopyable {
+ class ThreadableLoader : public Noncopyable {
public:
static void loadResourceSynchronously(ScriptExecutionContext*, const ResourceRequest&, ThreadableLoaderClient&, StoredCredentials);
- static PassRefPtr<ThreadableLoader> create(ScriptExecutionContext*, ThreadableLoaderClient*, const ResourceRequest&, LoadCallbacks, ContentSniff, StoredCredentials, RedirectOriginCheck);
+ static PassRefPtr<ThreadableLoader> create(ScriptExecutionContext*, ThreadableLoaderClient*, const ResourceRequest&, LoadCallbacks, ContentSniff, StoredCredentials, CrossOriginRedirectPolicy);
virtual void cancel() = 0;
void ref() { refThreadableLoader(); }
diff --git a/WebCore/loader/WorkerThreadableLoader.cpp b/WebCore/loader/WorkerThreadableLoader.cpp
index 8153ad8..4d12b8d 100644
--- a/WebCore/loader/WorkerThreadableLoader.cpp
+++ b/WebCore/loader/WorkerThreadableLoader.cpp
@@ -54,10 +54,10 @@ namespace WebCore {
static const char loadResourceSynchronouslyMode[] = "loadResourceSynchronouslyMode";
WorkerThreadableLoader::WorkerThreadableLoader(WorkerContext* workerContext, ThreadableLoaderClient* client, const String& taskMode, const ResourceRequest& request, LoadCallbacks callbacksSetting,
- ContentSniff contentSniff, StoredCredentials storedCredentials, RedirectOriginCheck redirectOriginCheck)
+ ContentSniff contentSniff, StoredCredentials storedCredentials, CrossOriginRedirectPolicy crossOriginRedirectPolicy)
: m_workerContext(workerContext)
, m_workerClientWrapper(ThreadableLoaderClientWrapper::create(client))
- , m_bridge(*(new MainThreadBridge(m_workerClientWrapper, m_workerContext->thread()->workerLoaderProxy(), taskMode, request, callbacksSetting, contentSniff, storedCredentials, redirectOriginCheck)))
+ , m_bridge(*(new MainThreadBridge(m_workerClientWrapper, m_workerContext->thread()->workerLoaderProxy(), taskMode, request, callbacksSetting, contentSniff, storedCredentials, crossOriginRedirectPolicy)))
{
}
@@ -66,7 +66,7 @@ WorkerThreadableLoader::~WorkerThreadableLoader()
m_bridge.destroy();
}
-void WorkerThreadableLoader::loadResourceSynchronously(WorkerContext* workerContext, const ResourceRequest& request, ThreadableLoaderClient& client, StoredCredentials storedCredentials, RedirectOriginCheck redirectOriginCheck)
+void WorkerThreadableLoader::loadResourceSynchronously(WorkerContext* workerContext, const ResourceRequest& request, ThreadableLoaderClient& client, StoredCredentials storedCredentials, CrossOriginRedirectPolicy crossOriginRedirectPolicy)
{
WorkerRunLoop& runLoop = workerContext->thread()->runLoop();
@@ -75,7 +75,7 @@ void WorkerThreadableLoader::loadResourceSynchronously(WorkerContext* workerCont
mode.append(String::number(runLoop.createUniqueId()));
ContentSniff contentSniff = request.url().isLocalFile() ? SniffContent : DoNotSniffContent;
- RefPtr<WorkerThreadableLoader> loader = WorkerThreadableLoader::create(workerContext, &client, mode, request, DoNotSendLoadCallbacks, contentSniff, storedCredentials, redirectOriginCheck);
+ RefPtr<WorkerThreadableLoader> loader = WorkerThreadableLoader::create(workerContext, &client, mode, request, DoNotSendLoadCallbacks, contentSniff, storedCredentials, crossOriginRedirectPolicy);
MessageQueueWaitResult result = MessageQueueMessageReceived;
while (!loader->done() && result != MessageQueueTerminated)
@@ -92,20 +92,20 @@ void WorkerThreadableLoader::cancel()
WorkerThreadableLoader::MainThreadBridge::MainThreadBridge(PassRefPtr<ThreadableLoaderClientWrapper> workerClientWrapper, WorkerLoaderProxy& loaderProxy, const String& taskMode,
const ResourceRequest& request, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials,
- RedirectOriginCheck redirectOriginCheck)
+ CrossOriginRedirectPolicy crossOriginRedirectPolicy)
: m_workerClientWrapper(workerClientWrapper)
, m_loaderProxy(loaderProxy)
, m_taskMode(taskMode.copy())
{
ASSERT(m_workerClientWrapper.get());
- m_loaderProxy.postTaskToLoader(createCallbackTask(&MainThreadBridge::mainThreadCreateLoader, this, request, callbacksSetting, contentSniff, storedCredentials, redirectOriginCheck));
+ m_loaderProxy.postTaskToLoader(createCallbackTask(&MainThreadBridge::mainThreadCreateLoader, this, request, callbacksSetting, contentSniff, storedCredentials, crossOriginRedirectPolicy));
}
WorkerThreadableLoader::MainThreadBridge::~MainThreadBridge()
{
}
-void WorkerThreadableLoader::MainThreadBridge::mainThreadCreateLoader(ScriptExecutionContext* context, MainThreadBridge* thisPtr, auto_ptr<CrossThreadResourceRequestData> requestData, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials, RedirectOriginCheck redirectOriginCheck)
+void WorkerThreadableLoader::MainThreadBridge::mainThreadCreateLoader(ScriptExecutionContext* context, MainThreadBridge* thisPtr, auto_ptr<CrossThreadResourceRequestData> requestData, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials, CrossOriginRedirectPolicy crossOriginRedirectPolicy)
{
ASSERT(isMainThread());
ASSERT(context->isDocument());
@@ -117,7 +117,7 @@ void WorkerThreadableLoader::MainThreadBridge::mainThreadCreateLoader(ScriptExec
// FIXME: If the a site requests a local resource, then this will return a non-zero value but the sync path
// will return a 0 value. Either this should return 0 or the other code path should do a callback with
// a failure.
- thisPtr->m_mainThreadLoader = ThreadableLoader::create(context, thisPtr, *request, callbacksSetting, contentSniff, storedCredentials, redirectOriginCheck);
+ thisPtr->m_mainThreadLoader = ThreadableLoader::create(context, thisPtr, *request, callbacksSetting, contentSniff, storedCredentials, crossOriginRedirectPolicy);
ASSERT(thisPtr->m_mainThreadLoader);
}
diff --git a/WebCore/loader/WorkerThreadableLoader.h b/WebCore/loader/WorkerThreadableLoader.h
index a36bedf..8b11b70 100644
--- a/WebCore/loader/WorkerThreadableLoader.h
+++ b/WebCore/loader/WorkerThreadableLoader.h
@@ -55,10 +55,10 @@ namespace WebCore {
class WorkerThreadableLoader : public RefCounted<WorkerThreadableLoader>, public ThreadableLoader {
public:
- static void loadResourceSynchronously(WorkerContext*, const ResourceRequest&, ThreadableLoaderClient&, StoredCredentials, RedirectOriginCheck);
- static PassRefPtr<WorkerThreadableLoader> create(WorkerContext* workerContext, ThreadableLoaderClient* client, const String& taskMode, const ResourceRequest& request, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials, RedirectOriginCheck redirectOriginCheck)
+ static void loadResourceSynchronously(WorkerContext*, const ResourceRequest&, ThreadableLoaderClient&, StoredCredentials, CrossOriginRedirectPolicy);
+ static PassRefPtr<WorkerThreadableLoader> create(WorkerContext* workerContext, ThreadableLoaderClient* client, const String& taskMode, const ResourceRequest& request, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials, CrossOriginRedirectPolicy crossOriginRedirectPolicy)
{
- return adoptRef(new WorkerThreadableLoader(workerContext, client, taskMode, request, callbacksSetting, contentSniff, storedCredentials, redirectOriginCheck));
+ return adoptRef(new WorkerThreadableLoader(workerContext, client, taskMode, request, callbacksSetting, contentSniff, storedCredentials, crossOriginRedirectPolicy));
}
~WorkerThreadableLoader();
@@ -97,7 +97,7 @@ namespace WebCore {
class MainThreadBridge : ThreadableLoaderClient {
public:
// All executed on the worker context's thread.
- MainThreadBridge(PassRefPtr<ThreadableLoaderClientWrapper>, WorkerLoaderProxy&, const String& taskMode, const ResourceRequest&, LoadCallbacks, ContentSniff, StoredCredentials, RedirectOriginCheck);
+ MainThreadBridge(PassRefPtr<ThreadableLoaderClientWrapper>, WorkerLoaderProxy&, const String& taskMode, const ResourceRequest&, LoadCallbacks, ContentSniff, StoredCredentials, CrossOriginRedirectPolicy);
void cancel();
void destroy();
@@ -109,7 +109,7 @@ namespace WebCore {
static void mainThreadDestroy(ScriptExecutionContext*, MainThreadBridge*);
~MainThreadBridge();
- static void mainThreadCreateLoader(ScriptExecutionContext*, MainThreadBridge*, std::auto_ptr<CrossThreadResourceRequestData>, LoadCallbacks, ContentSniff, StoredCredentials, RedirectOriginCheck);
+ static void mainThreadCreateLoader(ScriptExecutionContext*, MainThreadBridge*, std::auto_ptr<CrossThreadResourceRequestData>, LoadCallbacks, ContentSniff, StoredCredentials, CrossOriginRedirectPolicy);
static void mainThreadCancel(ScriptExecutionContext*, MainThreadBridge*);
virtual void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent);
virtual void didReceiveResponse(const ResourceResponse&);
@@ -133,7 +133,7 @@ namespace WebCore {
String m_taskMode;
};
- WorkerThreadableLoader(WorkerContext*, ThreadableLoaderClient*, const String& taskMode, const ResourceRequest&, LoadCallbacks, ContentSniff, StoredCredentials, RedirectOriginCheck);
+ WorkerThreadableLoader(WorkerContext*, ThreadableLoaderClient*, const String& taskMode, const ResourceRequest&, LoadCallbacks, ContentSniff, StoredCredentials, CrossOriginRedirectPolicy);
RefPtr<WorkerContext> m_workerContext;
RefPtr<ThreadableLoaderClientWrapper> m_workerClientWrapper;
diff --git a/WebCore/loader/appcache/ApplicationCache.cpp b/WebCore/loader/appcache/ApplicationCache.cpp
index 3c29d68..34dace4 100644
--- a/WebCore/loader/appcache/ApplicationCache.cpp
+++ b/WebCore/loader/appcache/ApplicationCache.cpp
@@ -82,7 +82,7 @@ void ApplicationCache::addResource(PassRefPtr<ApplicationCacheResource> resource
if (m_storageID) {
ASSERT(!resource->storageID());
- ASSERT(resource->type() & (ApplicationCacheResource::Dynamic | ApplicationCacheResource::Master));
+ ASSERT(resource->type() & ApplicationCacheResource::Master);
// Add the resource to the storage.
cacheStorage().store(resource.get(), this);
@@ -111,6 +111,7 @@ unsigned ApplicationCache::removeResource(const String& url)
ApplicationCacheResource* ApplicationCache::resourceForURL(const String& url)
{
+ ASSERT(!KURL(url).hasFragmentIdentifier());
return m_resources.get(url).get();
}
@@ -130,34 +131,12 @@ ApplicationCacheResource* ApplicationCache::resourceForRequest(const ResourceReq
// We only care about HTTP/HTTPS GET requests.
if (!requestIsHTTPOrHTTPSGet(request))
return false;
-
- return resourceForURL(request.url());
-}
-unsigned ApplicationCache::numDynamicEntries() const
-{
- // FIXME: Implement
- return 0;
-}
-
-String ApplicationCache::dynamicEntry(unsigned) const
-{
- // FIXME: Implement
- return String();
-}
-
-bool ApplicationCache::addDynamicEntry(const String& url)
-{
- if (!equalIgnoringCase(m_group->manifestURL().protocol(), KURL(url).protocol()))
- return false;
+ KURL url(request.url());
+ if (url.hasFragmentIdentifier())
+ url.removeFragmentIdentifier();
- // FIXME: Implement (be sure to respect private browsing state).
- return true;
-}
-
-void ApplicationCache::removeDynamicEntry(const String&)
-{
- // FIXME: Implement (be sure to respect private browsing state).
+ return resourceForURL(url);
}
void ApplicationCache::setOnlineWhitelist(const Vector<KURL>& onlineWhitelist)
diff --git a/WebCore/loader/appcache/ApplicationCache.h b/WebCore/loader/appcache/ApplicationCache.h
index 4566471..d718cd7 100644
--- a/WebCore/loader/appcache/ApplicationCache.h
+++ b/WebCore/loader/appcache/ApplicationCache.h
@@ -65,12 +65,6 @@ public:
ApplicationCacheResource* resourceForRequest(const ResourceRequest&);
ApplicationCacheResource* resourceForURL(const String& url);
- unsigned numDynamicEntries() const;
- String dynamicEntry(unsigned index) const;
-
- bool addDynamicEntry(const String& url);
- void removeDynamicEntry(const String& url);
-
void setOnlineWhitelist(const Vector<KURL>& onlineWhitelist);
const Vector<KURL>& onlineWhitelist() const { return m_onlineWhitelist; }
bool isURLInOnlineWhitelist(const KURL&); // There is an entry in online whitelist that has the same origin as the resource's URL and that is a prefix match for the resource's URL.
@@ -105,8 +99,10 @@ private:
Vector<KURL> m_onlineWhitelist;
FallbackURLVector m_fallbackURLs;
- // While an update is in progress, changes in dynamic entries are queued for later execution.
- Vector<std::pair<KURL, bool> > m_pendingDynamicEntryActions;
+ // The total size of the resources belonging to this Application Cache instance.
+ // This is an estimation of the size this Application Cache occupies in the
+ // database file.
+ int64_t m_estimatedSizeInStorage;
// The total size of the resources belonging to this Application Cache instance.
// This is an estimation of the size this Application Cache occupies in the
diff --git a/WebCore/loader/appcache/ApplicationCacheGroup.cpp b/WebCore/loader/appcache/ApplicationCacheGroup.cpp
index 735e3a3..739118f 100644
--- a/WebCore/loader/appcache/ApplicationCacheGroup.cpp
+++ b/WebCore/loader/appcache/ApplicationCacheGroup.cpp
@@ -29,6 +29,7 @@
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
#include "ApplicationCache.h"
+#include "ApplicationCacheHost.h"
#include "ApplicationCacheResource.h"
#include "ApplicationCacheStorage.h"
#include "ChromeClient.h"
@@ -85,7 +86,11 @@ ApplicationCache* ApplicationCacheGroup::cacheForMainRequest(const ResourceReque
if (!ApplicationCache::requestIsHTTPOrHTTPSGet(request))
return 0;
- if (ApplicationCacheGroup* group = cacheStorage().cacheGroupForURL(request.url())) {
+ KURL url(request.url());
+ if (url.hasFragmentIdentifier())
+ url.removeFragmentIdentifier();
+
+ if (ApplicationCacheGroup* group = cacheStorage().cacheGroupForURL(url)) {
ASSERT(group->newestCache());
ASSERT(!group->isObsolete());
@@ -100,7 +105,11 @@ ApplicationCache* ApplicationCacheGroup::fallbackCacheForMainRequest(const Resou
if (!ApplicationCache::requestIsHTTPOrHTTPSGet(request))
return 0;
- if (ApplicationCacheGroup* group = cacheStorage().fallbackCacheGroupForURL(request.url())) {
+ KURL url(request.url());
+ if (url.hasFragmentIdentifier())
+ url.removeFragmentIdentifier();
+
+ if (ApplicationCacheGroup* group = cacheStorage().fallbackCacheGroupForURL(url)) {
ASSERT(group->newestCache());
ASSERT(!group->isObsolete());
@@ -110,7 +119,7 @@ ApplicationCache* ApplicationCacheGroup::fallbackCacheForMainRequest(const Resou
return 0;
}
-void ApplicationCacheGroup::selectCache(Frame* frame, const KURL& manifestURL)
+void ApplicationCacheGroup::selectCache(Frame* frame, const KURL& passedManifestURL)
{
ASSERT(frame && frame->page());
@@ -118,14 +127,18 @@ void ApplicationCacheGroup::selectCache(Frame* frame, const KURL& manifestURL)
return;
DocumentLoader* documentLoader = frame->loader()->documentLoader();
- ASSERT(!documentLoader->applicationCache());
+ ASSERT(!documentLoader->applicationCacheHost()->applicationCache());
- if (manifestURL.isNull()) {
+ if (passedManifestURL.isNull()) {
selectCacheWithoutManifestURL(frame);
return;
}
-
- ApplicationCache* mainResourceCache = documentLoader->mainResourceApplicationCache();
+
+ KURL manifestURL(passedManifestURL);
+ if (manifestURL.hasFragmentIdentifier())
+ manifestURL.removeFragmentIdentifier();
+
+ ApplicationCache* mainResourceCache = documentLoader->applicationCacheHost()->mainResourceApplicationCache();
if (mainResourceCache) {
if (manifestURL == mainResourceCache->group()->m_manifestURL) {
@@ -133,7 +146,10 @@ void ApplicationCacheGroup::selectCache(Frame* frame, const KURL& manifestURL)
mainResourceCache->group()->update(frame, ApplicationCacheUpdateWithBrowsingContext);
} else {
// The main resource was loaded from cache, so the cache must have an entry for it. Mark it as foreign.
- ApplicationCacheResource* resource = mainResourceCache->resourceForURL(documentLoader->url());
+ KURL documentURL(documentLoader->url());
+ if (documentURL.hasFragmentIdentifier())
+ documentURL.removeFragmentIdentifier();
+ ApplicationCacheResource* resource = mainResourceCache->resourceForURL(documentURL);
bool inStorage = resource->storageID();
resource->addType(ApplicationCacheResource::Foreign);
if (inStorage)
@@ -160,14 +176,14 @@ void ApplicationCacheGroup::selectCache(Frame* frame, const KURL& manifestURL)
// Don't change anything on disk if private browsing is enabled.
if (!frame->settings() || frame->settings()->privateBrowsingEnabled()) {
- postListenerTask(&DOMApplicationCache::callCheckingListener, documentLoader);
- postListenerTask(&DOMApplicationCache::callErrorListener, documentLoader);
+ postListenerTask(ApplicationCacheHost::CHECKING_EVENT, documentLoader);
+ postListenerTask(ApplicationCacheHost::ERROR_EVENT, documentLoader);
return;
}
ApplicationCacheGroup* group = cacheStorage().findOrCreateCacheGroup(manifestURL);
- documentLoader->setCandidateApplicationCacheGroup(group);
+ documentLoader->applicationCacheHost()->setCandidateApplicationCacheGroup(group);
group->m_pendingMasterResourceLoaders.add(documentLoader);
group->m_downloadingPendingMasterResourceLoadersCount++;
@@ -181,9 +197,9 @@ void ApplicationCacheGroup::selectCacheWithoutManifestURL(Frame* frame)
return;
DocumentLoader* documentLoader = frame->loader()->documentLoader();
- ASSERT(!documentLoader->applicationCache());
+ ASSERT(!documentLoader->applicationCacheHost()->applicationCache());
- ApplicationCache* mainResourceCache = documentLoader->mainResourceApplicationCache();
+ ApplicationCache* mainResourceCache = documentLoader->applicationCacheHost()->mainResourceApplicationCache();
if (mainResourceCache) {
mainResourceCache->group()->associateDocumentLoaderWithCache(documentLoader, mainResourceCache);
@@ -195,7 +211,9 @@ void ApplicationCacheGroup::finishedLoadingMainResource(DocumentLoader* loader)
{
ASSERT(m_pendingMasterResourceLoaders.contains(loader));
ASSERT(m_completionType == None || m_pendingEntries.isEmpty());
- const KURL& url = loader->url();
+ KURL url = loader->url();
+ if (url.hasFragmentIdentifier())
+ url.removeFragmentIdentifier();
switch (m_completionType) {
case None:
@@ -218,9 +236,9 @@ void ApplicationCacheGroup::finishedLoadingMainResource(DocumentLoader* loader)
// 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->setApplicationCache(0); // Will unset candidate, too.
+ loader->applicationCacheHost()->setApplicationCache(0); // Will unset candidate, too.
m_associatedDocumentLoaders.remove(loader);
- postListenerTask(&DOMApplicationCache::callErrorListener, loader);
+ postListenerTask(ApplicationCacheHost::ERROR_EVENT, loader);
break;
case Completed:
ASSERT(m_associatedDocumentLoaders.contains(loader));
@@ -254,28 +272,28 @@ void ApplicationCacheGroup::failedLoadingMainResource(DocumentLoader* loader)
// 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(&DOMApplicationCache::callErrorListener, loader);
+ postListenerTask(ApplicationCacheHost::ERROR_EVENT, loader);
break;
case Failure:
// Cache update failed, too.
ASSERT(!m_cacheBeingUpdated); // Already cleared out by stopLoading().
- ASSERT(!loader->applicationCache() || loader->applicationCache() == m_cacheBeingUpdated);
+ ASSERT(!loader->applicationCacheHost()->applicationCache() || loader->applicationCacheHost()->applicationCache() == m_cacheBeingUpdated);
- loader->setApplicationCache(0); // Will unset candidate, too.
+ loader->applicationCacheHost()->setApplicationCache(0); // Will unset candidate, too.
m_associatedDocumentLoaders.remove(loader);
- postListenerTask(&DOMApplicationCache::callErrorListener, 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->applicationCache() == m_cacheBeingUpdated);
- ASSERT(!loader->candidateApplicationCacheGroup());
+ ASSERT(loader->applicationCacheHost()->applicationCache() == m_cacheBeingUpdated);
+ ASSERT(!loader->applicationCacheHost()->candidateApplicationCacheGroup());
m_associatedDocumentLoaders.remove(loader);
- loader->setApplicationCache(0);
+ loader->applicationCacheHost()->setApplicationCache(0);
- postListenerTask(&DOMApplicationCache::callErrorListener, loader);
+ postListenerTask(ApplicationCacheHost::ERROR_EVENT, loader);
break;
}
@@ -315,7 +333,7 @@ void ApplicationCacheGroup::disassociateDocumentLoader(DocumentLoader* loader)
m_pendingMasterResourceLoaders.remove(loader);
- loader->setApplicationCache(0); // Will set candidate to 0, too.
+ loader->applicationCacheHost()->setApplicationCache(0); // Will set candidate to 0, too.
if (!m_associatedDocumentLoaders.isEmpty() || !m_pendingMasterResourceLoaders.isEmpty())
return;
@@ -371,9 +389,9 @@ void ApplicationCacheGroup::update(Frame* frame, ApplicationCacheUpdateOption up
{
if (m_updateStatus == Checking || m_updateStatus == Downloading) {
if (updateOption == ApplicationCacheUpdateWithBrowsingContext) {
- postListenerTask(&DOMApplicationCache::callCheckingListener, frame->loader()->documentLoader());
+ postListenerTask(ApplicationCacheHost::CHECKING_EVENT, frame->loader()->documentLoader());
if (m_updateStatus == Downloading)
- postListenerTask(&DOMApplicationCache::callDownloadingListener, frame->loader()->documentLoader());
+ postListenerTask(ApplicationCacheHost::DOWNLOADING_EVENT, frame->loader()->documentLoader());
}
return;
}
@@ -383,8 +401,8 @@ void ApplicationCacheGroup::update(Frame* frame, ApplicationCacheUpdateOption up
ASSERT(m_pendingMasterResourceLoaders.isEmpty());
ASSERT(m_pendingEntries.isEmpty());
ASSERT(!m_cacheBeingUpdated);
- postListenerTask(&DOMApplicationCache::callCheckingListener, frame->loader()->documentLoader());
- postListenerTask(&DOMApplicationCache::callNoUpdateListener, frame->loader()->documentLoader());
+ postListenerTask(ApplicationCacheHost::CHECKING_EVENT, frame->loader()->documentLoader());
+ postListenerTask(ApplicationCacheHost::NOUPDATE_EVENT, frame->loader()->documentLoader());
return;
}
@@ -393,10 +411,10 @@ void ApplicationCacheGroup::update(Frame* frame, ApplicationCacheUpdateOption up
m_updateStatus = Checking;
- postListenerTask(&DOMApplicationCache::callCheckingListener, m_associatedDocumentLoaders);
+ postListenerTask(ApplicationCacheHost::CHECKING_EVENT, m_associatedDocumentLoaders);
if (!m_newestCache) {
ASSERT(updateOption == ApplicationCacheUpdateWithBrowsingContext);
- postListenerTask(&DOMApplicationCache::callCheckingListener, frame->loader()->documentLoader());
+ postListenerTask(ApplicationCacheHost::CHECKING_EVENT, frame->loader()->documentLoader());
}
ASSERT(!m_manifestHandle);
@@ -436,7 +454,9 @@ void ApplicationCacheGroup::didReceiveResponse(ResourceHandle* handle, const Res
ASSERT(handle == m_currentHandle);
- const KURL& url = handle->request().url();
+ KURL url(handle->request().url());
+ if (url.hasFragmentIdentifier())
+ url.removeFragmentIdentifier();
ASSERT(!m_currentResource);
ASSERT(m_pendingEntries.contains(url));
@@ -448,9 +468,10 @@ void ApplicationCacheGroup::didReceiveResponse(ResourceHandle* handle, const Res
ASSERT(!(type & ApplicationCacheResource::Master));
if (m_newestCache && response.httpStatusCode() == 304) { // Not modified.
- ApplicationCacheResource* newestCachedResource = m_newestCache->resourceForURL(handle->request().url());
+ ApplicationCacheResource* newestCachedResource = m_newestCache->resourceForURL(url);
if (newestCachedResource) {
m_cacheBeingUpdated->addResource(ApplicationCacheResource::create(url, newestCachedResource->response(), type, newestCachedResource->data()));
+ m_pendingEntries.remove(m_currentHandle->request().url());
m_currentHandle->cancel();
m_currentHandle = 0;
// Load the next resource, if any.
@@ -468,7 +489,7 @@ void ApplicationCacheGroup::didReceiveResponse(ResourceHandle* handle, const Res
// Skip this resource. It is dropped from the cache.
m_currentHandle->cancel();
m_currentHandle = 0;
- m_pendingEntries.remove(handle->request().url());
+ m_pendingEntries.remove(url);
// Load the next resource, if any.
startLoadingEntry();
} else {
@@ -478,6 +499,7 @@ void ApplicationCacheGroup::didReceiveResponse(ResourceHandle* handle, const Res
ApplicationCacheResource* newestCachedResource = m_newestCache->resourceForURL(handle->request().url());
ASSERT(newestCachedResource);
m_cacheBeingUpdated->addResource(ApplicationCacheResource::create(url, newestCachedResource->response(), type, newestCachedResource->data()));
+ m_pendingEntries.remove(m_currentHandle->request().url());
m_currentHandle->cancel();
m_currentHandle = 0;
// Load the next resource, if any.
@@ -531,7 +553,9 @@ void ApplicationCacheGroup::didFail(ResourceHandle* handle, const ResourceError&
}
unsigned type = m_currentResource ? m_currentResource->type() : m_pendingEntries.get(handle->request().url());
- const KURL& url = handle->request().url();
+ KURL url(handle->request().url());
+ if (url.hasFragmentIdentifier())
+ url.removeFragmentIdentifier();
ASSERT(!m_currentResource || !m_pendingEntries.contains(url));
m_currentResource = 0;
@@ -625,7 +649,7 @@ void ApplicationCacheGroup::didFinishLoadingManifest()
// We have the manifest, now download the resources.
m_updateStatus = Downloading;
- postListenerTask(&DOMApplicationCache::callDownloadingListener, m_associatedDocumentLoaders);
+ postListenerTask(ApplicationCacheHost::DOWNLOADING_EVENT, m_associatedDocumentLoaders);
ASSERT(m_pendingEntries.isEmpty());
@@ -633,7 +657,7 @@ void ApplicationCacheGroup::didFinishLoadingManifest()
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))
+ if (type & ApplicationCacheResource::Master)
addEntry(it->first, type);
}
}
@@ -675,8 +699,8 @@ void ApplicationCacheGroup::manifestNotFound()
{
makeObsolete();
- postListenerTask(&DOMApplicationCache::callObsoleteListener, m_associatedDocumentLoaders);
- postListenerTask(&DOMApplicationCache::callErrorListener, m_pendingMasterResourceLoaders);
+ postListenerTask(ApplicationCacheHost::OBSOLETE_EVENT, m_associatedDocumentLoaders);
+ postListenerTask(ApplicationCacheHost::ERROR_EVENT, m_pendingMasterResourceLoaders);
stopLoading();
@@ -686,9 +710,9 @@ void ApplicationCacheGroup::manifestNotFound()
while (!m_pendingMasterResourceLoaders.isEmpty()) {
HashSet<DocumentLoader*>::iterator it = m_pendingMasterResourceLoaders.begin();
- ASSERT((*it)->candidateApplicationCacheGroup() == this);
- ASSERT(!(*it)->applicationCache());
- (*it)->setCandidateApplicationCacheGroup(0);
+ ASSERT((*it)->applicationCacheHost()->candidateApplicationCacheGroup() == this);
+ ASSERT(!(*it)->applicationCacheHost()->applicationCache());
+ (*it)->applicationCacheHost()->setCandidateApplicationCacheGroup(0);
m_pendingMasterResourceLoaders.remove(it);
}
@@ -724,11 +748,11 @@ void ApplicationCacheGroup::checkIfLoadIsComplete()
if (!m_storageID)
cacheStorage().storeNewestCache(this);
- postListenerTask(&DOMApplicationCache::callNoUpdateListener, m_associatedDocumentLoaders);
+ postListenerTask(ApplicationCacheHost::NOUPDATE_EVENT, m_associatedDocumentLoaders);
break;
case Failure:
ASSERT(!m_cacheBeingUpdated);
- postListenerTask(&DOMApplicationCache::callErrorListener, m_associatedDocumentLoaders);
+ postListenerTask(ApplicationCacheHost::ERROR_EVENT, m_associatedDocumentLoaders);
if (m_caches.isEmpty()) {
ASSERT(m_associatedDocumentLoaders.isEmpty());
delete this;
@@ -752,6 +776,7 @@ void ApplicationCacheGroup::checkIfLoadIsComplete()
RefPtr<ApplicationCache> oldNewestCache = (m_newestCache == m_cacheBeingUpdated) ? 0 : m_newestCache;
setNewestCache(m_cacheBeingUpdated.release());
+#ifdef MANUAL_MERGE_REQUIRED
if (cacheStorage().storeNewestCache(this)) {
// New cache stored, now remove the old cache.
if (oldNewestCache)
@@ -796,6 +821,55 @@ void ApplicationCacheGroup::checkIfLoadIsComplete()
}
}
}
+#else // MANUAL_MERGE_REQUIRED
+ if (cacheStorage().storeNewestCache(this)) {
+ // New cache stored, now remove the old cache.
+ if (oldNewestCache)
+ cacheStorage().remove(oldNewestCache.get());
+ // Fire the success events.
+ postListenerTask(isUpgradeAttempt ? ApplicationCacheHost::UPDATEREADY_EVENT : ApplicationCacheHost::CACHED_EVENT, m_associatedDocumentLoaders);
+ } else {
+ if (cacheStorage().isMaximumSizeReached() && !m_calledReachedMaxAppCacheSize) {
+ // We ran out of space. All the changes in the cache storage have
+ // been rolled back. We roll back to the previous state in here,
+ // as well, call the chrome client asynchronously and retry to
+ // save the new cache.
+
+ // Save a reference to the new cache.
+ m_cacheBeingUpdated = m_newestCache.release();
+ if (oldNewestCache) {
+ // Reinstate the oldNewestCache.
+ setNewestCache(oldNewestCache.release());
+ }
+ scheduleReachedMaxAppCacheSizeCallback();
+ return;
+ } else {
+ // Run the "cache failure steps"
+ // Fire the error events to all pending master entries, as well any other cache hosts
+ // currently associated with a cache in this group.
+ postListenerTask(ApplicationCacheHost::ERROR_EVENT, m_associatedDocumentLoaders);
+ // Disassociate the pending master entries from the failed new cache. Note that
+ // all other loaders in the m_associatedDocumentLoaders are still associated with
+ // some other cache in this group. They are not associated with the failed new cache.
+
+ // 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)
+ disassociateDocumentLoader(loaders[i]); // This can delete this group.
+
+ // Reinstate the oldNewestCache, if there was one.
+ if (oldNewestCache) {
+ // This will discard the failed new cache.
+ setNewestCache(oldNewestCache.release());
+ } else {
+ // We must have been deleted by the last call to disassociateDocumentLoader().
+ return;
+ }
+ }
+ }
+#endif // MANUAL_MERGE_REQUIRED
break;
}
}
@@ -820,7 +894,7 @@ void ApplicationCacheGroup::startLoadingEntry()
EntryMap::const_iterator it = m_pendingEntries.begin();
- postListenerTask(&DOMApplicationCache::callProgressListener, m_associatedDocumentLoaders);
+ postListenerTask(ApplicationCacheHost::PROGRESS_EVENT, m_associatedDocumentLoaders);
ASSERT(!m_currentHandle);
@@ -851,6 +925,7 @@ void ApplicationCacheGroup::deliverDelayedMainResources()
void ApplicationCacheGroup::addEntry(const String& url, unsigned type)
{
ASSERT(m_cacheBeingUpdated);
+ ASSERT(!KURL(url).hasFragmentIdentifier());
// 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).
@@ -883,7 +958,7 @@ void ApplicationCacheGroup::associateDocumentLoaderWithCache(DocumentLoader* loa
ASSERT(!m_isObsolete);
- loader->setApplicationCache(cache);
+ loader->applicationCacheHost()->setApplicationCache(cache);
ASSERT(!m_associatedDocumentLoaders.contains(loader));
m_associatedDocumentLoaders.add(loader);
@@ -917,39 +992,44 @@ void ApplicationCacheGroup::scheduleReachedMaxAppCacheSizeCallback()
}
class CallCacheListenerTask : public ScriptExecutionContext::Task {
- typedef void (DOMApplicationCache::*ListenerFunction)();
public:
- static PassRefPtr<CallCacheListenerTask> create(ListenerFunction listenerFunction)
+ static PassRefPtr<CallCacheListenerTask> create(PassRefPtr<DocumentLoader> loader, ApplicationCacheHost::EventID eventID)
{
- return adoptRef(new CallCacheListenerTask(listenerFunction));
+ return adoptRef(new CallCacheListenerTask(loader, eventID));
}
virtual void performTask(ScriptExecutionContext* context)
{
- ASSERT(context->isDocument());
- if (DOMWindow* window = static_cast<Document*>(context)->domWindow()) {
- if (DOMApplicationCache* domCache = window->optionalApplicationCache())
- (domCache->*m_listenerFunction)();
- }
+
+ ASSERT_UNUSED(context, context->isDocument());
+ Frame* frame = m_documentLoader->frame();
+ if (!frame)
+ return;
+
+ ASSERT(frame->loader()->documentLoader() == m_documentLoader.get());
+
+ m_documentLoader->applicationCacheHost()->notifyEventListener(m_eventID);
}
private:
- CallCacheListenerTask(ListenerFunction listenerFunction)
- : m_listenerFunction(listenerFunction)
+ CallCacheListenerTask(PassRefPtr<DocumentLoader> loader, ApplicationCacheHost::EventID eventID)
+ : m_documentLoader(loader)
+ , m_eventID(eventID)
{
}
- ListenerFunction m_listenerFunction;
+ RefPtr<DocumentLoader> m_documentLoader;
+ ApplicationCacheHost::EventID m_eventID;
};
-void ApplicationCacheGroup::postListenerTask(ListenerFunction listenerFunction, const HashSet<DocumentLoader*>& loaderSet)
+void ApplicationCacheGroup::postListenerTask(ApplicationCacheHost::EventID eventID, 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);
+ postListenerTask(eventID, *iter);
}
-void ApplicationCacheGroup::postListenerTask(ListenerFunction listenerFunction, DocumentLoader* loader)
+void ApplicationCacheGroup::postListenerTask(ApplicationCacheHost::EventID eventID, DocumentLoader* loader)
{
Frame* frame = loader->frame();
if (!frame)
@@ -957,7 +1037,7 @@ void ApplicationCacheGroup::postListenerTask(ListenerFunction listenerFunction,
ASSERT(frame->loader()->documentLoader() == loader);
- frame->document()->postTask(CallCacheListenerTask::create(listenerFunction));
+ frame->document()->postTask(CallCacheListenerTask::create(loader, eventID));
}
void ApplicationCacheGroup::clearStorageID()
diff --git a/WebCore/loader/appcache/ApplicationCacheGroup.h b/WebCore/loader/appcache/ApplicationCacheGroup.h
index 281dadf..7fa8f33 100644
--- a/WebCore/loader/appcache/ApplicationCacheGroup.h
+++ b/WebCore/loader/appcache/ApplicationCacheGroup.h
@@ -32,6 +32,7 @@
#include <wtf/HashMap.h>
#include <wtf/HashSet.h>
+#include "DOMApplicationCache.h"
#include "KURL.h"
#include "PlatformString.h"
#include "ResourceHandle.h"
@@ -42,7 +43,6 @@ namespace WebCore {
class ApplicationCache;
class ApplicationCacheResource;
-class DOMApplicationCache;
class Document;
class DocumentLoader;
class Frame;
@@ -52,7 +52,7 @@ enum ApplicationCacheUpdateOption {
ApplicationCacheUpdateWithoutBrowsingContext
};
-class ApplicationCacheGroup : Noncopyable, ResourceHandleClient {
+class ApplicationCacheGroup : public Noncopyable, ResourceHandleClient {
public:
ApplicationCacheGroup(const KURL& manifestURL, bool isCopy = false);
~ApplicationCacheGroup();
@@ -91,11 +91,17 @@ public:
bool isCopy() const { return m_isCopy; }
private:
+#ifdef MANUAL_MERGE_REQUIRED
typedef void (DOMApplicationCache::*ListenerFunction)();
static void postListenerTask(ListenerFunction, const HashSet<DocumentLoader*>&);
static void postListenerTask(ListenerFunction, const Vector<RefPtr<DocumentLoader> >& loaders);
static void postListenerTask(ListenerFunction, DocumentLoader*);
void scheduleReachedMaxAppCacheSizeCallback();
+#else // MANUAL_MERGE_REQUIRED
+ static void postListenerTask(ApplicationCacheHost::EventID, const HashSet<DocumentLoader*>&);
+ static void postListenerTask(ApplicationCacheHost::EventID, DocumentLoader*);
+ void scheduleReachedMaxAppCacheSizeCallback();
+#endif // MANUAL_MERGE_REQUIRED
PassRefPtr<ResourceHandle> createResourceHandle(const KURL&, ApplicationCacheResource* newestCachedResource);
diff --git a/WebCore/loader/appcache/ApplicationCacheHost.cpp b/WebCore/loader/appcache/ApplicationCacheHost.cpp
new file mode 100644
index 0000000..b0c9e74
--- /dev/null
+++ b/WebCore/loader/appcache/ApplicationCacheHost.cpp
@@ -0,0 +1,381 @@
+/*
+ * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ApplicationCacheHost.h"
+
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+
+#include "ApplicationCache.h"
+#include "ApplicationCacheGroup.h"
+#include "ApplicationCacheResource.h"
+#include "DocumentLoader.h"
+#include "DOMApplicationCache.h"
+#include "Frame.h"
+#include "FrameLoader.h"
+#include "FrameLoaderClient.h"
+#include "MainResourceLoader.h"
+#include "ResourceLoader.h"
+#include "ResourceRequest.h"
+#include "Settings.h"
+
+namespace WebCore {
+
+ApplicationCacheHost::ApplicationCacheHost(DocumentLoader* documentLoader)
+ : m_domApplicationCache(0)
+ , m_documentLoader(documentLoader)
+ , m_candidateApplicationCacheGroup(0)
+{
+ ASSERT(m_documentLoader);
+}
+
+ApplicationCacheHost::~ApplicationCacheHost()
+{
+ if (m_applicationCache)
+ m_applicationCache->group()->disassociateDocumentLoader(m_documentLoader);
+ else if (m_candidateApplicationCacheGroup)
+ m_candidateApplicationCacheGroup->disassociateDocumentLoader(m_documentLoader);
+}
+
+void ApplicationCacheHost::selectCacheWithoutManifest()
+{
+ ApplicationCacheGroup::selectCacheWithoutManifestURL(m_documentLoader->frame());
+}
+
+void ApplicationCacheHost::selectCacheWithManifest(const KURL& manifestURL)
+{
+ ApplicationCacheGroup::selectCache(m_documentLoader->frame(), manifestURL);
+}
+
+void ApplicationCacheHost::maybeLoadMainResource(ResourceRequest& request, SubstituteData& substituteData)
+{
+ // Check if this request should be loaded from the application cache
+ if (!substituteData.isValid() && isApplicationCacheEnabled()) {
+ ASSERT(!m_mainResourceApplicationCache);
+
+ m_mainResourceApplicationCache = ApplicationCacheGroup::cacheForMainRequest(request, m_documentLoader);
+
+ if (m_mainResourceApplicationCache) {
+ // Get the resource from the application cache. By definition, cacheForMainRequest() returns a cache that contains the resource.
+ ApplicationCacheResource* resource = m_mainResourceApplicationCache->resourceForRequest(request);
+ substituteData = SubstituteData(resource->data(),
+ resource->response().mimeType(),
+ resource->response().textEncodingName(), KURL());
+ }
+ }
+}
+
+bool ApplicationCacheHost::maybeLoadFallbackForMainResponse(const ResourceRequest& request, const ResourceResponse& r)
+{
+ if (r.httpStatusCode() / 100 == 4 || r.httpStatusCode() / 100 == 5) {
+ ASSERT(!m_mainResourceApplicationCache);
+ if (isApplicationCacheEnabled()) {
+ m_mainResourceApplicationCache = ApplicationCacheGroup::fallbackCacheForMainRequest(request, documentLoader());
+
+ if (scheduleLoadFallbackResourceFromApplicationCache(documentLoader()->mainResourceLoader(), m_mainResourceApplicationCache.get()))
+ return true;
+ }
+ }
+ return false;
+}
+
+bool ApplicationCacheHost::maybeLoadFallbackForMainError(const ResourceRequest& request, const ResourceError& error)
+{
+ if (!error.isCancellation()) {
+ ASSERT(!m_mainResourceApplicationCache);
+ if (isApplicationCacheEnabled()) {
+ m_mainResourceApplicationCache = ApplicationCacheGroup::fallbackCacheForMainRequest(request, m_documentLoader);
+
+ if (scheduleLoadFallbackResourceFromApplicationCache(documentLoader()->mainResourceLoader(), m_mainResourceApplicationCache.get()))
+ return true;
+ }
+ }
+ return false;
+}
+
+void ApplicationCacheHost::mainResourceDataReceived(const char*, int, long long, bool)
+{
+ // This method is here to facilitate alternate implemetations of this interface by the host browser.
+}
+
+void ApplicationCacheHost::failedLoadingMainResource()
+{
+ ApplicationCacheGroup* group = m_candidateApplicationCacheGroup;
+ if (!group && m_applicationCache) {
+ ASSERT(!mainResourceApplicationCache()); // If the main resource were loaded from a cache, it wouldn't fail.
+ group = m_applicationCache->group();
+ }
+
+ if (group)
+ group->failedLoadingMainResource(m_documentLoader);
+}
+
+void ApplicationCacheHost::finishedLoadingMainResource()
+{
+ ApplicationCacheGroup* group = candidateApplicationCacheGroup();
+ if (!group && applicationCache() && !mainResourceApplicationCache())
+ group = applicationCache()->group();
+
+ if (group)
+ group->finishedLoadingMainResource(m_documentLoader);
+}
+
+bool ApplicationCacheHost::maybeLoadResource(ResourceLoader* loader, ResourceRequest& request, const KURL& originalURL)
+{
+ if (!isApplicationCacheEnabled())
+ return false;
+
+ if (request.url() != originalURL)
+ return false;
+
+ ApplicationCacheResource* resource;
+ if (!shouldLoadResourceFromApplicationCache(request, resource))
+ return false;
+
+ m_documentLoader->m_pendingSubstituteResources.set(loader, resource);
+ m_documentLoader->deliverSubstituteResourcesAfterDelay();
+
+ return true;
+}
+
+bool ApplicationCacheHost::maybeLoadFallbackForRedirect(ResourceLoader* resourceLoader, ResourceRequest& request, const ResourceResponse& redirectResponse)
+{
+ if (!redirectResponse.isNull() && !protocolHostAndPortAreEqual(request.url(), redirectResponse.url()))
+ if (scheduleLoadFallbackResourceFromApplicationCache(resourceLoader))
+ return true;
+ return false;
+}
+
+bool ApplicationCacheHost::maybeLoadFallbackForResponse(ResourceLoader* resourceLoader, const ResourceResponse& response)
+{
+ if (response.httpStatusCode() / 100 == 4 || response.httpStatusCode() / 100 == 5)
+ if (scheduleLoadFallbackResourceFromApplicationCache(resourceLoader))
+ return true;
+ return false;
+}
+
+bool ApplicationCacheHost::maybeLoadFallbackForError(ResourceLoader* resourceLoader, const ResourceError& error)
+{
+ if (!error.isCancellation())
+ if (scheduleLoadFallbackResourceFromApplicationCache(resourceLoader))
+ return true;
+ return false;
+}
+
+bool ApplicationCacheHost::maybeLoadSynchronously(ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data)
+{
+ ApplicationCacheResource* resource;
+ if (shouldLoadResourceFromApplicationCache(request, resource)) {
+ if (resource) {
+ response = resource->response();
+ data.append(resource->data()->data(), resource->data()->size());
+ } else {
+ error = documentLoader()->frameLoader()->client()->cannotShowURLError(request);
+ }
+ return true;
+ }
+ return false;
+}
+
+void ApplicationCacheHost::maybeLoadFallbackSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data)
+{
+ // If normal loading results in a redirect to a resource with another origin (indicative of a captive portal), or a 4xx or 5xx status code or equivalent,
+ // or if there were network errors (but not if the user canceled the download), then instead get, from the cache, the resource of the fallback entry
+ // corresponding to the matched namespace.
+ if ((!error.isNull() && !error.isCancellation())
+ || response.httpStatusCode() / 100 == 4 || response.httpStatusCode() / 100 == 5
+ || !protocolHostAndPortAreEqual(request.url(), response.url())) {
+ ApplicationCacheResource* resource;
+ if (getApplicationCacheFallbackResource(request, resource)) {
+ response = resource->response();
+ data.clear();
+ data.append(resource->data()->data(), resource->data()->size());
+ }
+ }
+}
+
+bool ApplicationCacheHost::canCacheInPageCache() const
+{
+ return !applicationCache() && !candidateApplicationCacheGroup();
+}
+
+void ApplicationCacheHost::setDOMApplicationCache(DOMApplicationCache* domApplicationCache)
+{
+ ASSERT(!m_domApplicationCache || !domApplicationCache);
+ m_domApplicationCache = domApplicationCache;
+}
+
+void ApplicationCacheHost::notifyEventListener(EventID id)
+{
+ if (m_domApplicationCache)
+ m_domApplicationCache->callEventListener(id);
+}
+
+void ApplicationCacheHost::setCandidateApplicationCacheGroup(ApplicationCacheGroup* group)
+{
+ ASSERT(!m_applicationCache);
+ m_candidateApplicationCacheGroup = group;
+}
+
+void ApplicationCacheHost::setApplicationCache(PassRefPtr<ApplicationCache> applicationCache)
+{
+ if (m_candidateApplicationCacheGroup) {
+ ASSERT(!m_applicationCache);
+ m_candidateApplicationCacheGroup = 0;
+ }
+
+ m_applicationCache = applicationCache;
+}
+
+bool ApplicationCacheHost::shouldLoadResourceFromApplicationCache(const ResourceRequest& request, ApplicationCacheResource*& resource)
+{
+ ApplicationCache* cache = applicationCache();
+ if (!cache || !cache->isComplete())
+ return false;
+
+ // If the resource is not a HTTP/HTTPS GET, then abort
+ if (!ApplicationCache::requestIsHTTPOrHTTPSGet(request))
+ return false;
+
+ // If the resource's URL is an master entry, the manifest, an explicit entry, or a fallback entry
+ // in the application cache, then get the resource from the cache (instead of fetching it).
+ resource = cache->resourceForURL(request.url());
+
+ // Resources that match fallback namespaces or online whitelist entries are fetched from the network,
+ // unless they are also cached.
+ if (!resource && (cache->urlMatchesFallbackNamespace(request.url()) || cache->isURLInOnlineWhitelist(request.url())))
+ return false;
+
+ // Resources that are not present in the manifest will always fail to load (at least, after the
+ // cache has been primed the first time), making the testing of offline applications simpler.
+ return true;
+}
+
+bool ApplicationCacheHost::getApplicationCacheFallbackResource(const ResourceRequest& request, ApplicationCacheResource*& resource, ApplicationCache* cache)
+{
+ if (!cache) {
+ cache = applicationCache();
+ if (!cache)
+ return false;
+ }
+ if (!cache->isComplete())
+ return false;
+
+ // If the resource is not a HTTP/HTTPS GET, then abort
+ if (!ApplicationCache::requestIsHTTPOrHTTPSGet(request))
+ return false;
+
+ KURL fallbackURL;
+ if (!cache->urlMatchesFallbackNamespace(request.url(), &fallbackURL))
+ return false;
+
+ resource = cache->resourceForURL(fallbackURL);
+ ASSERT(resource);
+
+ return true;
+}
+
+bool ApplicationCacheHost::scheduleLoadFallbackResourceFromApplicationCache(ResourceLoader* loader, ApplicationCache* cache)
+{
+ if (!isApplicationCacheEnabled())
+ return false;
+
+ ApplicationCacheResource* resource;
+ if (!getApplicationCacheFallbackResource(loader->request(), resource, cache))
+ return false;
+
+ m_documentLoader->m_pendingSubstituteResources.set(loader, resource);
+ m_documentLoader->deliverSubstituteResourcesAfterDelay();
+
+ loader->handle()->cancel();
+
+ return true;
+}
+
+ApplicationCacheHost::Status ApplicationCacheHost::status() const
+{
+ ApplicationCache* cache = applicationCache();
+ if (!cache)
+ return UNCACHED;
+
+ switch (cache->group()->updateStatus()) {
+ case ApplicationCacheGroup::Checking:
+ return CHECKING;
+ case ApplicationCacheGroup::Downloading:
+ return DOWNLOADING;
+ case ApplicationCacheGroup::Idle: {
+ if (cache->group()->isObsolete())
+ return OBSOLETE;
+ if (cache != cache->group()->newestCache())
+ return UPDATEREADY;
+ return IDLE;
+ }
+ }
+
+ ASSERT_NOT_REACHED();
+ return UNCACHED;
+}
+
+bool ApplicationCacheHost::update()
+{
+ ApplicationCache* cache = applicationCache();
+ if (!cache)
+ return false;
+ cache->group()->update(m_documentLoader->frame(), ApplicationCacheUpdateWithoutBrowsingContext);
+ return true;
+}
+
+bool ApplicationCacheHost::swapCache()
+{
+ ApplicationCache* cache = applicationCache();
+ if (!cache)
+ return false;
+
+ // If the group of application caches to which cache belongs has the lifecycle status obsolete, unassociate document from cache.
+ if (cache->group()->isObsolete()) {
+ cache->group()->disassociateDocumentLoader(m_documentLoader);
+ return true;
+ }
+
+ // If there is no newer cache, raise an INVALID_STATE_ERR exception.
+ ApplicationCache* newestCache = cache->group()->newestCache();
+ if (cache == newestCache)
+ return false;
+
+ ASSERT(cache->group() == newestCache->group());
+ setApplicationCache(newestCache);
+
+ return true;
+}
+
+bool ApplicationCacheHost::isApplicationCacheEnabled()
+{
+ return m_documentLoader->frame()->settings()
+ && m_documentLoader->frame()->settings()->offlineWebApplicationCacheEnabled();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(OFFLINE_WEB_APPLICATIONS)
diff --git a/WebCore/loader/appcache/ApplicationCacheHost.h b/WebCore/loader/appcache/ApplicationCacheHost.h
new file mode 100644
index 0000000..cb68862
--- /dev/null
+++ b/WebCore/loader/appcache/ApplicationCacheHost.h
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2009, Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ApplicationCacheHost_h
+#define ApplicationCacheHost_h
+
+#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+
+#include <wtf/OwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+ class DOMApplicationCache;
+ class DocumentLoader;
+ class KURL;
+ class ResourceLoader;
+ class ResourceError;
+ struct ResourceRequest;
+ class ResourceResponse;
+ class SubstituteData;
+#if PLATFORM(CHROMIUM)
+ class ApplicationCacheHostInternal;
+#else
+ class ApplicationCache;
+ class ApplicationCacheGroup;
+ class ApplicationCacheResource;
+ class ApplicationCacheStorage;
+#endif
+
+ class ApplicationCacheHost {
+ public:
+ // The Status numeric values are specified in the HTML5 spec.
+ enum Status {
+ UNCACHED = 0,
+ IDLE = 1,
+ CHECKING = 2,
+ DOWNLOADING = 3,
+ UPDATEREADY = 4,
+ OBSOLETE = 5
+ };
+
+ enum EventID {
+ CHECKING_EVENT = 0,
+ ERROR_EVENT,
+ NOUPDATE_EVENT,
+ DOWNLOADING_EVENT,
+ PROGRESS_EVENT,
+ UPDATEREADY_EVENT,
+ CACHED_EVENT,
+ OBSOLETE_EVENT // Must remain the last value, this is used to size arrays.
+ };
+
+ ApplicationCacheHost(DocumentLoader*);
+ ~ApplicationCacheHost();
+
+ void selectCacheWithoutManifest();
+ void selectCacheWithManifest(const KURL& manifestURL);
+
+ void maybeLoadMainResource(ResourceRequest&, SubstituteData&);
+ bool maybeLoadFallbackForMainResponse(const ResourceRequest&, const ResourceResponse&);
+ bool maybeLoadFallbackForMainError(const ResourceRequest&, const ResourceError&);
+ void mainResourceDataReceived(const char* data, int length, long long lengthReceived, bool allAtOnce);
+ void finishedLoadingMainResource();
+ void failedLoadingMainResource();
+
+ bool maybeLoadResource(ResourceLoader*, ResourceRequest&, const KURL& originalURL);
+ bool maybeLoadFallbackForRedirect(ResourceLoader*, ResourceRequest&, const ResourceResponse&);
+ bool maybeLoadFallbackForResponse(ResourceLoader*, const ResourceResponse&);
+ bool maybeLoadFallbackForError(ResourceLoader*, const ResourceError&);
+
+ bool maybeLoadSynchronously(ResourceRequest&, ResourceError&, ResourceResponse&, Vector<char>& data);
+ void maybeLoadFallbackSynchronously(const ResourceRequest&, ResourceError&, ResourceResponse&, Vector<char>& data);
+
+ bool canCacheInPageCache() const;
+
+ Status status() const;
+ bool update();
+ bool swapCache();
+
+ void setDOMApplicationCache(DOMApplicationCache* domApplicationCache);
+ void notifyEventListener(EventID id);
+
+ private:
+ bool isApplicationCacheEnabled();
+ DocumentLoader* documentLoader() { return m_documentLoader; }
+
+ DOMApplicationCache* m_domApplicationCache;
+ DocumentLoader* m_documentLoader;
+
+#if PLATFORM(CHROMIUM)
+ friend class ApplicationCacheHostInternal;
+ OwnPtr<ApplicationCacheHostInternal> m_internal;
+#else
+ friend class ApplicationCacheGroup;
+ friend class ApplicationCacheStorage;
+
+ bool scheduleLoadFallbackResourceFromApplicationCache(ResourceLoader*, ApplicationCache* = 0);
+ bool shouldLoadResourceFromApplicationCache(const ResourceRequest&, ApplicationCacheResource*&);
+ bool getApplicationCacheFallbackResource(const ResourceRequest&, ApplicationCacheResource*&, ApplicationCache* = 0);
+ void setCandidateApplicationCacheGroup(ApplicationCacheGroup* group);
+ ApplicationCacheGroup* candidateApplicationCacheGroup() const { return m_candidateApplicationCacheGroup; }
+ void setApplicationCache(PassRefPtr<ApplicationCache> applicationCache);
+ ApplicationCache* applicationCache() const { return m_applicationCache.get(); }
+ ApplicationCache* mainResourceApplicationCache() const { return m_mainResourceApplicationCache.get(); }
+
+
+ // The application cache that the document loader is associated with (if any).
+ RefPtr<ApplicationCache> m_applicationCache;
+
+ // Before an application cache has finished loading, this will be the candidate application
+ // group that the document loader is associated with.
+ ApplicationCacheGroup* m_candidateApplicationCacheGroup;
+
+ // This is the application cache the main resource was loaded from (if any).
+ RefPtr<ApplicationCache> m_mainResourceApplicationCache;
+#endif
+ };
+
+} // namespace WebCore
+
+#endif // ENABLE(OFFLINE_WEB_APPLICATIONS)
+#endif // ApplicationCacheHost_h
diff --git a/WebCore/loader/appcache/ApplicationCacheResource.cpp b/WebCore/loader/appcache/ApplicationCacheResource.cpp
index 90e65ad..03c5c83 100644
--- a/WebCore/loader/appcache/ApplicationCacheResource.cpp
+++ b/WebCore/loader/appcache/ApplicationCacheResource.cpp
@@ -80,8 +80,6 @@ void ApplicationCacheResource::dumpType(unsigned type)
printf("foreign ");
if (type & Fallback)
printf("fallback ");
- if (type & Dynamic)
- printf("dynamic ");
printf("\n");
}
diff --git a/WebCore/loader/appcache/ApplicationCacheResource.h b/WebCore/loader/appcache/ApplicationCacheResource.h
index 53fdd1d..2ca7846 100644
--- a/WebCore/loader/appcache/ApplicationCacheResource.h
+++ b/WebCore/loader/appcache/ApplicationCacheResource.h
@@ -39,12 +39,12 @@ public:
Manifest = 1 << 1,
Explicit = 1 << 2,
Foreign = 1 << 3,
- Fallback = 1 << 4,
- Dynamic = 1 << 5
+ Fallback = 1 << 4
};
static PassRefPtr<ApplicationCacheResource> create(const KURL& url, const ResourceResponse& response, unsigned type, PassRefPtr<SharedBuffer> buffer = SharedBuffer::create())
{
+ ASSERT(!url.hasFragmentIdentifier());
return adoptRef(new ApplicationCacheResource(url, response, type, buffer));
}
diff --git a/WebCore/loader/appcache/ApplicationCacheStorage.cpp b/WebCore/loader/appcache/ApplicationCacheStorage.cpp
index a1dad15..e081f5d 100644
--- a/WebCore/loader/appcache/ApplicationCacheStorage.cpp
+++ b/WebCore/loader/appcache/ApplicationCacheStorage.cpp
@@ -29,6 +29,7 @@
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
#include "ApplicationCache.h"
+#include "ApplicationCacheHost.h"
#include "ApplicationCacheGroup.h"
#include "ApplicationCacheResource.h"
#include "CString.h"
@@ -127,11 +128,12 @@ ApplicationCacheGroup* ApplicationCacheStorage::loadCacheGroup(const KURL& manif
ApplicationCacheGroup* ApplicationCacheStorage::findOrCreateCacheGroup(const KURL& manifestURL)
{
+ ASSERT(!manifestURL.hasFragmentIdentifier());
+
std::pair<CacheGroupMap::iterator, bool> result = m_cachesInMemory.add(manifestURL, 0);
if (!result.second) {
ASSERT(result.first->second);
-
return result.first->second;
}
@@ -176,6 +178,8 @@ void ApplicationCacheStorage::loadManifestHostHashes()
ApplicationCacheGroup* ApplicationCacheStorage::cacheGroupForURL(const KURL& url)
{
+ ASSERT(!url.hasFragmentIdentifier());
+
loadManifestHostHashes();
// Hash the host name and see if there's a manifest with the same host.
@@ -251,6 +255,8 @@ ApplicationCacheGroup* ApplicationCacheStorage::cacheGroupForURL(const KURL& url
ApplicationCacheGroup* ApplicationCacheStorage::fallbackCacheGroupForURL(const KURL& url)
{
+ ASSERT(!url.hasFragmentIdentifier());
+
// Check if an appropriate cache already exists in memory.
CacheGroupMap::const_iterator end = m_cachesInMemory.end();
for (CacheGroupMap::const_iterator it = m_cachesInMemory.begin(); it != end; ++it) {
@@ -356,6 +362,7 @@ const String& ApplicationCacheStorage::cacheDirectory() const
return m_cacheDirectory;
}
+#ifdef MANUAL_MERGE_REQUIRED
void ApplicationCacheStorage::setMaximumSize(int64_t size)
{
m_maximumSize = size;
@@ -406,6 +413,60 @@ int64_t ApplicationCacheStorage::spaceNeeded(int64_t cacheToSave)
ASSERT(spaceNeeded);
return spaceNeeded;
}
+#else // MANUAL_MERGE_REQUIRED
+void ApplicationCacheStorage::setMaximumSize(int64_t size)
+{
+ m_maximumSize = size;
+}
+
+int64_t ApplicationCacheStorage::maximumSize() const
+{
+ return m_maximumSize;
+}
+
+bool ApplicationCacheStorage::isMaximumSizeReached() const
+{
+ return m_isMaximumSizeReached;
+}
+
+int64_t ApplicationCacheStorage::spaceNeeded(int64_t cacheToSave)
+{
+ int64_t spaceNeeded = 0;
+ long long fileSize = 0;
+ if (!getFileSize(m_cacheFile, fileSize))
+ return 0;
+
+ int64_t currentSize = fileSize;
+
+ // Determine the amount of free space we have available.
+ int64_t totalAvailableSize = 0;
+ if (m_maximumSize < currentSize) {
+ // The max size is smaller than the actual size of the app cache file.
+ // This can happen if the client previously imposed a larger max size
+ // value and the app cache file has already grown beyond the current
+ // max size value.
+ // The amount of free space is just the amount of free space inside
+ // the database file. Note that this is always 0 if SQLite is compiled
+ // with AUTO_VACUUM = 1.
+ totalAvailableSize = m_database.freeSpaceSize();
+ } else {
+ // The max size is the same or larger than the current size.
+ // The amount of free space available is the amount of free space
+ // inside the database file plus the amount we can grow until we hit
+ // the max size.
+ totalAvailableSize = (m_maximumSize - currentSize) + m_database.freeSpaceSize();
+ }
+
+ // The space needed to be freed in order to accomodate the failed cache is
+ // the size of the failed cache minus any already available free space.
+ spaceNeeded = cacheToSave - totalAvailableSize;
+ // The space needed value must be positive (or else the total already
+ // available free space would be larger than the size of the failed cache and
+ // saving of the cache should have never failed).
+ ASSERT(spaceNeeded);
+ return spaceNeeded;
+}
+#endif // MANUAL_MERGE_REQUIRED
bool ApplicationCacheStorage::executeSQLCommand(const String& sql)
{
@@ -674,9 +735,6 @@ bool ApplicationCacheStorage::storeUpdatedType(ApplicationCacheResource* resourc
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)
@@ -933,8 +991,12 @@ void ApplicationCacheStorage::empty()
it->second->clearStorageID();
}
-bool ApplicationCacheStorage::storeCopyOfCache(const String& cacheDirectory, ApplicationCache* cache)
+bool ApplicationCacheStorage::storeCopyOfCache(const String& cacheDirectory, ApplicationCacheHost* cacheHost)
{
+ ApplicationCache* cache = cacheHost->applicationCache();
+ if (!cache)
+ return true;
+
// Create a new cache.
RefPtr<ApplicationCache> cacheCopy = ApplicationCache::create();
@@ -964,6 +1026,118 @@ bool ApplicationCacheStorage::storeCopyOfCache(const String& cacheDirectory, App
return copyStorage.storeNewestCache(groupCopy.get());
}
+#ifdef MANUAL_MERGE_REQUIRED
+
+bool ApplicationCacheStorage::manifestURLs(Vector<KURL>* urls)
+{
+ ASSERT(urls);
+ openDatabase(false);
+ if (!m_database.isOpen())
+ return false;
+
+ SQLiteStatement selectURLs(m_database, "SELECT manifestURL FROM CacheGroups");
+
+ if (selectURLs.prepare() != SQLResultOk)
+ return false;
+
+ while (selectURLs.step() == SQLResultRow)
+ urls->append(selectURLs.getColumnText(0));
+
+ return true;
+}
+
+bool ApplicationCacheStorage::cacheGroupSize(const String& manifestURL, int64_t* size)
+{
+ ASSERT(size);
+ openDatabase(false);
+ if (!m_database.isOpen())
+ return false;
+
+ SQLiteStatement statement(m_database, "SELECT sum(Caches.size) FROM Caches INNER JOIN CacheGroups ON Caches.cacheGroup=CacheGroups.id WHERE CacheGroups.manifestURL=?");
+ if (statement.prepare() != SQLResultOk)
+ return false;
+
+ statement.bindText(1, manifestURL);
+
+ int result = statement.step();
+ if (result == SQLResultDone)
+ return false;
+
+ if (result != SQLResultRow) {
+ LOG_ERROR("Could not get the size of the cache group, error \"%s\"", m_database.lastErrorMsg());
+ return false;
+ }
+
+ *size = statement.getColumnInt64(0);
+ return true;
+}
+
+bool ApplicationCacheStorage::deleteCacheGroup(const String& manifestURL)
+{
+ SQLiteTransaction deleteTransaction(m_database);
+ // Check to see if the group is in memory.
+ ApplicationCacheGroup* group = m_cachesInMemory.get(manifestURL);
+ if (group)
+ cacheGroupMadeObsolete(group);
+ else {
+ // The cache group is not in memory, so remove it from the disk.
+ openDatabase(false);
+ if (!m_database.isOpen())
+ return false;
+
+ SQLiteStatement idStatement(m_database, "SELECT id FROM CacheGroups WHERE manifestURL=?");
+ if (idStatement.prepare() != SQLResultOk)
+ return false;
+
+ idStatement.bindText(1, manifestURL);
+
+ int result = idStatement.step();
+ if (result == SQLResultDone)
+ return false;
+
+ if (result != SQLResultRow) {
+ LOG_ERROR("Could not load cache group id, error \"%s\"", m_database.lastErrorMsg());
+ return false;
+ }
+
+ int64_t groupId = idStatement.getColumnInt64(0);
+
+ SQLiteStatement cacheStatement(m_database, "DELETE FROM Caches WHERE cacheGroup=?");
+ if (cacheStatement.prepare() != SQLResultOk)
+ return false;
+
+ SQLiteStatement groupStatement(m_database, "DELETE FROM CacheGroups WHERE id=?");
+ if (groupStatement.prepare() != SQLResultOk)
+ return false;
+
+ cacheStatement.bindInt64(1, groupId);
+ executeStatement(cacheStatement);
+ groupStatement.bindInt64(1, groupId);
+ executeStatement(groupStatement);
+ }
+
+ deleteTransaction.commit();
+ return true;
+}
+
+void ApplicationCacheStorage::vacuumDatabaseFile()
+{
+ m_database.runVacuumCommand();
+}
+
+void ApplicationCacheStorage::checkForMaxSizeReached()
+{
+ if (m_database.lastError() == SQLResultFull)
+ m_isMaximumSizeReached = true;
+}
+
+ApplicationCacheStorage::ApplicationCacheStorage()
+ : m_maximumSize(INT_MAX)
+ , m_isMaximumSizeReached(false)
+{
+}
+
+#else // MANUAL_MERGE_REQUIRED
bool ApplicationCacheStorage::manifestURLs(Vector<KURL>* urls)
{
@@ -1059,6 +1233,10 @@ bool ApplicationCacheStorage::deleteCacheGroup(const String& manifestURL)
void ApplicationCacheStorage::vacuumDatabaseFile()
{
+ openDatabase(false);
+ if (!m_database.isOpen())
+ return;
+
m_database.runVacuumCommand();
}
@@ -1074,6 +1252,7 @@ ApplicationCacheStorage::ApplicationCacheStorage()
{
}
+#endif // MANUAL_MERGE_REQUIRED
ApplicationCacheStorage& cacheStorage()
{
DEFINE_STATIC_LOCAL(ApplicationCacheStorage, storage, ());
diff --git a/WebCore/loader/appcache/ApplicationCacheStorage.h b/WebCore/loader/appcache/ApplicationCacheStorage.h
index c6d687e..1348aa9 100644
--- a/WebCore/loader/appcache/ApplicationCacheStorage.h
+++ b/WebCore/loader/appcache/ApplicationCacheStorage.h
@@ -37,6 +37,7 @@
namespace WebCore {
class ApplicationCache;
+class ApplicationCacheHost;
class ApplicationCacheGroup;
class ApplicationCacheResource;
class KURL;
@@ -69,7 +70,7 @@ public:
void empty();
- static bool storeCopyOfCache(const String& cacheDirectory, ApplicationCache*);
+ static bool storeCopyOfCache(const String& cacheDirectory, ApplicationCacheHost*);
bool manifestURLs(Vector<KURL>* urls);
bool cacheGroupSize(const String& manifestURL, int64_t* size);
diff --git a/WebCore/loader/appcache/DOMApplicationCache.cpp b/WebCore/loader/appcache/DOMApplicationCache.cpp
index 12d86a7..109ac1a 100644
--- a/WebCore/loader/appcache/DOMApplicationCache.cpp
+++ b/WebCore/loader/appcache/DOMApplicationCache.cpp
@@ -28,9 +28,7 @@
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
-#include "ApplicationCache.h"
-#include "ApplicationCacheGroup.h"
-#include "ApplicationCacheResource.h"
+#include "ApplicationCacheHost.h"
#include "DocumentLoader.h"
#include "Event.h"
#include "EventException.h"
@@ -38,87 +36,52 @@
#include "EventNames.h"
#include "Frame.h"
#include "FrameLoader.h"
-#include "StaticStringList.h"
namespace WebCore {
DOMApplicationCache::DOMApplicationCache(Frame* frame)
: m_frame(frame)
{
+ ASSERT(applicationCacheHost());
+ applicationCacheHost()->setDOMApplicationCache(this);
}
void DOMApplicationCache::disconnectFrame()
{
+ ApplicationCacheHost* cacheHost = applicationCacheHost();
+ if (cacheHost)
+ cacheHost->setDOMApplicationCache(0);
m_frame = 0;
}
-ApplicationCache* DOMApplicationCache::associatedCache() const
+ApplicationCacheHost* DOMApplicationCache::applicationCacheHost() const
{
- if (!m_frame)
+ if (!m_frame || !m_frame->loader()->documentLoader())
return 0;
-
- return m_frame->loader()->documentLoader()->applicationCache();
+ return m_frame->loader()->documentLoader()->applicationCacheHost();
}
unsigned short DOMApplicationCache::status() const
{
- ApplicationCache* cache = associatedCache();
- if (!cache)
- return UNCACHED;
-
- switch (cache->group()->updateStatus()) {
- case ApplicationCacheGroup::Checking:
- return CHECKING;
- case ApplicationCacheGroup::Downloading:
- return DOWNLOADING;
- case ApplicationCacheGroup::Idle: {
- if (cache->group()->isObsolete())
- return OBSOLETE;
- if (cache != cache->group()->newestCache())
- return UPDATEREADY;
- return IDLE;
- }
- }
-
- ASSERT_NOT_REACHED();
- return 0;
+ ApplicationCacheHost* cacheHost = applicationCacheHost();
+ if (!cacheHost)
+ return ApplicationCacheHost::UNCACHED;
+ return cacheHost->status();
}
void DOMApplicationCache::update(ExceptionCode& ec)
{
- ApplicationCache* cache = associatedCache();
- if (!cache) {
+ ApplicationCacheHost* cacheHost = applicationCacheHost();
+ if (!cacheHost || !cacheHost->update())
ec = INVALID_STATE_ERR;
- return;
- }
-
- cache->group()->update(m_frame, ApplicationCacheUpdateWithoutBrowsingContext);
}
bool DOMApplicationCache::swapCache()
{
- if (!m_frame)
- return false;
-
- ApplicationCache* cache = m_frame->loader()->documentLoader()->applicationCache();
- if (!cache)
+ ApplicationCacheHost* cacheHost = applicationCacheHost();
+ if (!cacheHost)
return false;
-
- // If the group of application caches to which cache belongs has the lifecycle status obsolete, unassociate document from cache.
- if (cache->group()->isObsolete()) {
- cache->group()->disassociateDocumentLoader(m_frame->loader()->documentLoader());
- return true;
- }
-
- // If there is no newer cache, raise an INVALID_STATE_ERR exception.
- ApplicationCache* newestCache = cache->group()->newestCache();
- if (cache == newestCache)
- return false;
-
- ASSERT(cache->group() == newestCache->group());
- m_frame->loader()->documentLoader()->setApplicationCache(newestCache);
-
- return true;
+ return cacheHost->swapCache();
}
void DOMApplicationCache::swapCache(ExceptionCode& ec)
@@ -127,65 +90,6 @@ void DOMApplicationCache::swapCache(ExceptionCode& ec)
ec = INVALID_STATE_ERR;
}
-PassRefPtr<DOMStringList> DOMApplicationCache::items()
-{
- Vector<String> result;
- if (ApplicationCache* cache = associatedCache()) {
- unsigned numEntries = cache->numDynamicEntries();
- result.reserveInitialCapacity(numEntries);
- for (unsigned i = 0; i < numEntries; ++i)
- result.append(cache->dynamicEntry(i));
- }
- return StaticStringList::adopt(result);
-}
-
-bool DOMApplicationCache::hasItem(const KURL& url, ExceptionCode& ec)
-{
- ApplicationCache* cache = associatedCache();
- if (!cache) {
- ec = INVALID_STATE_ERR;
- return false;
- }
-
- if (!url.isValid()) {
- ec = SYNTAX_ERR;
- return false;
- }
-
- ApplicationCacheResource* resource = cache->resourceForURL(url.string());
- return resource && (resource->type() & ApplicationCacheResource::Dynamic);
-}
-
-void DOMApplicationCache::add(const KURL& url, ExceptionCode& ec)
-{
- ApplicationCache* cache = associatedCache();
- if (!cache) {
- ec = INVALID_STATE_ERR;
- return;
- }
-
- if (!url.isValid()) {
- ec = SYNTAX_ERR;
- return;
- }
-
- if (!cache->addDynamicEntry(url)) {
- // This should use the (currently not specified) security exceptions in HTML5 4.3.4
- ec = SECURITY_ERR;
- }
-}
-
-void DOMApplicationCache::remove(const KURL& url, ExceptionCode& ec)
-{
- ApplicationCache* cache = associatedCache();
- if (!cache) {
- ec = INVALID_STATE_ERR;
- return;
- }
-
- cache->removeDynamicEntry(url);
-}
-
ScriptExecutionContext* DOMApplicationCache::scriptExecutionContext() const
{
return m_frame->document();
@@ -231,7 +135,7 @@ bool DOMApplicationCache::dispatchEvent(PassRefPtr<Event> event, ExceptionCode&
ec = EventException::UNSPECIFIED_EVENT_TYPE_ERR;
return true;
}
-
+
ListenerVector listenersCopy = m_eventListeners.get(event->type());
for (ListenerVector::const_iterator listenerIter = listenersCopy.begin(); listenerIter != listenersCopy.end(); ++listenerIter) {
event->setTarget(this);
@@ -258,45 +162,53 @@ void DOMApplicationCache::callListener(const AtomicString& eventType, EventListe
ASSERT(!ec);
}
-void DOMApplicationCache::callCheckingListener()
+const AtomicString& DOMApplicationCache::toEventType(ApplicationCacheHost::EventID id)
{
- callListener(eventNames().checkingEvent, m_onCheckingListener.get());
-}
-
-void DOMApplicationCache::callErrorListener()
-{
- callListener(eventNames().errorEvent, m_onErrorListener.get());
-}
-
-void DOMApplicationCache::callNoUpdateListener()
-{
- callListener(eventNames().noupdateEvent, m_onNoUpdateListener.get());
-}
-
-void DOMApplicationCache::callDownloadingListener()
-{
- callListener(eventNames().downloadingEvent, m_onDownloadingListener.get());
-}
-
-void DOMApplicationCache::callProgressListener()
-{
- callListener(eventNames().progressEvent, m_onProgressListener.get());
-}
-
-void DOMApplicationCache::callUpdateReadyListener()
-{
- callListener(eventNames().updatereadyEvent, m_onUpdateReadyListener.get());
+ switch (id) {
+ case ApplicationCacheHost::CHECKING_EVENT:
+ return eventNames().checkingEvent;
+ case ApplicationCacheHost::ERROR_EVENT:
+ return eventNames().errorEvent;
+ case ApplicationCacheHost::NOUPDATE_EVENT:
+ return eventNames().noupdateEvent;
+ case ApplicationCacheHost::DOWNLOADING_EVENT:
+ return eventNames().downloadingEvent;
+ case ApplicationCacheHost::PROGRESS_EVENT:
+ return eventNames().progressEvent;
+ case ApplicationCacheHost::UPDATEREADY_EVENT:
+ return eventNames().updatereadyEvent;
+ case ApplicationCacheHost::CACHED_EVENT:
+ return eventNames().cachedEvent;
+ case ApplicationCacheHost::OBSOLETE_EVENT:
+ return eventNames().obsoleteEvent;
+ }
+ ASSERT_NOT_REACHED();
+ return eventNames().errorEvent;
}
-void DOMApplicationCache::callCachedListener()
+ApplicationCacheHost::EventID DOMApplicationCache::toEventID(const AtomicString& eventType)
{
- callListener(eventNames().cachedEvent, m_onCachedListener.get());
+ if (eventType == eventNames().checkingEvent)
+ return ApplicationCacheHost::CHECKING_EVENT;
+ if (eventType == eventNames().errorEvent)
+ return ApplicationCacheHost::ERROR_EVENT;
+ if (eventType == eventNames().noupdateEvent)
+ return ApplicationCacheHost::NOUPDATE_EVENT;
+ if (eventType == eventNames().downloadingEvent)
+ return ApplicationCacheHost::DOWNLOADING_EVENT;
+ if (eventType == eventNames().progressEvent)
+ return ApplicationCacheHost::PROGRESS_EVENT;
+ if (eventType == eventNames().updatereadyEvent)
+ return ApplicationCacheHost::UPDATEREADY_EVENT;
+ if (eventType == eventNames().cachedEvent)
+ return ApplicationCacheHost::CACHED_EVENT;
+ if (eventType == eventNames().obsoleteEvent)
+ return ApplicationCacheHost::OBSOLETE_EVENT;
+
+ ASSERT_NOT_REACHED();
+ return ApplicationCacheHost::ERROR_EVENT;
}
-void DOMApplicationCache::callObsoleteListener()
-{
- callListener(eventNames().obsoleteEvent, m_onObsoleteListener.get());
-}
#if USE(V8)
RefPtr<EventListener>* DOMApplicationCache::getAttributeEventListenerStorage(const AtomicString& eventType)
diff --git a/WebCore/loader/appcache/DOMApplicationCache.h b/WebCore/loader/appcache/DOMApplicationCache.h
index 57b37bc..ade0fcf 100644
--- a/WebCore/loader/appcache/DOMApplicationCache.h
+++ b/WebCore/loader/appcache/DOMApplicationCache.h
@@ -28,6 +28,7 @@
#if ENABLE(OFFLINE_WEB_APPLICATIONS)
+#include "ApplicationCacheHost.h"
#include "AtomicStringHash.h"
#include "EventTarget.h"
#include "EventListener.h"
@@ -38,41 +39,34 @@
namespace WebCore {
-class ApplicationCache;
class AtomicStringImpl;
-class DOMStringList;
class Frame;
class KURL;
class String;
-
+
class DOMApplicationCache : public RefCounted<DOMApplicationCache>, public EventTarget {
public:
static PassRefPtr<DOMApplicationCache> create(Frame* frame) { return adoptRef(new DOMApplicationCache(frame)); }
- void disconnectFrame();
+ ~DOMApplicationCache() { ASSERT(!m_frame); }
- enum Status {
- UNCACHED = 0,
- IDLE = 1,
- CHECKING = 2,
- DOWNLOADING = 3,
- UPDATEREADY = 4,
- OBSOLETE = 5
- };
+ void disconnectFrame();
unsigned short status() const;
-
void update(ExceptionCode&);
void swapCache(ExceptionCode&);
-
- PassRefPtr<DOMStringList> items();
- bool hasItem(const KURL&, ExceptionCode&);
- void add(const KURL&, ExceptionCode&);
- void remove(const KURL&, ExceptionCode&);
+
+ // Event listener attributes by EventID
+
+ void setAttributeEventListener(ApplicationCacheHost::EventID id, PassRefPtr<EventListener> eventListener) { m_attributeEventListeners[id] = eventListener; }
+ EventListener* getAttributeEventListener(ApplicationCacheHost::EventID id) const { return m_attributeEventListeners[id].get(); }
+ void clearAttributeEventListener(ApplicationCacheHost::EventID id) { m_attributeEventListeners[id] = 0; }
+ void callEventListener(ApplicationCacheHost::EventID id) { callListener(toEventType(id), getAttributeEventListener(id)); }
+
+ // EventTarget impl
virtual void addEventListener(const AtomicString& eventType, PassRefPtr<EventListener>, bool useCapture);
virtual void removeEventListener(const AtomicString& eventType, EventListener*, bool useCapture);
virtual bool dispatchEvent(PassRefPtr<Event>, ExceptionCode&);
-
typedef Vector<RefPtr<EventListener> > ListenerVector;
typedef HashMap<AtomicString, ListenerVector> EventListenersMap;
EventListenersMap& eventListeners() { return m_eventListeners; }
@@ -80,33 +74,36 @@ public:
using RefCounted<DOMApplicationCache>::ref;
using RefCounted<DOMApplicationCache>::deref;
- void setOnchecking(PassRefPtr<EventListener> eventListener) { m_onCheckingListener = eventListener; }
- EventListener* onchecking() const { return m_onCheckingListener.get(); }
+ // Explicitly named attribute event listener helpers
- void setOnerror(PassRefPtr<EventListener> eventListener) { m_onErrorListener = eventListener; }
- EventListener* onerror() const { return m_onErrorListener.get(); }
+ void setOnchecking(PassRefPtr<EventListener> listener) { setAttributeEventListener(ApplicationCacheHost::CHECKING_EVENT, listener); }
+ EventListener* onchecking() const { return getAttributeEventListener(ApplicationCacheHost::CHECKING_EVENT); }
- void setOnnoupdate(PassRefPtr<EventListener> eventListener) { m_onNoUpdateListener = eventListener; }
- EventListener* onnoupdate() const { return m_onNoUpdateListener.get(); }
+ void setOnerror(PassRefPtr<EventListener> listener) { setAttributeEventListener(ApplicationCacheHost::ERROR_EVENT, listener);}
+ EventListener* onerror() const { return getAttributeEventListener(ApplicationCacheHost::ERROR_EVENT); }
- void setOndownloading(PassRefPtr<EventListener> eventListener) { m_onDownloadingListener = eventListener; }
- EventListener* ondownloading() const { return m_onDownloadingListener.get(); }
-
- void setOnprogress(PassRefPtr<EventListener> eventListener) { m_onProgressListener = eventListener; }
- EventListener* onprogress() const { return m_onProgressListener.get(); }
+ void setOnnoupdate(PassRefPtr<EventListener> listener) { setAttributeEventListener(ApplicationCacheHost::NOUPDATE_EVENT, listener); }
+ EventListener* onnoupdate() const { return getAttributeEventListener(ApplicationCacheHost::NOUPDATE_EVENT); }
+
+ void setOndownloading(PassRefPtr<EventListener> listener) { setAttributeEventListener(ApplicationCacheHost::DOWNLOADING_EVENT, listener); }
+ EventListener* ondownloading() const { return getAttributeEventListener(ApplicationCacheHost::DOWNLOADING_EVENT); }
+
+ void setOnprogress(PassRefPtr<EventListener> listener) { setAttributeEventListener(ApplicationCacheHost::PROGRESS_EVENT, listener); }
+ EventListener* onprogress() const { return getAttributeEventListener(ApplicationCacheHost::PROGRESS_EVENT); }
- void setOnupdateready(PassRefPtr<EventListener> eventListener) { m_onUpdateReadyListener = eventListener; }
- EventListener* onupdateready() const { return m_onUpdateReadyListener.get(); }
+ void setOnupdateready(PassRefPtr<EventListener> listener) { setAttributeEventListener(ApplicationCacheHost::UPDATEREADY_EVENT, listener); }
+ EventListener* onupdateready() const { return getAttributeEventListener(ApplicationCacheHost::UPDATEREADY_EVENT); }
- void setOncached(PassRefPtr<EventListener> eventListener) { m_onCachedListener = eventListener; }
- EventListener* oncached() const { return m_onCachedListener.get(); }
+ void setOncached(PassRefPtr<EventListener> listener) { setAttributeEventListener(ApplicationCacheHost::CACHED_EVENT, listener); }
+ EventListener* oncached() const { return getAttributeEventListener(ApplicationCacheHost::CACHED_EVENT); }
- void setOnobsolete(PassRefPtr<EventListener> eventListener) { m_onObsoleteListener = eventListener; }
- EventListener* onobsolete() const { return m_onObsoleteListener.get(); }
+ void setOnobsolete(PassRefPtr<EventListener> listener) { setAttributeEventListener(ApplicationCacheHost::OBSOLETE_EVENT, listener); }
+ EventListener* onobsolete() const { return getAttributeEventListener(ApplicationCacheHost::OBSOLETE_EVENT); }
virtual ScriptExecutionContext* scriptExecutionContext() const;
DOMApplicationCache* toDOMApplicationCache() { return this; }
+#ifdef MANUAL_MERGE_REQUIRED
void callCheckingListener();
void callErrorListener();
void callNoUpdateListener();
@@ -122,29 +119,28 @@ public:
void clearAttributeEventListener(const AtomicString& eventType);
#endif
+#else // MANUAL_MERGE_REQUIRED
+ static const AtomicString& toEventType(ApplicationCacheHost::EventID id);
+ static ApplicationCacheHost::EventID toEventID(const AtomicString& eventType);
+
+#endif // MANUAL_MERGE_REQUIRED
private:
DOMApplicationCache(Frame*);
+
void callListener(const AtomicString& eventType, EventListener*);
virtual void refEventTarget() { ref(); }
virtual void derefEventTarget() { deref(); }
- ApplicationCache* associatedCache() const;
+ ApplicationCacheHost* applicationCacheHost() const;
bool swapCache();
#if USE(V8)
RefPtr<EventListener>* getAttributeEventListenerStorage(const AtomicString& eventType);
#endif
- RefPtr<EventListener> m_onCheckingListener;
- RefPtr<EventListener> m_onErrorListener;
- RefPtr<EventListener> m_onNoUpdateListener;
- RefPtr<EventListener> m_onDownloadingListener;
- RefPtr<EventListener> m_onProgressListener;
- RefPtr<EventListener> m_onUpdateReadyListener;
- RefPtr<EventListener> m_onCachedListener;
- RefPtr<EventListener> m_onObsoleteListener;
-
+ RefPtr<EventListener> m_attributeEventListeners[ApplicationCacheHost::OBSOLETE_EVENT + 1];
+
EventListenersMap m_eventListeners;
Frame* m_frame;
diff --git a/WebCore/loader/appcache/DOMApplicationCache.idl b/WebCore/loader/appcache/DOMApplicationCache.idl
index 1156c9c..ebc1d19 100644
--- a/WebCore/loader/appcache/DOMApplicationCache.idl
+++ b/WebCore/loader/appcache/DOMApplicationCache.idl
@@ -43,17 +43,6 @@ module offline {
void swapCache()
raises(DOMException);
-#if defined(ENABLE_APPLICATION_CACHE_DYNAMIC_ENTRIES) && ENABLE_APPLICATION_CACHE_DYNAMIC_ENTRIES
- // dynamic entries
- readonly attribute DOMStringList items;
- [Custom] boolean hasItem(in DOMString url)
- raises(DOMException);
- [Custom] void add(in DOMString uri)
- raises(DOMException);
- [Custom] void remove(in DOMString uri)
- raises(DOMException);
-#endif
-
// events
attribute EventListener onchecking;
attribute EventListener onerror;
diff --git a/WebCore/loader/appcache/ManifestParser.cpp b/WebCore/loader/appcache/ManifestParser.cpp
index 4169313..a2df825 100644
--- a/WebCore/loader/appcache/ManifestParser.cpp
+++ b/WebCore/loader/appcache/ManifestParser.cpp
@@ -114,8 +114,8 @@ bool parseManifest(const KURL& manifestURL, const char* data, int length, Manife
if (!url.isValid())
continue;
- if (url.hasRef())
- url.setRef(String());
+ if (url.hasFragmentIdentifier())
+ url.removeFragmentIdentifier();
if (!equalIgnoringCase(url.protocol(), manifestURL.protocol()))
continue;
@@ -141,8 +141,8 @@ bool parseManifest(const KURL& manifestURL, const char* data, int length, Manife
KURL namespaceURL(manifestURL, String(line.characters(), p - line.characters()));
if (!namespaceURL.isValid())
continue;
- if (namespaceURL.hasRef())
- namespaceURL.setRef(String());
+ if (namespaceURL.hasFragmentIdentifier())
+ namespaceURL.removeFragmentIdentifier();
if (!protocolHostAndPortAreEqual(manifestURL, namespaceURL))
continue;
@@ -159,8 +159,8 @@ bool parseManifest(const KURL& manifestURL, const char* data, int length, Manife
KURL fallbackURL(manifestURL, String(fallbackStart, p - fallbackStart));
if (!fallbackURL.isValid())
continue;
- if (fallbackURL.hasRef())
- fallbackURL.setRef(String());
+ if (fallbackURL.hasFragmentIdentifier())
+ fallbackURL.removeFragmentIdentifier();
if (!protocolHostAndPortAreEqual(manifestURL, fallbackURL))
continue;
diff --git a/WebCore/loader/archive/ArchiveResourceCollection.h b/WebCore/loader/archive/ArchiveResourceCollection.h
index f898a8d..9d630d1 100644
--- a/WebCore/loader/archive/ArchiveResourceCollection.h
+++ b/WebCore/loader/archive/ArchiveResourceCollection.h
@@ -39,7 +39,7 @@
namespace WebCore {
-class ArchiveResourceCollection : Noncopyable {
+class ArchiveResourceCollection : public Noncopyable {
public:
ArchiveResourceCollection();
diff --git a/WebCore/loader/icon/IconDatabase.cpp b/WebCore/loader/icon/IconDatabase.cpp
index 1f49c88..a6c2a66 100644
--- a/WebCore/loader/icon/IconDatabase.cpp
+++ b/WebCore/loader/icon/IconDatabase.cpp
@@ -27,6 +27,8 @@
#include "config.h"
#include "IconDatabase.h"
+#if ENABLE(ICONDATABASE)
+
#include "AutodrainedPool.h"
#include "DocumentLoader.h"
#include "FileSystem.h"
@@ -2080,3 +2082,5 @@ void IconDatabase::writeIconSnapshotToSQLDatabase(const IconSnapshot& snapshot)
}
} // namespace WebCore
+
+#endif // ENABLE(ICONDATABASE)
diff --git a/WebCore/loader/icon/IconDatabase.h b/WebCore/loader/icon/IconDatabase.h
index 40f641a..44ef22a 100644
--- a/WebCore/loader/icon/IconDatabase.h
+++ b/WebCore/loader/icon/IconDatabase.h
@@ -62,7 +62,7 @@ enum IconLoadDecision {
IconLoadUnknown
};
-class IconDatabase : Noncopyable {
+class IconDatabase : public Noncopyable {
// *** Main Thread Only ***
public:
@@ -165,6 +165,7 @@ private:
HashSet<String> m_pageURLsPendingImport;
HashSet<String> m_pageURLsInterestedInIcons;
HashSet<IconRecord*> m_iconsPendingReading;
+#endif // ENABLE(ICONDATABASE)
// *** Sync Thread Only ***
public:
@@ -174,6 +175,7 @@ public:
bool shouldStopThreadActivity() const;
+#if ENABLE(ICONDATABASE)
private:
static void* iconDatabaseSyncThreadStart(void *);
void* iconDatabaseSyncThread();
@@ -238,4 +240,4 @@ IconDatabase* iconDatabase();
} // namespace WebCore
-#endif
+#endif // IconDatabase_h
diff --git a/WebCore/loader/icon/IconDatabaseNone.cpp b/WebCore/loader/icon/IconDatabaseNone.cpp
index a7fb88d..03a7964 100644
--- a/WebCore/loader/icon/IconDatabaseNone.cpp
+++ b/WebCore/loader/icon/IconDatabaseNone.cpp
@@ -26,6 +26,8 @@
#include "config.h"
#include "IconDatabase.h"
+#if !ENABLE(ICONDATABASE)
+
#include "PlatformString.h"
#include "SharedBuffer.h"
#include <wtf/StdLibExtras.h>
@@ -194,4 +196,23 @@ void IconDatabase::setClient(IconDatabaseClient*)
{
}
+// ************************
+// *** Sync Thread Only ***
+// ************************
+
+void IconDatabase::importIconURLForPageURL(const String&, const String&)
+{
+}
+
+void IconDatabase::importIconDataForIconURL(PassRefPtr<SharedBuffer>, const String&)
+{
+}
+
+bool IconDatabase::shouldStopThreadActivity() const
+{
+ return true;
+}
+
} // namespace WebCore
+
+#endif // !ENABLE(ICONDATABASE)
diff --git a/WebCore/loader/icon/IconLoader.h b/WebCore/loader/icon/IconLoader.h
index a7194d8..7b96ed8 100644
--- a/WebCore/loader/icon/IconLoader.h
+++ b/WebCore/loader/icon/IconLoader.h
@@ -38,7 +38,7 @@ class Frame;
class KURL;
class SharedBuffer;
-class IconLoader : private SubresourceLoaderClient, Noncopyable {
+class IconLoader : private SubresourceLoaderClient, public Noncopyable {
public:
static std::auto_ptr<IconLoader> create(Frame*);
~IconLoader();
diff --git a/WebCore/loader/icon/PageURLRecord.h b/WebCore/loader/icon/PageURLRecord.h
index bc52f5b..f7ccb8f 100644
--- a/WebCore/loader/icon/PageURLRecord.h
+++ b/WebCore/loader/icon/PageURLRecord.h
@@ -51,7 +51,7 @@ public:
String iconURL;
};
-class PageURLRecord : Noncopyable {
+class PageURLRecord : public Noncopyable {
public:
PageURLRecord(const String& pageURL);
~PageURLRecord();
diff --git a/WebCore/loader/icon/wince/IconDatabaseWince.cpp b/WebCore/loader/icon/wince/IconDatabaseWince.cpp
new file mode 100644
index 0000000..e6d686c
--- /dev/null
+++ b/WebCore/loader/icon/wince/IconDatabaseWince.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2007-2009 Torch Mobile Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "IconDatabase.h"
+
+#include "AutodrainedPool.h"
+#include "CString.h"
+#include "DocumentLoader.h"
+#include "FileSystem.h"
+#include "IconDatabaseClient.h"
+#include "IconRecord.h"
+#include "Image.h"
+
+namespace WebCore {
+
+// Function to obtain the global icon database.
+IconDatabase* iconDatabase() { return 0; }
+
+IconDatabase::IconDatabase() {}
+IconDatabase::~IconDatabase() {}
+
+void IconDatabase::setClient(IconDatabaseClient*) {}
+
+bool IconDatabase::open(const String& path) { return false; }
+void IconDatabase::close() {}
+
+void IconDatabase::removeAllIcons() {}
+
+Image* IconDatabase::iconForPageURL(const String&, const IntSize&) { return 0; }
+void IconDatabase::readIconForPageURLFromDisk(const String&) {}
+String IconDatabase::iconURLForPageURL(const String&) { return String(); }
+Image* IconDatabase::defaultIcon(const IntSize&) { return 0;}
+
+void IconDatabase::retainIconForPageURL(const String&) {}
+void IconDatabase::releaseIconForPageURL(const String&) {}
+
+void IconDatabase::setIconDataForIconURL(PassRefPtr<SharedBuffer> data, const String&) {}
+void IconDatabase::setIconURLForPageURL(const String& iconURL, const String& pageURL) {}
+
+IconLoadDecision IconDatabase::loadDecisionForIconURL(const String&, DocumentLoader*) { return IconLoadNo; }
+bool IconDatabase::iconDataKnownForIconURL(const String&) { return false; }
+
+void IconDatabase::setEnabled(bool enabled) {}
+bool IconDatabase::isEnabled() const { return false; }
+
+void IconDatabase::setPrivateBrowsingEnabled(bool flag) {}
+bool IconDatabase::isPrivateBrowsingEnabled() const { return false; }
+
+void IconDatabase::delayDatabaseCleanup() {}
+void IconDatabase::allowDatabaseCleanup() {}
+void IconDatabase::checkIntegrityBeforeOpening() {}
+
+// Support for WebCoreStatistics in WebKit
+size_t IconDatabase::pageURLMappingCount() { return 0; }
+size_t IconDatabase::retainedPageURLCount() {return 0; }
+size_t IconDatabase::iconRecordCount() { return 0; }
+size_t IconDatabase::iconRecordCountWithData() { return 0; }
+
+bool IconDatabase::isOpen() const { return false; }
+String IconDatabase::databasePath() const { return String(); }
+String IconDatabase::defaultDatabaseFilename() { return String(); }
+
+} // namespace WebCore
diff --git a/WebCore/loader/loader.cpp b/WebCore/loader/loader.cpp
index ed82e94..65d15a5 100644
--- a/WebCore/loader/loader.cpp
+++ b/WebCore/loader/loader.cpp
@@ -178,6 +178,35 @@ void Loader::resumePendingRequests()
scheduleServePendingRequests();
}
+void Loader::nonCacheRequestInFlight(const KURL& url)
+{
+ if (!url.protocolInHTTPFamily())
+ return;
+
+ AtomicString hostName = url.host();
+ RefPtr<Host> host = m_hosts.get(hostName.impl());
+ if (!host) {
+ host = Host::create(hostName, maxRequestsInFlightPerHost);
+ m_hosts.add(hostName.impl(), host);
+ }
+
+ host->nonCacheRequestInFlight();
+}
+
+void Loader::nonCacheRequestComplete(const KURL& url)
+{
+ if (!url.protocolInHTTPFamily())
+ return;
+
+ AtomicString hostName = url.host();
+ RefPtr<Host> host = m_hosts.get(hostName.impl());
+ ASSERT(host);
+ if (!host)
+ return;
+
+ host->nonCacheRequestComplete();
+}
+
void Loader::cancelRequests(DocLoader* docLoader)
{
docLoader->clearPendingPreloads();
@@ -206,6 +235,7 @@ Loader::Host::Host(const AtomicString& name, unsigned maxRequestsInFlight)
: m_name(name)
, m_maxRequestsInFlight(maxRequestsInFlight)
, m_numResourcesProcessing(0)
+ , m_nonCachedRequestsInFlight(0)
{
}
@@ -221,6 +251,17 @@ void Loader::Host::addRequest(Request* request, Priority priority)
m_requestsPending[priority].append(request);
}
+void Loader::Host::nonCacheRequestInFlight()
+{
+ ++m_nonCachedRequestsInFlight;
+}
+
+void Loader::Host::nonCacheRequestComplete()
+{
+ --m_nonCachedRequestsInFlight;
+ ASSERT(m_nonCachedRequestsInFlight >= 0);
+}
+
bool Loader::Host::hasRequests() const
{
if (!m_requestsLoading.isEmpty())
@@ -248,11 +289,12 @@ void Loader::Host::servePendingRequests(RequestQueue& requestsPending, bool& ser
Request* request = requestsPending.first();
DocLoader* docLoader = request->docLoader();
bool resourceIsCacheValidator = request->cachedResource()->isCacheValidator();
- // If the document is fully parsed and there are no pending stylesheets there won't be any more
- // resources that we would want to push to the front of the queue. Just hand off the remaining resources
- // to the networking layer.
- bool parsedAndStylesheetsKnown = !docLoader->doc()->parsing() && docLoader->doc()->haveStylesheetsLoaded();
- if (!parsedAndStylesheetsKnown && !resourceIsCacheValidator && m_requestsLoading.size() >= m_maxRequestsInFlight) {
+
+ // For named hosts - which are only http(s) hosts - we should always enforce the connection limit.
+ // For non-named hosts - everything but http(s) - we should only enforce the limit if the document isn't done parsing
+ // and we don't know all stylesheets yet.
+ bool shouldLimitRequests = !m_name.isNull() || docLoader->doc()->parsing() || !docLoader->doc()->haveStylesheetsLoaded();
+ if (shouldLimitRequests && m_requestsLoading.size() + m_nonCachedRequestsInFlight >= m_maxRequestsInFlight) {
serveLowerPriority = false;
return;
}
diff --git a/WebCore/loader/loader.h b/WebCore/loader/loader.h
index c5b9416..d0a526f 100644
--- a/WebCore/loader/loader.h
+++ b/WebCore/loader/loader.h
@@ -35,9 +35,10 @@ namespace WebCore {
class CachedResource;
class DocLoader;
+ class KURL;
class Request;
- class Loader : Noncopyable {
+ class Loader : public Noncopyable {
public:
Loader();
~Loader();
@@ -52,6 +53,9 @@ namespace WebCore {
bool isSuspendingPendingRequests() { return m_isSuspendingPendingRequests; }
void suspendPendingRequests();
void resumePendingRequests();
+
+ void nonCacheRequestInFlight(const KURL&);
+ void nonCacheRequestComplete(const KURL&);
private:
Priority determinePriority(const CachedResource*) const;
@@ -69,11 +73,13 @@ namespace WebCore {
const AtomicString& name() const { return m_name; }
void addRequest(Request*, Priority);
+ void nonCacheRequestInFlight();
+ void nonCacheRequestComplete();
void servePendingRequests(Priority minimumPriority = Low);
void cancelRequests(DocLoader*);
bool hasRequests() const;
- bool processingResource() const { return m_numResourcesProcessing != 0; }
+ bool processingResource() const { return m_numResourcesProcessing != 0 || m_nonCachedRequestsInFlight !=0; }
private:
Host(const AtomicString&, unsigned);
@@ -94,6 +100,7 @@ namespace WebCore {
const AtomicString m_name;
const int m_maxRequestsInFlight;
int m_numResourcesProcessing;
+ int m_nonCachedRequestsInFlight;
};
typedef HashMap<AtomicStringImpl*, RefPtr<Host> > HostMap;
HostMap m_hosts;