summaryrefslogtreecommitdiffstats
path: root/WebCore/loader
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2009-10-08 17:19:54 +0100
committerSteve Block <steveblock@google.com>2009-10-20 00:41:58 +0100
commit231d4e3152a9c27a73b6ac7badbe6be673aa3ddf (patch)
treea6c7e2d6cd7bfa7011cc39abbb436142d7a4a7c8 /WebCore/loader
parente196732677050bd463301566a68a643b6d14b907 (diff)
downloadexternal_webkit-231d4e3152a9c27a73b6ac7badbe6be673aa3ddf.zip
external_webkit-231d4e3152a9c27a73b6ac7badbe6be673aa3ddf.tar.gz
external_webkit-231d4e3152a9c27a73b6ac7badbe6be673aa3ddf.tar.bz2
Merge webkit.org at R49305 : Automatic merge by git.
Change-Id: I8968561bc1bfd72b8923b7118d3728579c6dbcc7
Diffstat (limited to 'WebCore/loader')
-rw-r--r--WebCore/loader/Cache.cpp9
-rw-r--r--WebCore/loader/CachedFont.cpp15
-rw-r--r--WebCore/loader/CachedResource.cpp25
-rw-r--r--WebCore/loader/CachedResource.h9
-rw-r--r--WebCore/loader/CachedResourceClient.h4
-rw-r--r--WebCore/loader/CachedResourceHandle.h3
-rw-r--r--WebCore/loader/CrossOriginPreflightResultCache.cpp17
-rw-r--r--WebCore/loader/CrossOriginPreflightResultCache.h1
-rw-r--r--WebCore/loader/DocLoader.cpp37
-rw-r--r--WebCore/loader/DocumentLoader.cpp15
-rw-r--r--WebCore/loader/DocumentLoader.h8
-rw-r--r--WebCore/loader/DocumentThreadableLoader.cpp245
-rw-r--r--WebCore/loader/DocumentThreadableLoader.h28
-rw-r--r--WebCore/loader/EmptyClients.h21
-rw-r--r--WebCore/loader/FTPDirectoryDocument.cpp8
-rw-r--r--WebCore/loader/FTPDirectoryDocument.h4
-rw-r--r--WebCore/loader/FTPDirectoryParser.cpp144
-rw-r--r--WebCore/loader/FrameLoader.cpp1079
-rw-r--r--WebCore/loader/FrameLoader.h168
-rw-r--r--WebCore/loader/FrameLoaderClient.h16
-rw-r--r--WebCore/loader/FrameLoaderTypes.h6
-rw-r--r--WebCore/loader/ImageDocument.cpp27
-rw-r--r--WebCore/loader/ImageDocument.h4
-rw-r--r--WebCore/loader/MainResourceLoader.cpp30
-rw-r--r--WebCore/loader/MediaDocument.cpp4
-rw-r--r--WebCore/loader/MediaDocument.h13
-rw-r--r--WebCore/loader/PlaceholderDocument.cpp2
-rw-r--r--WebCore/loader/PlaceholderDocument.h2
-rw-r--r--WebCore/loader/PluginDocument.cpp4
-rw-r--r--WebCore/loader/PluginDocument.h4
-rw-r--r--WebCore/loader/PolicyCallback.cpp133
-rw-r--r--WebCore/loader/PolicyCallback.h80
-rw-r--r--WebCore/loader/PolicyChecker.cpp197
-rw-r--r--WebCore/loader/PolicyChecker.h97
-rw-r--r--WebCore/loader/RedirectScheduler.cpp374
-rw-r--r--WebCore/loader/RedirectScheduler.h81
-rw-r--r--WebCore/loader/ResourceLoader.cpp5
-rw-r--r--WebCore/loader/SubresourceLoader.cpp7
-rw-r--r--WebCore/loader/TextDocument.h4
-rw-r--r--WebCore/loader/TextResourceDecoder.cpp26
-rw-r--r--WebCore/loader/ThreadableLoader.cpp12
-rw-r--r--WebCore/loader/ThreadableLoader.h32
-rw-r--r--WebCore/loader/UserStyleSheetLoader.cpp62
-rw-r--r--WebCore/loader/UserStyleSheetLoader.h57
-rw-r--r--WebCore/loader/WorkerThreadableLoader.cpp22
-rw-r--r--WebCore/loader/WorkerThreadableLoader.h12
-rw-r--r--WebCore/loader/appcache/ApplicationCache.cpp5
-rw-r--r--WebCore/loader/appcache/ApplicationCache.h3
-rw-r--r--WebCore/loader/appcache/ApplicationCacheGroup.cpp9
-rw-r--r--WebCore/loader/appcache/ApplicationCacheGroup.h4
-rw-r--r--WebCore/loader/appcache/ApplicationCacheHost.cpp14
-rw-r--r--WebCore/loader/appcache/ApplicationCacheHost.h2
-rw-r--r--WebCore/loader/appcache/ApplicationCacheStorage.cpp43
-rw-r--r--WebCore/loader/appcache/DOMApplicationCache.cpp115
-rw-r--r--WebCore/loader/appcache/DOMApplicationCache.h59
-rw-r--r--WebCore/loader/appcache/DOMApplicationCache.idl2
-rw-r--r--WebCore/loader/appcache/ManifestParser.cpp9
-rw-r--r--WebCore/loader/appcache/ManifestParser.h1
-rw-r--r--WebCore/loader/archive/cf/LegacyWebArchive.cpp6
-rw-r--r--WebCore/loader/icon/IconDatabase.cpp26
-rw-r--r--WebCore/loader/icon/IconDatabaseNone.cpp2
-rw-r--r--WebCore/loader/loader.cpp6
62 files changed, 2005 insertions, 1454 deletions
diff --git a/WebCore/loader/Cache.cpp b/WebCore/loader/Cache.cpp
index 6eeba77..1f28709 100644
--- a/WebCore/loader/Cache.cpp
+++ b/WebCore/loader/Cache.cpp
@@ -34,6 +34,7 @@
#include "FrameView.h"
#include "Image.h"
#include "ResourceHandle.h"
+#include "SecurityOrigin.h"
#include <stdio.h>
#include <wtf/CurrentTime.h>
@@ -105,7 +106,7 @@ CachedResource* Cache::requestResource(DocLoader* docLoader, CachedResource::Typ
if (resource && requestIsPreload && !resource->isPreloaded())
return 0;
- if (FrameLoader::restrictAccessToLocal() && !FrameLoader::canLoad(url, String(), docLoader->doc())) {
+ if (SecurityOrigin::restrictAccessToLocal() && !SecurityOrigin::canLoad(url, String(), docLoader->doc())) {
Document* doc = docLoader->doc();
if (doc && !requestIsPreload)
FrameLoader::reportLocalLoadFailed(doc->frame(), url.string());
@@ -183,6 +184,7 @@ void Cache::revalidateResource(CachedResource* resource, DocLoader* docLoader)
{
ASSERT(resource);
ASSERT(resource->inCache());
+ ASSERT(resource == m_resources.get(resource->url()));
ASSERT(!disabled());
if (resource->resourceToRevalidate())
return;
@@ -191,7 +193,7 @@ void Cache::revalidateResource(CachedResource* resource, DocLoader* docLoader)
return;
}
const String& url = resource->url();
- CachedResource* newResource = createResource(resource->type(), KURL(url), resource->encoding());
+ CachedResource* newResource = createResource(resource->type(), KURL(ParsedURLString, url), resource->encoding());
newResource->setResourceToRevalidate(resource);
evict(resource);
m_resources.set(url, newResource);
@@ -206,6 +208,7 @@ void Cache::revalidationSucceeded(CachedResource* revalidatingResource, const Re
ASSERT(resource);
ASSERT(!resource->inCache());
ASSERT(resource->isLoaded());
+ ASSERT(revalidatingResource->inCache());
evict(revalidatingResource);
@@ -352,7 +355,7 @@ void Cache::pruneDeadResources()
current = m_allResources[i].m_tail;
while (current) {
CachedResource* prev = current->m_prevInAllResourcesList;
- if (!current->hasClients() && !current->isPreloaded()) {
+ if (!current->hasClients() && !current->isPreloaded() && !current->isCacheValidator()) {
evict(current);
// If evict() caused pruneDeadResources() to be re-entered, bail out. This can happen when removing an
// SVG CachedImage that has subresources.
diff --git a/WebCore/loader/CachedFont.cpp b/WebCore/loader/CachedFont.cpp
index dfb9dd8..9cf152d 100644
--- a/WebCore/loader/CachedFont.cpp
+++ b/WebCore/loader/CachedFont.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Torch Mobile, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,12 +27,16 @@
#include "config.h"
#include "CachedFont.h"
+#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) || (PLATFORM(CHROMIUM) && (PLATFORM(WIN_OS) || PLATFORM(LINUX))) || PLATFORM(HAIKU) || PLATFORM(WINCE)
+#define STORE_FONT_CUSTOM_PLATFORM_DATA
+#endif
+
#include "Cache.h"
#include "CachedResourceClient.h"
#include "CachedResourceClientWalker.h"
#include "DOMImplementation.h"
#include "FontPlatformData.h"
-#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) || (PLATFORM(CHROMIUM) && (PLATFORM(WIN_OS) || PLATFORM(LINUX)))
+#ifdef STORE_FONT_CUSTOM_PLATFORM_DATA
#include "FontCustomPlatformData.h"
#endif
#include "TextResourceDecoder.h"
@@ -60,7 +65,7 @@ CachedFont::CachedFont(const String &url)
CachedFont::~CachedFont()
{
-#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) || (PLATFORM(CHROMIUM) && (PLATFORM(WIN_OS) || PLATFORM(LINUX)))
+#ifdef STORE_FONT_CUSTOM_PLATFORM_DATA
delete m_fontData;
#endif
}
@@ -98,7 +103,7 @@ void CachedFont::beginLoadIfNeeded(DocLoader* dl)
bool CachedFont::ensureCustomFontData()
{
-#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) || (PLATFORM(CHROMIUM) && (PLATFORM(WIN_OS) || PLATFORM(LINUX)))
+#ifdef STORE_FONT_CUSTOM_PLATFORM_DATA
#if ENABLE(SVG_FONTS)
ASSERT(!m_isSVGFont);
#endif
@@ -117,7 +122,7 @@ FontPlatformData CachedFont::platformDataFromCustomData(float size, bool bold, b
if (m_externalSVGDocument)
return FontPlatformData(size, bold, italic);
#endif
-#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) || (PLATFORM(CHROMIUM) && (PLATFORM(WIN_OS) || PLATFORM(LINUX)))
+#ifdef STORE_FONT_CUSTOM_PLATFORM_DATA
ASSERT(m_fontData);
return m_fontData->fontPlatformData(static_cast<int>(size), bold, italic, renderingMode);
#else
@@ -173,7 +178,7 @@ SVGFontElement* CachedFont::getSVGFontById(const String& fontName) const
void CachedFont::allClientsRemoved()
{
-#if PLATFORM(CG) || PLATFORM(QT) || PLATFORM(GTK) || (PLATFORM(CHROMIUM) && (PLATFORM(WIN_OS) || PLATFORM(LINUX)))
+#ifdef STORE_FONT_CUSTOM_PLATFORM_DATA
if (m_fontData) {
delete m_fontData;
m_fontData = 0;
diff --git a/WebCore/loader/CachedResource.cpp b/WebCore/loader/CachedResource.cpp
index 478873f..43de633 100644
--- a/WebCore/loader/CachedResource.cpp
+++ b/WebCore/loader/CachedResource.cpp
@@ -59,7 +59,7 @@ CachedResource::CachedResource(const String& url, Type type)
, m_docLoader(0)
, m_handleCount(0)
, m_resourceToRevalidate(0)
- , m_isBeingRevalidated(false)
+ , m_proxyResource(0)
{
#ifndef NDEBUG
cachedResourceLeakCounter.increment();
@@ -89,6 +89,8 @@ CachedResource::CachedResource(const String& url, Type type)
CachedResource::~CachedResource()
{
+ ASSERT(!m_resourceToRevalidate); // Should be true because canDelete() checks this.
+ ASSERT(canDelete());
ASSERT(!inCache());
ASSERT(!m_deleted);
ASSERT(url().isNull() || cache()->resourceForURL(url()) != this);
@@ -97,9 +99,6 @@ CachedResource::~CachedResource()
cachedResourceLeakCounter.decrement();
#endif
- if (m_resourceToRevalidate)
- m_resourceToRevalidate->m_isBeingRevalidated = false;
-
if (m_docLoader)
m_docLoader->removeCachedResource(this);
}
@@ -298,18 +297,26 @@ void CachedResource::setResourceToRevalidate(CachedResource* resource)
ASSERT(resource);
ASSERT(!m_resourceToRevalidate);
ASSERT(resource != this);
- ASSERT(!resource->m_isBeingRevalidated);
ASSERT(m_handlesToRevalidate.isEmpty());
ASSERT(resource->type() == type());
- resource->m_isBeingRevalidated = true;
+
+ // The following assert should be investigated whenever it occurs. Although it should never fire, it currently does in rare circumstances.
+ // https://bugs.webkit.org/show_bug.cgi?id=28604.
+ // So the code needs to be robust to this assert failing thus the "if (m_resourceToRevalidate->m_proxyResource == this)" in CachedResource::clearResourceToRevalidate.
+ ASSERT(!resource->m_proxyResource);
+
+ resource->m_proxyResource = this;
m_resourceToRevalidate = resource;
}
void CachedResource::clearResourceToRevalidate()
{
ASSERT(m_resourceToRevalidate);
- m_resourceToRevalidate->m_isBeingRevalidated = false;
- m_resourceToRevalidate->deleteIfPossible();
+ // A resource may start revalidation before this method has been called, so check that this resource is still the proxy resource before clearing it out.
+ if (m_resourceToRevalidate->m_proxyResource == this) {
+ m_resourceToRevalidate->m_proxyResource = 0;
+ m_resourceToRevalidate->deleteIfPossible();
+ }
m_handlesToRevalidate.clear();
m_resourceToRevalidate = 0;
deleteIfPossible();
@@ -403,7 +410,7 @@ bool CachedResource::mustRevalidate(CachePolicy cachePolicy) const
bool CachedResource::isSafeToMakePurgeable() const
{
- return !hasClients() && !m_isBeingRevalidated && !m_resourceToRevalidate;
+ return !hasClients() && !m_proxyResource && !m_resourceToRevalidate;
}
bool CachedResource::makePurgeable(bool purgeable)
diff --git a/WebCore/loader/CachedResource.h b/WebCore/loader/CachedResource.h
index babdf89..05d24fc 100644
--- a/WebCore/loader/CachedResource.h
+++ b/WebCore/loader/CachedResource.h
@@ -129,7 +129,7 @@ public:
// while still being referenced. This means the object should delete itself
// if the number of clients observing it ever drops to 0.
// The resource can be brought back to cache after successful revalidation.
- void setInCache(bool b) { m_inCache = b; if (b) m_isBeingRevalidated = false; }
+ void setInCache(bool inCache) { m_inCache = inCache; }
bool inCache() const { return m_inCache; }
void setInLiveDecodedResourcesList(bool b) { m_inLiveDecodedResourcesList = b; }
@@ -142,7 +142,7 @@ public:
void setResponse(const ResourceResponse&);
const ResourceResponse& response() const { return m_response; }
- bool canDelete() const { return !hasClients() && !m_request && !m_preloadCount && !m_handleCount && !m_resourceToRevalidate && !m_isBeingRevalidated; }
+ bool canDelete() const { return !hasClients() && !m_request && !m_preloadCount && !m_handleCount && !m_resourceToRevalidate && !m_proxyResource; }
bool isExpired() const;
@@ -251,7 +251,10 @@ private:
// to to be clients of m_resourceToRevalidate and the resource is deleted. If not, the field is zeroed and this
// resources becomes normal resource load.
CachedResource* m_resourceToRevalidate;
- bool m_isBeingRevalidated;
+
+ // If this field is non-null, the resource has a proxy for checking whether it is still up to date (see m_resourceToRevalidate).
+ CachedResource* m_proxyResource;
+
// These handles will need to be updated to point to the m_resourceToRevalidate in case we get 304 response.
HashSet<CachedResourceHandleBase*> m_handlesToRevalidate;
};
diff --git a/WebCore/loader/CachedResourceClient.h b/WebCore/loader/CachedResourceClient.h
index 2e0b15b..dd9bb94 100644
--- a/WebCore/loader/CachedResourceClient.h
+++ b/WebCore/loader/CachedResourceClient.h
@@ -25,6 +25,8 @@
#ifndef CachedResourceClient_h
#define CachedResourceClient_h
+#include <wtf/FastAllocBase.h>
+
#if ENABLE(XBL)
namespace XBL {
class XBLDocument;
@@ -48,7 +50,7 @@ namespace WebCore {
* inherit from this class and overload one of the 3 functions
*
*/
- class CachedResourceClient
+ class CachedResourceClient : public FastAllocBase
{
public:
virtual ~CachedResourceClient() { }
diff --git a/WebCore/loader/CachedResourceHandle.h b/WebCore/loader/CachedResourceHandle.h
index 13c03c7..9d45b94 100644
--- a/WebCore/loader/CachedResourceHandle.h
+++ b/WebCore/loader/CachedResourceHandle.h
@@ -38,7 +38,8 @@ namespace WebCore {
bool operator!() const { return !m_resource; }
// This conversion operator allows implicit conversion to bool but not to other integer types.
- typedef CachedResource* CachedResourceHandleBase::*UnspecifiedBoolType;
+ // Parenthesis is needed for winscw compiler to resolve class qualifier in this case.
+ typedef CachedResource* (CachedResourceHandleBase::*UnspecifiedBoolType);
operator UnspecifiedBoolType() const { return m_resource ? &CachedResourceHandleBase::m_resource : 0; }
protected:
diff --git a/WebCore/loader/CrossOriginPreflightResultCache.cpp b/WebCore/loader/CrossOriginPreflightResultCache.cpp
index 4bd05b2..cea66b1 100644
--- a/WebCore/loader/CrossOriginPreflightResultCache.cpp
+++ b/WebCore/loader/CrossOriginPreflightResultCache.cpp
@@ -30,6 +30,8 @@
#include "CrossOriginAccessControl.h"
#include "ResourceResponse.h"
#include <wtf/CurrentTime.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/Threading.h>
namespace WebCore {
@@ -64,8 +66,7 @@ static void addToAccessControlAllowList(const String& string, unsigned start, un
while (end && isSpaceOrNewline((*stringImpl)[end]))
--end;
- // substringCopy() is called on the strings because the cache is accessed on multiple threads.
- set.add(string.substringCopy(start, end - start + 1));
+ set.add(string.substring(start, end - start + 1));
}
template<class HashType>
@@ -137,20 +138,20 @@ bool CrossOriginPreflightResultCacheItem::allowsRequest(bool includeCredentials,
CrossOriginPreflightResultCache& CrossOriginPreflightResultCache::shared()
{
- AtomicallyInitializedStatic(CrossOriginPreflightResultCache&, cache = *new CrossOriginPreflightResultCache);
+ DEFINE_STATIC_LOCAL(CrossOriginPreflightResultCache, cache, ());
+ ASSERT(isMainThread());
return cache;
}
void CrossOriginPreflightResultCache::appendEntry(const String& origin, const KURL& url, CrossOriginPreflightResultCacheItem* preflightResult)
{
- MutexLocker lock(m_mutex);
- // Note that the entry may already be present in the HashMap if another thread is accessing the same location.
- m_preflightHashMap.set(std::make_pair(origin.copy(), url.copy()), preflightResult);
+ ASSERT(isMainThread());
+ m_preflightHashMap.set(std::make_pair(origin, url), preflightResult);
}
bool CrossOriginPreflightResultCache::canSkipPreflight(const String& origin, const KURL& url, bool includeCredentials, const String& method, const HTTPHeaderMap& requestHeaders)
{
- MutexLocker lock(m_mutex);
+ ASSERT(isMainThread());
CrossOriginPreflightResultHashMap::iterator cacheIt = m_preflightHashMap.find(std::make_pair(origin, url));
if (cacheIt == m_preflightHashMap.end())
return false;
@@ -165,7 +166,7 @@ bool CrossOriginPreflightResultCache::canSkipPreflight(const String& origin, con
void CrossOriginPreflightResultCache::empty()
{
- MutexLocker lock(m_mutex);
+ ASSERT(isMainThread());
deleteAllValues(m_preflightHashMap);
m_preflightHashMap.clear();
}
diff --git a/WebCore/loader/CrossOriginPreflightResultCache.h b/WebCore/loader/CrossOriginPreflightResultCache.h
index f71d1c8..97b526a 100644
--- a/WebCore/loader/CrossOriginPreflightResultCache.h
+++ b/WebCore/loader/CrossOriginPreflightResultCache.h
@@ -72,7 +72,6 @@ namespace WebCore {
typedef HashMap<std::pair<String, KURL>, CrossOriginPreflightResultCacheItem*> CrossOriginPreflightResultHashMap;
CrossOriginPreflightResultHashMap m_preflightHashMap;
- Mutex m_mutex;
};
} // namespace WebCore
diff --git a/WebCore/loader/DocLoader.cpp b/WebCore/loader/DocLoader.cpp
index 9c11a88..9e97354 100644
--- a/WebCore/loader/DocLoader.cpp
+++ b/WebCore/loader/DocLoader.cpp
@@ -200,6 +200,41 @@ bool DocLoader::canRequest(CachedResource::Type type, const KURL& url)
ASSERT_NOT_REACHED();
break;
}
+
+ // Given that the load is allowed by the same-origin policy, we should
+ // check whether the load passes the mixed-content policy.
+ //
+ // Note: Currently, we always allow mixed content, but we generate a
+ // callback to the FrameLoaderClient in case the embedder wants to
+ // update any security indicators.
+ //
+ switch (type) {
+ case CachedResource::Script:
+#if ENABLE(XSLT)
+ case CachedResource::XSLStyleSheet:
+#endif
+#if ENABLE(XBL)
+ case CachedResource::XBL:
+#endif
+ // These resource can inject script into the current document.
+ if (Frame* f = frame())
+ f->loader()->checkIfRunInsecureContent(m_doc->securityOrigin(), url);
+ break;
+ case CachedResource::ImageResource:
+ case CachedResource::CSSStyleSheet:
+ case CachedResource::FontResource: {
+ // These resources can corrupt only the frame's pixels.
+ if (Frame* f = frame()) {
+ Frame* top = f->tree()->top();
+ top->loader()->checkIfDisplayInsecureContent(top->document()->securityOrigin(), url);
+ }
+ break;
+ }
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ // FIXME: Consider letting the embedder block mixed content loads.
return true;
}
@@ -224,7 +259,7 @@ CachedResource* DocLoader::requestResource(CachedResource::Type type, const Stri
if (resource) {
// Check final URL of resource to catch redirects.
// See <https://bugs.webkit.org/show_bug.cgi?id=21963>.
- if (!canRequest(type, KURL(resource->url())))
+ if (fullURL != resource->url() && !canRequest(type, KURL(ParsedURLString, resource->url())))
return 0;
m_documentResources.set(resource->url(), resource);
diff --git a/WebCore/loader/DocumentLoader.cpp b/WebCore/loader/DocumentLoader.cpp
index 4ec69a7..5ca6e58 100644
--- a/WebCore/loader/DocumentLoader.cpp
+++ b/WebCore/loader/DocumentLoader.cpp
@@ -148,7 +148,6 @@ DocumentLoader::DocumentLoader(const ResourceRequest& req, const SubstituteData&
, m_gotFirstByte(false)
, m_primaryLoadComplete(false)
, m_isClientRedirect(false)
- , m_loadingFromCachedPage(false)
, m_stopRecordingResponses(false)
, m_substituteResourceDeliveryTimer(this, &DocumentLoader::substituteResourceDeliveryTimerFired)
, m_didCreateGlobalHistoryEntry(false)
@@ -278,7 +277,7 @@ void DocumentLoader::stopLoading(DatabasePolicy databasePolicy)
Document* doc = m_frame->document();
if (loading || doc->parsing())
- m_frame->loader()->stopLoading(false, databasePolicy);
+ m_frame->loader()->stopLoading(UnloadEventPolicyNone, databasePolicy);
}
// Always cancel multipart loaders
@@ -568,7 +567,7 @@ void DocumentLoader::getSubresources(Vector<PassRefPtr<ArchiveResource> >& subre
const DocLoader::DocumentResourceMap& allResources = document->docLoader()->allCachedResources();
DocLoader::DocumentResourceMap::const_iterator end = allResources.end();
for (DocLoader::DocumentResourceMap::const_iterator it = allResources.begin(); it != end; ++it) {
- RefPtr<ArchiveResource> subresource = this->subresource(KURL(it->second->url()));
+ RefPtr<ArchiveResource> subresource = this->subresource(KURL(ParsedURLString, it->second->url()));
if (subresource)
subresources.append(subresource.release());
}
@@ -697,16 +696,6 @@ bool DocumentLoader::urlForHistoryReflectsFailure() const
return m_substituteData.isValid() || m_response.httpStatusCode() >= 400;
}
-void DocumentLoader::loadFromCachedPage(PassRefPtr<CachedPage> cachedPage)
-{
- LOG(PageCache, "WebCorePageCache: DocumentLoader %p loading from cached page %p", this, cachedPage.get());
-
- prepareForLoadStart();
- setLoadingFromCachedPage(true);
- setCommitted(true);
- frameLoader()->commitProvisionalLoad(cachedPage);
-}
-
const KURL& DocumentLoader::originalURL() const
{
return m_originalRequestCopy.url();
diff --git a/WebCore/loader/DocumentLoader.h b/WebCore/loader/DocumentLoader.h
index 134d954..1220a0e 100644
--- a/WebCore/loader/DocumentLoader.h
+++ b/WebCore/loader/DocumentLoader.h
@@ -43,8 +43,11 @@ namespace WebCore {
class Archive;
class ArchiveResource;
class ArchiveResourceCollection;
+<<<<<<< HEAD:WebCore/loader/DocumentLoader.h
#endif
class CachedPage;
+=======
+>>>>>>> webkit.org at 49305:WebCore/loader/DocumentLoader.h
class Frame;
class FrameLoader;
class MainResourceLoader;
@@ -174,10 +177,6 @@ namespace WebCore {
bool didCreateGlobalHistoryEntry() const { return m_didCreateGlobalHistoryEntry; }
void setDidCreateGlobalHistoryEntry(bool didCreateGlobalHistoryEntry) { m_didCreateGlobalHistoryEntry = didCreateGlobalHistoryEntry; }
- void loadFromCachedPage(PassRefPtr<CachedPage>);
- void setLoadingFromCachedPage(bool loading) { m_loadingFromCachedPage = loading; }
- bool isLoadingFromCachedPage() const { return m_loadingFromCachedPage; }
-
void setDefersLoading(bool);
bool startLoadingMainResource(unsigned long identifier);
@@ -264,7 +263,6 @@ namespace WebCore {
bool m_gotFirstByte;
bool m_primaryLoadComplete;
bool m_isClientRedirect;
- bool m_loadingFromCachedPage;
String m_pageTitle;
diff --git a/WebCore/loader/DocumentThreadableLoader.cpp b/WebCore/loader/DocumentThreadableLoader.cpp
index dd5ca76..8a223fd 100644
--- a/WebCore/loader/DocumentThreadableLoader.cpp
+++ b/WebCore/loader/DocumentThreadableLoader.cpp
@@ -32,8 +32,9 @@
#include "DocumentThreadableLoader.h"
#include "AuthenticationChallenge.h"
+#include "CrossOriginAccessControl.h"
+#include "CrossOriginPreflightResultCache.h"
#include "Document.h"
-#include "DocumentThreadableLoader.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "ResourceRequest.h"
@@ -43,61 +44,106 @@
namespace WebCore {
-void DocumentThreadableLoader::loadResourceSynchronously(Document* document, const ResourceRequest& request, ThreadableLoaderClient& client, StoredCredentials storedCredentials)
+void DocumentThreadableLoader::loadResourceSynchronously(Document* document, const ResourceRequest& request, ThreadableLoaderClient& client, const ThreadableLoaderOptions& options)
{
- bool sameOriginRequest = document->securityOrigin()->canRequest(request.url());
-
- Vector<char> data;
- ResourceError error;
- ResourceResponse response;
- unsigned long identifier = std::numeric_limits<unsigned long>::max();
- if (document->frame())
- identifier = document->frame()->loader()->loadResourceSynchronously(request, storedCredentials, error, response, data);
-
- // No exception for file:/// resources, see <rdar://problem/4962298>.
- // Also, if we have an HTTP response, then it wasn't a network error in fact.
- if (!error.isNull() && !request.url().isLocalFile() && response.httpStatusCode() <= 0) {
- client.didFail(error);
- return;
- }
-
- // FIXME: This check along with the one in willSendRequest is specific to xhr and
- // should be made more generic.
- if (sameOriginRequest && !document->securityOrigin()->canRequest(response.url())) {
- client.didFailRedirectCheck();
- return;
- }
-
- client.didReceiveResponse(response);
-
- const char* bytes = static_cast<const char*>(data.data());
- int len = static_cast<int>(data.size());
- client.didReceiveData(bytes, len);
-
- client.didFinishLoading(identifier);
+ // The loader will be deleted as soon as this function exits.
+ RefPtr<DocumentThreadableLoader> loader = adoptRef(new DocumentThreadableLoader(document, &client, LoadSynchronously, request, options));
+ ASSERT(loader->hasOneRef());
}
-PassRefPtr<DocumentThreadableLoader> DocumentThreadableLoader::create(Document* document, ThreadableLoaderClient* client, const ResourceRequest& request, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials, CrossOriginRedirectPolicy crossOriginRedirectPolicy)
+PassRefPtr<DocumentThreadableLoader> DocumentThreadableLoader::create(Document* document, ThreadableLoaderClient* client, const ResourceRequest& request, const ThreadableLoaderOptions& options)
{
- ASSERT(document);
- RefPtr<DocumentThreadableLoader> loader = adoptRef(new DocumentThreadableLoader(document, client, request, callbacksSetting, contentSniff, storedCredentials, crossOriginRedirectPolicy));
+ RefPtr<DocumentThreadableLoader> loader = adoptRef(new DocumentThreadableLoader(document, client, LoadAsynchronously, request, options));
if (!loader->m_loader)
loader = 0;
return loader.release();
}
-DocumentThreadableLoader::DocumentThreadableLoader(Document* document, ThreadableLoaderClient* client, const ResourceRequest& request, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials, CrossOriginRedirectPolicy crossOriginRedirectPolicy)
+DocumentThreadableLoader::DocumentThreadableLoader(Document* document, ThreadableLoaderClient* client, BlockingBehavior blockingBehavior, const ResourceRequest& request, const ThreadableLoaderOptions& options)
: m_client(client)
, m_document(document)
- , m_allowStoredCredentials(storedCredentials == AllowStoredCredentials)
+ , m_options(options)
, m_sameOriginRequest(document->securityOrigin()->canRequest(request.url()))
- , m_denyCrossOriginRedirect(crossOriginRedirectPolicy == DenyCrossOriginRedirect)
+ , m_async(blockingBehavior == LoadAsynchronously)
{
ASSERT(document);
ASSERT(client);
- ASSERT(storedCredentials == AllowStoredCredentials || storedCredentials == DoNotAllowStoredCredentials);
- ASSERT(crossOriginRedirectPolicy == DenyCrossOriginRedirect || crossOriginRedirectPolicy == AllowCrossOriginRedirect);
- m_loader = SubresourceLoader::create(document->frame(), this, request, false, callbacksSetting == SendLoadCallbacks, contentSniff == SniffContent);
+
+ if (m_sameOriginRequest || m_options.crossOriginRequestPolicy == AllowCrossOriginRequests) {
+ bool skipCanLoadCheck = false;
+ loadRequest(request, skipCanLoadCheck);
+ return;
+ }
+
+ if (m_options.crossOriginRequestPolicy == DenyCrossOriginRequests) {
+ m_client->didFail(ResourceError());
+ return;
+ }
+
+ ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl);
+
+ if (!m_options.forcePreflight && isSimpleCrossOriginAccessRequest(request.httpMethod(), request.httpHeaderFields()))
+ makeSimpleCrossOriginAccessRequest(request);
+ else {
+ m_actualRequest.set(new ResourceRequest(request));
+ m_actualRequest->setAllowCookies(m_options.allowCredentials);
+
+ if (CrossOriginPreflightResultCache::shared().canSkipPreflight(document->securityOrigin()->toString(), request.url(), m_options.allowCredentials, request.httpMethod(), request.httpHeaderFields()))
+ preflightSuccess();
+ else
+ makeCrossOriginAccessRequestWithPreflight(request);
+ }
+}
+
+void DocumentThreadableLoader::makeSimpleCrossOriginAccessRequest(const ResourceRequest& request)
+{
+ ASSERT(isSimpleCrossOriginAccessRequest(request.httpMethod(), request.httpHeaderFields()));
+
+ // Cross-origin requests are only defined for HTTP. We would catch this when checking response headers later, but there is no reason to send a request that's guaranteed to be denied.
+ if (!request.url().protocolInHTTPFamily()) {
+ m_client->didFail(ResourceError());
+ return;
+ }
+
+ // Make a copy of the passed request so that we can modify some details.
+ ResourceRequest crossOriginRequest(request);
+ crossOriginRequest.removeCredentials();
+ crossOriginRequest.setAllowCookies(m_options.allowCredentials);
+ crossOriginRequest.setHTTPOrigin(m_document->securityOrigin()->toString());
+
+ bool skipCanLoadCheck = false;
+ loadRequest(crossOriginRequest, skipCanLoadCheck);
+}
+
+void DocumentThreadableLoader::makeCrossOriginAccessRequestWithPreflight(const ResourceRequest& request)
+{
+ ResourceRequest preflightRequest(request.url());
+ preflightRequest.removeCredentials();
+ preflightRequest.setHTTPOrigin(m_document->securityOrigin()->toString());
+ preflightRequest.setAllowCookies(m_options.allowCredentials);
+ preflightRequest.setHTTPMethod("OPTIONS");
+ preflightRequest.setHTTPHeaderField("Access-Control-Request-Method", request.httpMethod());
+
+ const HTTPHeaderMap& requestHeaderFields = request.httpHeaderFields();
+
+ if (requestHeaderFields.size() > 0) {
+ Vector<UChar> headerBuffer;
+ HTTPHeaderMap::const_iterator it = requestHeaderFields.begin();
+ append(headerBuffer, it->first);
+ ++it;
+
+ HTTPHeaderMap::const_iterator end = requestHeaderFields.end();
+ for (; it != end; ++it) {
+ headerBuffer.append(',');
+ headerBuffer.append(' ');
+ append(headerBuffer, it->first);
+ }
+
+ preflightRequest.setHTTPHeaderField("Access-Control-Request-Headers", String::adopt(headerBuffer));
+ }
+
+ bool skipCanLoadCheck = false;
+ loadRequest(preflightRequest, skipCanLoadCheck);
}
DocumentThreadableLoader::~DocumentThreadableLoader()
@@ -122,8 +168,7 @@ void DocumentThreadableLoader::willSendRequest(SubresourceLoader* loader, Resour
ASSERT(m_client);
ASSERT_UNUSED(loader, loader == m_loader);
- // FIXME: This needs to be fixed to follow the redirect correctly even for cross-domain requests.
- if (m_denyCrossOriginRedirect && !m_document->securityOrigin()->canRequest(request.url())) {
+ if (!isAllowedRedirect(request.url())) {
RefPtr<DocumentThreadableLoader> protect(this);
m_client->didFailRedirectCheck();
request = ResourceRequest();
@@ -143,7 +188,31 @@ void DocumentThreadableLoader::didReceiveResponse(SubresourceLoader* loader, con
ASSERT(m_client);
ASSERT_UNUSED(loader, loader == m_loader);
- m_client->didReceiveResponse(response);
+ if (m_actualRequest) {
+ if (!passesAccessControlCheck(response, m_options.allowCredentials, m_document->securityOrigin())) {
+ preflightFailure();
+ return;
+ }
+
+ OwnPtr<CrossOriginPreflightResultCacheItem> preflightResult(new CrossOriginPreflightResultCacheItem(m_options.allowCredentials));
+ if (!preflightResult->parse(response)
+ || !preflightResult->allowsCrossOriginMethod(m_actualRequest->httpMethod())
+ || !preflightResult->allowsCrossOriginHeaders(m_actualRequest->httpHeaderFields())) {
+ preflightFailure();
+ return;
+ }
+
+ CrossOriginPreflightResultCache::shared().appendEntry(m_document->securityOrigin()->toString(), m_actualRequest->url(), preflightResult.release());
+ } else {
+ if (!m_sameOriginRequest && m_options.crossOriginRequestPolicy == UseAccessControl) {
+ if (!passesAccessControlCheck(response, m_options.allowCredentials, m_document->securityOrigin())) {
+ m_client->didFail(ResourceError());
+ return;
+ }
+ }
+
+ m_client->didReceiveResponse(response);
+ }
}
void DocumentThreadableLoader::didReceiveData(SubresourceLoader* loader, const char* data, int lengthReceived)
@@ -158,7 +227,17 @@ void DocumentThreadableLoader::didFinishLoading(SubresourceLoader* loader)
{
ASSERT(loader == m_loader);
ASSERT(m_client);
- m_client->didFinishLoading(loader->identifier());
+ didFinishLoading(loader->identifier());
+}
+
+void DocumentThreadableLoader::didFinishLoading(unsigned long identifier)
+{
+ if (m_actualRequest) {
+ ASSERT(!m_sameOriginRequest);
+ ASSERT(m_options.crossOriginRequestPolicy == UseAccessControl);
+ preflightSuccess();
+ } else
+ m_client->didFinishLoading(identifier);
}
void DocumentThreadableLoader::didFail(SubresourceLoader* loader, const ResourceError& error)
@@ -172,9 +251,9 @@ void DocumentThreadableLoader::didFail(SubresourceLoader* loader, const Resource
bool DocumentThreadableLoader::getShouldUseCredentialStorage(SubresourceLoader* loader, bool& shouldUseCredentialStorage)
{
- ASSERT_UNUSED(loader, loader == m_loader);
+ ASSERT_UNUSED(loader, loader == m_loader || !m_loader);
- if (!m_allowStoredCredentials) {
+ if (!m_options.allowCredentials) {
shouldUseCredentialStorage = false;
return true;
}
@@ -200,4 +279,76 @@ void DocumentThreadableLoader::receivedCancellation(SubresourceLoader* loader, c
m_client->didReceiveAuthenticationCancellation(challenge.failureResponse());
}
+void DocumentThreadableLoader::preflightSuccess()
+{
+ OwnPtr<ResourceRequest> actualRequest;
+ actualRequest.swap(m_actualRequest);
+
+ bool skipCanLoadCheck = true; // ok to skip load check since we already asked about the preflight request
+ loadRequest(*actualRequest, skipCanLoadCheck);
+}
+
+void DocumentThreadableLoader::preflightFailure()
+{
+ m_client->didFail(ResourceError());
+}
+
+void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, bool skipCanLoadCheck)
+{
+ if (m_async) {
+ // Don't sniff content or send load callbacks for the preflight request.
+ bool sendLoadCallbacks = m_options.sendLoadCallbacks && !m_actualRequest;
+ bool sniffContent = m_options.sniffContent && !m_actualRequest;
+
+ // Clear the loader so that any callbacks from SubresourceLoader::create will not have the old loader.
+ m_loader = 0;
+ m_loader = SubresourceLoader::create(m_document->frame(), this, request, skipCanLoadCheck, sendLoadCallbacks, sniffContent);
+ return;
+ }
+
+ // FIXME: ThreadableLoaderOptions.sniffContent is not supported for synchronous requests.
+ StoredCredentials storedCredentials = m_options.allowCredentials ? AllowStoredCredentials : DoNotAllowStoredCredentials;
+
+ Vector<char> data;
+ ResourceError error;
+ ResourceResponse response;
+ unsigned long identifier = std::numeric_limits<unsigned long>::max();
+ if (m_document->frame())
+ identifier = m_document->frame()->loader()->loadResourceSynchronously(request, storedCredentials, error, response, data);
+
+ // No exception for file:/// resources, see <rdar://problem/4962298>.
+ // Also, if we have an HTTP response, then it wasn't a network error in fact.
+ if (!error.isNull() && !request.url().isLocalFile() && response.httpStatusCode() <= 0) {
+ m_client->didFail(error);
+ return;
+ }
+
+ // FIXME: FrameLoader::loadSynchronously() does not tell us whether a redirect happened or not, so we guess by comparing the
+ // request and response URLs. This isn't a perfect test though, since a server can serve a redirect to the same URL that was
+ // requested.
+ if (request.url() != response.url() && !isAllowedRedirect(response.url())) {
+ m_client->didFailRedirectCheck();
+ return;
+ }
+
+ didReceiveResponse(0, response);
+
+ const char* bytes = static_cast<const char*>(data.data());
+ int len = static_cast<int>(data.size());
+ didReceiveData(0, bytes, len);
+
+ didFinishLoading(identifier);
+}
+
+bool DocumentThreadableLoader::isAllowedRedirect(const KURL& url)
+{
+ if (m_options.crossOriginRequestPolicy == AllowCrossOriginRequests)
+ return true;
+
+ // FIXME: We need to implement access control for each redirect. This will require some refactoring though, because the code
+ // that processes redirects doesn't know about access control and expects a synchronous answer from its client about whether
+ // a redirect should proceed.
+ return m_sameOriginRequest && m_document->securityOrigin()->canRequest(url);
+}
+
} // namespace WebCore
diff --git a/WebCore/loader/DocumentThreadableLoader.h b/WebCore/loader/DocumentThreadableLoader.h
index 465475f..64b1a22 100644
--- a/WebCore/loader/DocumentThreadableLoader.h
+++ b/WebCore/loader/DocumentThreadableLoader.h
@@ -33,19 +33,21 @@
#include "SubresourceLoaderClient.h"
#include "ThreadableLoader.h"
+#include <wtf/OwnPtr.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
#include <wtf/RefPtr.h>
namespace WebCore {
class Document;
+ class KURL;
struct ResourceRequest;
class ThreadableLoaderClient;
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, CrossOriginRedirectPolicy);
+ static void loadResourceSynchronously(Document*, const ResourceRequest&, ThreadableLoaderClient&, const ThreadableLoaderOptions&);
+ static PassRefPtr<DocumentThreadableLoader> create(Document*, ThreadableLoaderClient*, const ResourceRequest&, const ThreadableLoaderOptions&);
virtual ~DocumentThreadableLoader();
virtual void cancel();
@@ -58,7 +60,13 @@ namespace WebCore {
virtual void derefThreadableLoader() { deref(); }
private:
- DocumentThreadableLoader(Document*, ThreadableLoaderClient*, const ResourceRequest&, LoadCallbacks, ContentSniff, StoredCredentials, CrossOriginRedirectPolicy);
+ enum BlockingBehavior {
+ LoadSynchronously,
+ LoadAsynchronously
+ };
+
+ DocumentThreadableLoader(Document*, ThreadableLoaderClient*, BlockingBehavior blockingBehavior, const ResourceRequest&, const ThreadableLoaderOptions& options);
+
virtual void willSendRequest(SubresourceLoader*, ResourceRequest&, const ResourceResponse& redirectResponse);
virtual void didSendData(SubresourceLoader*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent);
@@ -71,12 +79,22 @@ namespace WebCore {
virtual void didReceiveAuthenticationChallenge(SubresourceLoader*, const AuthenticationChallenge&);
virtual void receivedCancellation(SubresourceLoader*, const AuthenticationChallenge&);
+ void didFinishLoading(unsigned long identifier);
+ void makeSimpleCrossOriginAccessRequest(const ResourceRequest& request);
+ void makeCrossOriginAccessRequestWithPreflight(const ResourceRequest& request);
+ void preflightSuccess();
+ void preflightFailure();
+
+ void loadRequest(const ResourceRequest&, bool skipCanLoadCheck);
+ bool isAllowedRedirect(const KURL&);
+
RefPtr<SubresourceLoader> m_loader;
ThreadableLoaderClient* m_client;
Document* m_document;
- bool m_allowStoredCredentials;
+ ThreadableLoaderOptions m_options;
bool m_sameOriginRequest;
- bool m_denyCrossOriginRedirect;
+ bool m_async;
+ OwnPtr<ResourceRequest> m_actualRequest; // non-null during Access Control preflight checks
};
} // namespace WebCore
diff --git a/WebCore/loader/EmptyClients.h b/WebCore/loader/EmptyClients.h
index 3f70c43..d9e09fb 100644
--- a/WebCore/loader/EmptyClients.h
+++ b/WebCore/loader/EmptyClients.h
@@ -39,6 +39,7 @@
#include "FormState.h"
#include "FrameLoaderClient.h"
#include "InspectorClient.h"
+#include "PluginHalterClient.h"
#include "ResourceError.h"
#include "SharedBuffer.h"
@@ -120,9 +121,10 @@ public:
virtual void scroll(const IntSize&, const IntRect&, const IntRect&) { }
virtual IntPoint screenToWindow(const IntPoint& p) const { return p; }
virtual IntRect windowToScreen(const IntRect& r) const { return r; }
- virtual PlatformWidget platformWindow() const { return 0; }
+ virtual PlatformPageClient platformPageClient() const { return 0; }
virtual void contentsSizeChanged(Frame*, const IntSize&) const { }
+ virtual void scrollbarsModeDidChange() const { }
virtual void mouseDidMoveOverElement(const HitTestResult&, unsigned) { }
virtual void setToolTip(const String&, TextDirection) { }
@@ -137,6 +139,10 @@ public:
virtual void reachedMaxAppCacheSize(int64_t) { }
#endif
+#if ENABLE(NOTIFICATIONS)
+ virtual NotificationPresenter* notificationPresenter() const { return 0; }
+#endif
+
virtual void runOpenPanel(Frame*, PassRefPtr<FileChooser>) { }
virtual void formStateDidChange(const Node*) { }
@@ -280,7 +286,8 @@ public:
#endif
virtual void saveViewStateToItem(HistoryItem*) { }
virtual bool canCachePage() const { return false; }
-
+ virtual void didDisplayInsecureContent() { }
+ virtual void didRunInsecureContent(SecurityOrigin*) { }
virtual PassRefPtr<Frame> createFrame(const KURL&, const String&, HTMLFrameOwnerElement*, const String&, bool, int, int) { 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; }
@@ -414,6 +421,7 @@ public:
};
+#if ENABLE(CONTEXT_MENUS)
class EmptyContextMenuClient : public ContextMenuClient {
public:
virtual ~EmptyContextMenuClient() { }
@@ -434,7 +442,9 @@ public:
virtual void searchWithSpotlight() { }
#endif
};
+#endif // ENABLE(CONTEXT_MENUS)
+#if ENABLE(DRAG_SUPPORT)
class EmptyDragClient : public DragClient {
public:
virtual ~EmptyDragClient() {}
@@ -446,6 +456,7 @@ public:
virtual DragImageRef createDragImageForLink(KURL&, const String&, Frame*) { return 0; }
virtual void dragControllerDestroyed() { }
};
+#endif // ENABLE(DRAG_SUPPORT)
class EmptyInspectorClient : public InspectorClient {
public:
@@ -478,6 +489,12 @@ public:
virtual void inspectorWindowObjectCleared() { }
};
+class EmptyPluginHalterClient : public PluginHalterClient
+{
+public:
+ virtual bool shouldHaltPlugin(Node*) const { return false; }
+};
+
}
#endif // EmptyClients_h
diff --git a/WebCore/loader/FTPDirectoryDocument.cpp b/WebCore/loader/FTPDirectoryDocument.cpp
index ace4cfe..ee0f4ca 100644
--- a/WebCore/loader/FTPDirectoryDocument.cpp
+++ b/WebCore/loader/FTPDirectoryDocument.cpp
@@ -118,7 +118,7 @@ void FTPDirectoryTokenizer::appendEntry(const String& filename, const String& si
rowElement->setAttribute("class", "ftpDirectoryEntryRow", ec);
RefPtr<Element> element = m_doc->createElement(tdTag, false);
- element->appendChild(new Text(m_doc, String(&noBreakSpace, 1)), ec);
+ element->appendChild(Text::create(m_doc, String(&noBreakSpace, 1)), ec);
if (isDirectory)
element->setAttribute("class", "ftpDirectoryIcon ftpDirectoryTypeDirectory", ec);
else
@@ -130,12 +130,12 @@ void FTPDirectoryTokenizer::appendEntry(const String& filename, const String& si
rowElement->appendChild(element, ec);
element = m_doc->createElement(tdTag, false);
- element->appendChild(new Text(m_doc, date), ec);
+ element->appendChild(Text::create(m_doc, date), ec);
element->setAttribute("class", "ftpDirectoryFileDate", ec);
rowElement->appendChild(element, ec);
element = m_doc->createElement(tdTag, false);
- element->appendChild(new Text(m_doc, size), ec);
+ element->appendChild(Text::create(m_doc, size), ec);
element->setAttribute("class", "ftpDirectoryFileSize", ec);
rowElement->appendChild(element, ec);
}
@@ -152,7 +152,7 @@ PassRefPtr<Element> FTPDirectoryTokenizer::createTDForFilename(const String& fil
RefPtr<Element> anchorElement = m_doc->createElement(aTag, false);
anchorElement->setAttribute("href", fullURL, ec);
- anchorElement->appendChild(new Text(m_doc, filename), ec);
+ anchorElement->appendChild(Text::create(m_doc, filename), ec);
RefPtr<Element> tdElement = m_doc->createElement(tdTag, false);
tdElement->appendChild(anchorElement, ec);
diff --git a/WebCore/loader/FTPDirectoryDocument.h b/WebCore/loader/FTPDirectoryDocument.h
index ecc6f73..b208c4e 100644
--- a/WebCore/loader/FTPDirectoryDocument.h
+++ b/WebCore/loader/FTPDirectoryDocument.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 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
@@ -35,7 +35,7 @@ class FTPDirectoryDocument : public HTMLDocument {
public:
static PassRefPtr<FTPDirectoryDocument> create(Frame* frame)
{
- return new FTPDirectoryDocument(frame);
+ return adoptRef(new FTPDirectoryDocument(frame));
}
private:
diff --git a/WebCore/loader/FTPDirectoryParser.cpp b/WebCore/loader/FTPDirectoryParser.cpp
index 6573fb6..40bd714 100644
--- a/WebCore/loader/FTPDirectoryParser.cpp
+++ b/WebCore/loader/FTPDirectoryParser.cpp
@@ -57,6 +57,13 @@ static struct tm *gmtimeQt(const time_t *const timep, struct tm *result)
#endif
#endif
+static inline FTPEntryType ParsingFailed(ListState& state)
+{
+ if (state.parsedOne || state.listStyle) /* junk if we fail to parse */
+ return FTPJunkEntry; /* this time but had previously parsed sucessfully */
+ return FTPMiscEntry; /* its part of a comment or error message */
+}
+
FTPEntryType parseOneFTPLine(const char* line, ListState& state, ListResult& result)
{
result.clear();
@@ -126,6 +133,9 @@ FTPEntryType parseOneFTPLine(const char* line, ListState& state, ListResult& res
}
}
+ if (!numtoks)
+ return ParsingFailed(state);
+
linelen_sans_wsp = &(tokens[numtoks-1][toklen[numtoks-1]]) - tokens[0];
if (numtoks == (sizeof(tokens)/sizeof(tokens[0])) )
{
@@ -356,11 +366,16 @@ FTPEntryType parseOneFTPLine(const char* line, ListState& state, ListResult& res
pos++;
p++;
}
- if (lstyle && pos < (toklen[0]-1) && *p == ']')
+ if (lstyle && pos < (toklen[0]-1))
{
+ /* ']' was found and there is at least one character after it */
+ ASSERT(*p == ']');
pos++;
p++;
tokmarker = pos; /* length of leading "[DIR1.DIR2.etc]" */
+ } else {
+ /* not a CMU style listing */
+ lstyle = 0;
}
}
while (lstyle && pos < toklen[0] && *p != ';')
@@ -387,7 +402,7 @@ FTPEntryType parseOneFTPLine(const char* line, ListState& state, ListResult& res
pos -= tokmarker; /* => fnlength sans "[DIR1.DIR2.etc]" */
p = &(tokens[0][tokmarker]); /* offset of basename */
- if (!lstyle || pos > 80) /* VMS filenames can't be longer than that */
+ if (!lstyle || pos == 0 || pos > 80) /* VMS filenames can't be longer than that */
{
lstyle = 0;
}
@@ -780,7 +795,7 @@ FTPEntryType parseOneFTPLine(const char* line, ListState& state, ListResult& res
state.parsedOne = true;
state.listStyle = lstyle;
- p = &(line[linelen_sans_wsp]); /* line end sans wsp */
+ p = &(line[linelen]); /* line end */
result.caseSensitive = true;
result.filename = tokens[3];
result.filenameLength = p - tokens[3];
@@ -788,29 +803,46 @@ FTPEntryType parseOneFTPLine(const char* line, ListState& state, ListResult& res
if (*tokens[2] != '<') /* not <DIR> or <JUNCTION> */
{
+ // try to handle correctly spaces at the beginning of the filename
+ // filesize (token[2]) must end at offset 38
+ if (tokens[2] + toklen[2] - line == 38) {
+ result.filename = &(line[39]);
+ result.filenameLength = p - result.filename;
+ }
result.type = FTPFileEntry;
pos = toklen[2];
result.fileSize = String(tokens[2], pos);
}
- else if ((tokens[2][1]) != 'D') /* not <DIR> */
- {
- result.type = FTPJunkEntry; /* unknown until junc for sure */
- if (result.filenameLength > 4)
+ else {
+ // try to handle correctly spaces at the beginning of the filename
+ // token[2] must begin at offset 24, the length is 5 or 10
+ // token[3] must begin at offset 39 or higher
+ if (tokens[2] - line == 24 && (toklen[2] == 5 || toklen[2] == 10) &&
+ tokens[3] - line >= 39) {
+ result.filename = &(line[39]);
+ result.filenameLength = p - result.filename;
+ }
+
+ if ((tokens[2][1]) != 'D') /* not <DIR> */
{
- p = result.filename;
- for (pos = result.filenameLength - 4; pos > 0; pos--)
+ result.type = FTPJunkEntry; /* unknown until junc for sure */
+ if (result.filenameLength > 4)
{
- if (p[0] == ' ' && p[3] == ' ' && p[2] == '>' &&
- (p[1] == '=' || p[1] == '-'))
+ p = result.filename;
+ for (pos = result.filenameLength - 4; pos > 0; pos--)
{
- result.type = FTPLinkEntry;
- result.filenameLength = p - result.filename;
- result.linkname = p + 4;
- result.linknameLength = &(line[linelen_sans_wsp])
- - result.linkname;
- break;
+ if (p[0] == ' ' && p[3] == ' ' && p[2] == '>' &&
+ (p[1] == '=' || p[1] == '-'))
+ {
+ result.type = FTPLinkEntry;
+ result.filenameLength = p - result.filename;
+ result.linkname = p + 4;
+ result.linknameLength = &(line[linelen])
+ - result.linkname;
+ break;
+ }
+ p++;
}
- p++;
}
}
}
@@ -821,8 +853,13 @@ FTPEntryType parseOneFTPLine(const char* line, ListState& state, ListResult& res
result.modifiedTime.tm_mon--;
result.modifiedTime.tm_mday = atoi(tokens[0]+3);
result.modifiedTime.tm_year = atoi(tokens[0]+6);
+ /* if year has only two digits then assume that
+ 00-79 is 2000-2079
+ 80-99 is 1980-1999 */
if (result.modifiedTime.tm_year < 80)
- result.modifiedTime.tm_year += 100;
+ result.modifiedTime.tm_year += 2000;
+ else if (result.modifiedTime.tm_year < 100)
+ result.modifiedTime.tm_year += 1900;
}
result.modifiedTime.tm_hour = atoi(tokens[1]+0);
@@ -974,6 +1011,8 @@ FTPEntryType parseOneFTPLine(const char* line, ListState& state, ListResult& res
* "drwxr-xr-x 2 0 0 512 May 28 22:17 etc"
*/
+ bool isOldHellsoft = false;
+
if (numtoks >= 6)
{
/* there are two perm formats (Hellsoft/NetWare and *IX strmode(3)).
@@ -999,6 +1038,8 @@ FTPEntryType parseOneFTPLine(const char* line, ListState& state, ListResult& res
{
/* rest is FMA[S] or AFM[S] */
lstyle = 'U'; /* very likely one of the NetWare servers */
+ if (toklen[0] == 10)
+ isOldHellsoft = true;
}
}
}
@@ -1063,7 +1104,7 @@ FTPEntryType parseOneFTPLine(const char* line, ListState& state, ListResult& res
/* check that size is numeric */
p = tokens[tokmarker];
- for (pos = 0; lstyle && pos < toklen[tokmarker]; pos++)
+ for (unsigned int i = 0; lstyle && i < toklen[tokmarker]; ++i)
{
if (!isASCIIDigit(*p++))
lstyle = 0;
@@ -1072,11 +1113,11 @@ FTPEntryType parseOneFTPLine(const char* line, ListState& state, ListResult& res
{
month_num = 0;
p = tokens[tokmarker+1];
- for (pos = 0;pos < (12*3); pos+=3)
+ for (unsigned int i = 0; i < (12*3); i+=3)
{
- if (p[0] == month_names[pos+0] &&
- p[1] == month_names[pos+1] &&
- p[2] == month_names[pos+2])
+ if (p[0] == month_names[i+0] &&
+ p[1] == month_names[i+1] &&
+ p[2] == month_names[i+2])
break;
month_num++;
}
@@ -1084,8 +1125,8 @@ FTPEntryType parseOneFTPLine(const char* line, ListState& state, ListResult& res
lstyle = 0;
}
} /* relative position test */
- } /* while (pos+5) < numtoks */
- } /* if (numtoks >= 4) */
+ } /* for (pos = (numtoks-5); !lstyle && pos > 1; pos--) */
+ } /* if (lstyle == 'U') */
if (lstyle == 'U')
{
@@ -1144,24 +1185,49 @@ FTPEntryType parseOneFTPLine(const char* line, ListState& state, ListResult& res
} /* time/year */
- result.filename = tokens[tokmarker+4];
- result.filenameLength = (&(line[linelen_sans_wsp]))
+ // there is exacly 1 space between filename and previous token in all
+ // outputs except old Hellsoft
+ if (!isOldHellsoft)
+ result.filename = tokens[tokmarker+3] + toklen[tokmarker+3] + 1;
+ else
+ result.filename = tokens[tokmarker+4];
+
+ result.filenameLength = (&(line[linelen]))
- (result.filename);
if (result.type == FTPLinkEntry && result.filenameLength > 4)
{
- p = result.filename + 1;
- for (pos = 1; pos < (result.filenameLength - 4); pos++)
+ /* First try to use result.fe_size to find " -> " sequence.
+ This can give proper result for cases like "aaa -> bbb -> ccc". */
+ unsigned int fileSize = result.fileSize.toUInt();
+
+ if (result.filenameLength > (fileSize + 4) &&
+ strncmp(result.filename + result.filenameLength - fileSize - 4, " -> ", 4) == 0)
+ {
+ result.linkname = result.filename + (result.filenameLength - fileSize);
+ result.linknameLength = (&(line[linelen])) - (result.linkname);
+ result.filenameLength -= fileSize + 4;
+ }
+ else
{
- if (*p == ' ' && p[1] == '-' && p[2] == '>' && p[3] == ' ')
+ /* Search for sequence " -> " from the end for case when there are
+ more occurrences. F.e. if ftpd returns "a -> b -> c" assume
+ "a -> b" as a name. Powerusers can remove unnecessary parts
+ manually but there is no way to follow the link when some
+ essential part is missing. */
+ p = result.filename + (result.filenameLength - 5);
+ for (pos = (result.filenameLength - 5); pos > 0; pos--)
{
- result.linkname = p + 4;
- result.linknameLength = (&(line[linelen_sans_wsp]))
- - (result.linkname);
- result.filenameLength = pos;
- break;
+ if (strncmp(p, " -> ", 4) == 0)
+ {
+ result.linkname = p + 4;
+ result.linknameLength = (&(line[linelen]))
+ - (result.linkname);
+ result.filenameLength = pos;
+ break;
+ }
+ p--;
}
- p++;
}
}
@@ -1618,9 +1684,7 @@ FTPEntryType parseOneFTPLine(const char* line, ListState& state, ListResult& res
} /* if (linelen > 0) */
- if (state.parsedOne || state.listStyle) /* junk if we fail to parse */
- return FTPJunkEntry; /* this time but had previously parsed sucessfully */
- return FTPMiscEntry; /* its part of a comment or error message */
+ return ParsingFailed(state);
}
} // namespace WebCore
diff --git a/WebCore/loader/FrameLoader.cpp b/WebCore/loader/FrameLoader.cpp
index c28040f..9dfefcd 100644
--- a/WebCore/loader/FrameLoader.cpp
+++ b/WebCore/loader/FrameLoader.cpp
@@ -73,6 +73,7 @@
#include "Page.h"
#include "PageCache.h"
#include "PageGroup.h"
+#include "PageTransitionEvent.h"
#include "PlaceholderDocument.h"
#include "PluginData.h"
#include "PluginDocument.h"
@@ -89,6 +90,11 @@
#include "SecurityOrigin.h"
#include "SegmentedString.h"
#include "Settings.h"
+
+#if ENABLE(SHARED_WORKERS)
+#include "SharedWorkerRepository.h"
+#endif
+
#include "TextResourceDecoder.h"
#include "WindowFeatures.h"
#include "XMLHttpRequest.h"
@@ -108,6 +114,7 @@
#include "SVGViewSpec.h"
#endif
+<<<<<<< HEAD:WebCore/loader/FrameLoader.cpp
#ifdef ANDROID_INSTRUMENT
#include "TimeCounter.h"
#include "RenderArena.h"
@@ -115,6 +122,10 @@
#if PLATFORM(ANDROID)
#include "WebCoreFrameBridge.h"
+=======
+#if PLATFORM(MAC) || PLATFORM(WIN)
+#define PAGE_CACHE_ACCEPTS_UNLOAD_HANDLERS
+>>>>>>> webkit.org at 49305:WebCore/loader/FrameLoader.cpp
#endif
namespace WebCore {
@@ -124,91 +135,12 @@ using namespace SVGNames;
#endif
using namespace HTMLNames;
-struct ScheduledRedirection {
- enum Type { redirection, locationChange, historyNavigation, formSubmission };
-
- const Type type;
- const double delay;
- const String url;
- const String referrer;
- const FrameLoadRequest frameRequest;
- const RefPtr<Event> event;
- const RefPtr<FormState> formState;
- const int historySteps;
- const bool lockHistory;
- const bool lockBackForwardList;
- const bool wasUserGesture;
- const bool wasRefresh;
- const bool wasDuringLoad;
-
- ScheduledRedirection(double delay, const String& url, bool lockHistory, bool lockBackForwardList, bool wasUserGesture, bool refresh)
- : type(redirection)
- , delay(delay)
- , url(url)
- , historySteps(0)
- , lockHistory(lockHistory)
- , lockBackForwardList(lockBackForwardList)
- , wasUserGesture(wasUserGesture)
- , wasRefresh(refresh)
- , wasDuringLoad(false)
- {
- ASSERT(!url.isEmpty());
- }
-
- ScheduledRedirection(const String& url, const String& referrer, bool lockHistory, bool lockBackForwardList, bool wasUserGesture, bool refresh, bool duringLoad)
- : type(locationChange)
- , delay(0)
- , url(url)
- , referrer(referrer)
- , historySteps(0)
- , lockHistory(lockHistory)
- , lockBackForwardList(lockBackForwardList)
- , wasUserGesture(wasUserGesture)
- , wasRefresh(refresh)
- , wasDuringLoad(duringLoad)
- {
- ASSERT(!url.isEmpty());
- }
-
- explicit ScheduledRedirection(int historyNavigationSteps)
- : type(historyNavigation)
- , delay(0)
- , historySteps(historyNavigationSteps)
- , lockHistory(false)
- , lockBackForwardList(false)
- , wasUserGesture(false)
- , wasRefresh(false)
- , wasDuringLoad(false)
- {
- }
-
- ScheduledRedirection(const FrameLoadRequest& frameRequest,
- bool lockHistory, bool lockBackForwardList, PassRefPtr<Event> event, PassRefPtr<FormState> formState,
- bool duringLoad)
- : type(formSubmission)
- , delay(0)
- , frameRequest(frameRequest)
- , event(event)
- , formState(formState)
- , historySteps(0)
- , lockHistory(lockHistory)
- , lockBackForwardList(lockBackForwardList)
- , wasUserGesture(false)
- , wasRefresh(false)
- , wasDuringLoad(duringLoad)
- {
- ASSERT(!frameRequest.isEmpty());
- ASSERT(this->formState);
- }
-};
-
#if ENABLE(XHTMLMP)
static const char defaultAcceptHeader[] = "application/xml,application/vnd.wap.xhtml+xml,application/xhtml+xml;profile='http://www.wapforum.org/xhtml',text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5";
#else
static const char defaultAcceptHeader[] = "application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5";
#endif
static double storedTimeOfLastCompletedLoad;
-static FrameLoader::LocalLoadPolicy localLoadPolicy = FrameLoader::AllowLocalLoadsForLocalOnly;
bool isBackForwardLoadType(FrameLoadType type)
{
@@ -246,12 +178,10 @@ static inline bool canReferToParentFrameEncoding(const Frame* frame, const Frame
FrameLoader::FrameLoader(Frame* frame, FrameLoaderClient* client)
: m_frame(frame)
, m_client(client)
+ , m_policyChecker(frame)
, m_state(FrameStateCommittedPage)
, m_loadType(FrameLoadTypeStandard)
- , m_policyLoadType(FrameLoadTypeStandard)
, m_delegateIsHandlingProvisionalLoadError(false)
- , m_delegateIsDecidingNavigationPolicy(false)
- , m_delegateIsHandlingUnimplementablePolicy(false)
, m_firstLayoutDone(false)
, m_quickRedirectComing(false)
, m_sentRedirectNotification(false)
@@ -263,20 +193,19 @@ FrameLoader::FrameLoader(Frame* frame, FrameLoaderClient* client)
, m_unloadEventBeingDispatched(false)
, m_isComplete(false)
, m_isLoadingMainResource(false)
- , m_cancellingWithLoadInProgress(false)
, m_needsClear(false)
, m_receivedData(false)
, m_encodingWasChosenByUser(false)
, m_containsPlugIns(false)
- , m_redirectionTimer(this, &FrameLoader::redirectionTimerFired)
- , m_checkCompletedTimer(this, &FrameLoader::checkCompletedTimerFired)
- , m_checkLoadCompleteTimer(this, &FrameLoader::checkLoadCompleteTimerFired)
+ , m_checkTimer(this, &FrameLoader::checkTimerFired)
+ , m_shouldCallCheckCompleted(false)
+ , m_shouldCallCheckLoadComplete(false)
, m_opener(0)
- , m_openedByDOM(false)
, m_creatingInitialEmptyDocument(false)
, m_isDisplayingInitialEmptyDocument(false)
, m_committedFirstRealDocumentLoad(false)
, m_didPerformFirstNavigation(false)
+ , m_loadingFromCachedPage(false)
#ifndef NDEBUG
, m_didDispatchDidCommitLoad(false)
#endif
@@ -299,7 +228,7 @@ void FrameLoader::init()
// this somewhat odd set of steps is needed to give the frame an initial empty document
m_isDisplayingInitialEmptyDocument = false;
m_creatingInitialEmptyDocument = true;
- setPolicyDocumentLoader(m_client->createDocumentLoader(ResourceRequest(KURL("")), SubstituteData()).get());
+ setPolicyDocumentLoader(m_client->createDocumentLoader(ResourceRequest(KURL(ParsedURLString, "")), SubstituteData()).get());
setProvisionalDocumentLoader(m_policyDocumentLoader.get());
setState(FrameStateProvisional);
m_provisionalDocumentLoader->setResponse(ResourceResponse(KURL(), "text/html", 0, String(), String()));
@@ -319,6 +248,11 @@ void FrameLoader::setDefersLoading(bool defers)
m_provisionalDocumentLoader->setDefersLoading(defers);
if (m_policyDocumentLoader)
m_policyDocumentLoader->setDefersLoading(defers);
+
+ if (!defers) {
+ m_frame->redirectScheduler()->startTimer();
+ startCheckCompleteTimer();
+ }
}
Frame* FrameLoader::createWindow(FrameLoader* frameLoaderForFrameLookup, const FrameLoadRequest& request, const WindowFeatures& features, bool& created)
@@ -433,7 +367,7 @@ bool FrameLoader::requestFrame(HTMLFrameOwnerElement* ownerElement, const String
Frame* frame = ownerElement->contentFrame();
if (frame)
- frame->loader()->scheduleLocationChange(url.string(), m_outgoingReferrer, true, true, isProcessingUserGesture());
+ frame->redirectScheduler()->scheduleLocationChange(url.string(), m_outgoingReferrer, true, true, isProcessingUserGesture());
else
frame = loadSubframe(ownerElement, url, frameName, m_outgoingReferrer);
@@ -458,12 +392,12 @@ Frame* FrameLoader::loadSubframe(HTMLFrameOwnerElement* ownerElement, const KURL
marginHeight = o->getMarginHeight();
}
- if (!canLoad(url, referrer)) {
+ if (!SecurityOrigin::canLoad(url, referrer, 0)) {
FrameLoader::reportLocalLoadFailed(m_frame, url.string());
return 0;
}
- bool hideReferrer = shouldHideReferrer(url, referrer);
+ bool hideReferrer = SecurityOrigin::shouldHideReferrer(url, referrer);
RefPtr<Frame> frame = m_client->createFrame(url, name, ownerElement, hideReferrer ? String() : referrer, allowsScrolling, marginWidth, marginHeight);
if (!frame) {
@@ -571,23 +505,27 @@ void FrameLoader::submitForm(const char* action, const String& url, PassRefPtr<F
frameRequest.resourceRequest().setURL(u);
addHTTPOriginIfNeeded(frameRequest.resourceRequest(), outgoingOrigin());
- targetFrame->loader()->scheduleFormSubmission(frameRequest, lockHistory, event, formState);
+ targetFrame->redirectScheduler()->scheduleFormSubmission(frameRequest, lockHistory, event, formState);
}
-void FrameLoader::stopLoading(bool sendUnload, DatabasePolicy databasePolicy)
+void FrameLoader::stopLoading(UnloadEventPolicy unloadEventPolicy, DatabasePolicy databasePolicy)
{
if (m_frame->document() && m_frame->document()->tokenizer())
m_frame->document()->tokenizer()->stopParsing();
- if (sendUnload) {
+ if (unloadEventPolicy != UnloadEventPolicyNone) {
if (m_frame->document()) {
if (m_didCallImplicitClose && !m_wasUnloadEventEmitted) {
Node* currentFocusedNode = m_frame->document()->focusedNode();
if (currentFocusedNode)
currentFocusedNode->aboutToUnload();
m_unloadEventBeingDispatched = true;
- if (m_frame->domWindow())
- m_frame->domWindow()->dispatchUnloadEvent();
+ if (m_frame->domWindow()) {
+ if (unloadEventPolicy == UnloadEventPolicyUnloadAndPageHide)
+ m_frame->domWindow()->dispatchEvent(PageTransitionEvent::create(EventNames().pagehideEvent, m_frame->document()->inPageCache()), m_frame->document());
+ if (!m_frame->document()->inPageCache())
+ m_frame->domWindow()->dispatchEvent(Event::create(eventNames().unloadEvent, false, false), m_frame->domWindow()->document());
+ }
m_unloadEventBeingDispatched = false;
if (m_frame->document())
m_frame->document()->updateStyleIfNeeded();
@@ -600,7 +538,7 @@ void FrameLoader::stopLoading(bool sendUnload, DatabasePolicy databasePolicy)
m_frame->document()->removeAllEventListeners();
}
- m_isComplete = true; // to avoid calling completed() in finishedParsing() (David)
+ m_isComplete = true; // to avoid calling completed() in finishedParsing()
m_isLoadingMainResource = false;
m_didCallImplicitClose = true; // don't want that one either
@@ -623,9 +561,9 @@ void FrameLoader::stopLoading(bool sendUnload, DatabasePolicy databasePolicy)
// tell all subframes to stop as well
for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
- child->loader()->stopLoading(sendUnload);
+ child->loader()->stopLoading(unloadEventPolicy);
- cancelRedirection();
+ m_frame->redirectScheduler()->cancel();
}
void FrameLoader::stop()
@@ -645,20 +583,15 @@ void FrameLoader::stop()
bool FrameLoader::closeURL()
{
saveDocumentState();
- stopLoading(true);
+
+ // Should only send the pagehide event here if the current document exists and has not been placed in the page cache.
+ Document* currentDocument = m_frame->document();
+ stopLoading(currentDocument && !currentDocument->inPageCache() ? UnloadEventPolicyUnloadAndPageHide : UnloadEventPolicyUnloadOnly);
+
m_frame->editor()->clearUndoRedoOperations();
return true;
}
-void FrameLoader::cancelRedirection(bool cancelWithLoadInProgress)
-{
- m_cancellingWithLoadInProgress = cancelWithLoadInProgress;
-
- stopRedirectionTimer();
-
- m_scheduledRedirection.clear();
-}
-
KURL FrameLoader::iconURL()
{
// If this isn't a top level frame, return nothing
@@ -667,7 +600,7 @@ KURL FrameLoader::iconURL()
// If we have an iconURL from a Link element, return that
if (!m_frame->document()->iconURL().isEmpty())
- return KURL(m_frame->document()->iconURL());
+ return KURL(ParsedURLString, m_frame->document()->iconURL());
// Don't return a favicon iconURL unless we're http or https
if (!m_URL.protocolInHTTPFamily())
@@ -684,13 +617,13 @@ KURL FrameLoader::iconURL()
bool FrameLoader::didOpenURL(const KURL& url)
{
- if (m_scheduledRedirection && m_scheduledRedirection->wasDuringLoad) {
+ if (m_frame->redirectScheduler()->redirectScheduledDuringLoad()) {
// A redirect was scheduled before the document was created.
// This can happen when one frame changes another frame's location.
return false;
}
- cancelRedirection();
+ m_frame->redirectScheduler()->cancel();
m_frame->editor()->clearLastEditCommand();
closeURL();
@@ -727,7 +660,7 @@ void FrameLoader::didExplicitOpen()
// from a subsequent window.document.open / window.document.write call.
// Cancelling redirection here works for all cases because document.open
// implicitly precedes document.write.
- cancelRedirection();
+ m_frame->redirectScheduler()->cancel();
if (m_frame->document()->url() != blankURL())
m_URL = m_frame->document()->url();
}
@@ -742,8 +675,10 @@ bool FrameLoader::executeIfJavaScriptURL(const KURL& url, bool userGesture, bool
const int javascriptSchemeLength = sizeof("javascript:") - 1;
- String script = decodeURLEscapeSequences(url.string().substring(javascriptSchemeLength));
- ScriptValue result = executeScript(script, userGesture);
+ String script = url.string().substring(javascriptSchemeLength);
+ ScriptValue result;
+ if (m_frame->script()->xssAuditor()->canEvaluateJavaScriptURL(script))
+ result = executeScript(decodeURLEscapeSequences(script), userGesture);
String scriptResult;
if (!result.getString(scriptResult))
@@ -789,7 +724,7 @@ ScriptValue FrameLoader::executeScript(const ScriptSourceCode& sourceCode)
void FrameLoader::cancelAndClear()
{
- cancelRedirection();
+ m_frame->redirectScheduler()->cancel();
if (!m_isComplete)
closeURL();
@@ -798,7 +733,7 @@ void FrameLoader::cancelAndClear()
m_frame->script()->updatePlatformScriptObjects();
}
-void FrameLoader::clear(bool clearWindowProperties, bool clearScriptObjects)
+void FrameLoader::clear(bool clearWindowProperties, bool clearScriptObjects, bool clearFrameView)
{
m_frame->editor()->clear();
@@ -825,7 +760,7 @@ void FrameLoader::clear(bool clearWindowProperties, bool clearScriptObjects)
m_frame->selection()->clear();
m_frame->eventHandler()->clear();
- if (m_frame->view())
+ if (clearFrameView && m_frame->view())
m_frame->view()->clear();
m_frame->setSelectionGranularity(CharacterGranularity);
@@ -840,11 +775,11 @@ void FrameLoader::clear(bool clearWindowProperties, bool clearScriptObjects)
if (clearScriptObjects)
m_frame->script()->clearScriptObjects();
- m_redirectionTimer.stop();
- m_scheduledRedirection.clear();
+ m_frame->redirectScheduler()->clear();
- m_checkCompletedTimer.stop();
- m_checkLoadCompleteTimer.stop();
+ m_checkTimer.stop();
+ m_shouldCallCheckCompleted = false;
+ m_shouldCallCheckLoadComplete = false;
m_receivedData = false;
m_isDisplayingInitialEmptyDocument = false;
@@ -881,7 +816,7 @@ void FrameLoader::receivedFirstData()
else
url = m_frame->document()->completeURL(url).string();
- scheduleHTTPRedirection(delay, url);
+ m_frame->redirectScheduler()->scheduleRedirect(delay, url);
}
const String& FrameLoader::responseMIMEType() const
@@ -933,12 +868,9 @@ void FrameLoader::begin(const KURL& url, bool dispatch, SecurityOrigin* origin)
m_outgoingReferrer = ref.string();
m_URL = url;
+ document->setURL(m_URL);
m_frame->setDocument(document);
- if (dispatch)
- dispatchWindowObjectAvailable();
-
- document->setURL(m_URL);
if (m_decoder)
document->setDecoder(m_decoder.get());
if (forcedSecurityOrigin)
@@ -947,6 +879,9 @@ void FrameLoader::begin(const KURL& url, bool dispatch, SecurityOrigin* origin)
m_frame->domWindow()->setURL(document->url());
m_frame->domWindow()->setSecurityOrigin(document->securityOrigin());
+ if (dispatch)
+ dispatchWindowObjectAvailable();
+
updateFirstPartyForCookies();
Settings* settings = document->settings();
@@ -961,12 +896,6 @@ void FrameLoader::begin(const KURL& url, bool dispatch, SecurityOrigin* origin)
document->parseDNSPrefetchControlHeader(dnsPrefetchControl);
}
-#if FRAME_LOADS_USER_STYLESHEET
- KURL userStyleSheet = settings ? settings->userStyleSheetLocation() : KURL();
- if (!userStyleSheet.isEmpty())
- m_frame->setUserStyleSheetLocation(userStyleSheet);
-#endif
-
restoreDocumentState();
document->implicitOpen();
@@ -1146,21 +1075,6 @@ void FrameLoader::startIconLoader()
m_iconLoader->startLoading();
}
-void FrameLoader::setLocalLoadPolicy(LocalLoadPolicy policy)
-{
- localLoadPolicy = policy;
-}
-
-bool FrameLoader::restrictAccessToLocal()
-{
- return localLoadPolicy != FrameLoader::AllowLocalLoadsForAll;
-}
-
-bool FrameLoader::allowSubstituteDataAccessToLocal()
-{
- return localLoadPolicy != FrameLoader::AllowLocalLoadsForLocalOnly;
-}
-
void FrameLoader::commitIconURLToIconDatabase(const KURL& icon)
{
ASSERT(iconDatabase());
@@ -1220,6 +1134,8 @@ void FrameLoader::finishedParsing()
if (m_creatingInitialEmptyDocument)
return;
+ m_frame->injectUserScripts(InjectAtDocumentEnd);
+
// This can be called from the Frame's destructor, in which case we shouldn't protect ourselves
// because doing so will cause us to re-enter the destructor when protector goes out of scope.
// Null-checking the FrameView indicates whether or not we're in the destructor.
@@ -1244,15 +1160,34 @@ void FrameLoader::loadDone()
checkCompleted();
}
+bool FrameLoader::allChildrenAreComplete() const
+{
+ for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
+ if (!child->loader()->m_isComplete)
+ return false;
+ }
+ return true;
+}
+
+bool FrameLoader::allAncestorsAreComplete() const
+{
+ for (Frame* ancestor = m_frame; ancestor; ancestor = ancestor->tree()->parent()) {
+ if (!ancestor->loader()->m_isComplete)
+ return false;
+ }
+ return true;
+}
+
void FrameLoader::checkCompleted()
{
+ m_shouldCallCheckCompleted = false;
+
if (m_frame->view())
m_frame->view()->checkStopDelayingDeferredRepaints();
// Any frame that hasn't completed yet?
- for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
- if (!child->loader()->m_isComplete)
- return;
+ if (!allChildrenAreComplete())
+ return;
// Have we completed before?
if (m_isComplete)
@@ -1272,38 +1207,44 @@ void FrameLoader::checkCompleted()
RefPtr<Frame> protect(m_frame);
checkCallImplicitClose(); // if we didn't do it before
- // Do not start a redirection timer for subframes here.
- // That is deferred until the parent is completed.
- if (m_scheduledRedirection && !m_frame->tree()->parent())
- startRedirectionTimer();
+ m_frame->redirectScheduler()->startTimer();
completed();
if (m_frame->page())
checkLoadComplete();
}
-void FrameLoader::checkCompletedTimerFired(Timer<FrameLoader>*)
+void FrameLoader::checkTimerFired(Timer<FrameLoader>*)
{
- checkCompleted();
+ if (Page* page = m_frame->page()) {
+ if (page->defersLoading())
+ return;
+ }
+ if (m_shouldCallCheckCompleted)
+ checkCompleted();
+ if (m_shouldCallCheckLoadComplete)
+ checkLoadComplete();
}
-void FrameLoader::scheduleCheckCompleted()
+void FrameLoader::startCheckCompleteTimer()
{
- if (!m_checkCompletedTimer.isActive())
- m_checkCompletedTimer.startOneShot(0);
+ if (!(m_shouldCallCheckCompleted || m_shouldCallCheckLoadComplete))
+ return;
+ if (m_checkTimer.isActive())
+ return;
+ m_checkTimer.startOneShot(0);
}
-void FrameLoader::checkLoadCompleteTimerFired(Timer<FrameLoader>*)
+void FrameLoader::scheduleCheckCompleted()
{
- if (!m_frame->page())
- return;
- checkLoadComplete();
+ m_shouldCallCheckCompleted = true;
+ startCheckCompleteTimer();
}
void FrameLoader::scheduleCheckLoadComplete()
{
- if (!m_checkLoadCompleteTimer.isActive())
- m_checkLoadCompleteTimer.startOneShot(0);
+ m_shouldCallCheckLoadComplete = true;
+ startCheckCompleteTimer();
}
void FrameLoader::checkCallImplicitClose()
@@ -1311,9 +1252,8 @@ void FrameLoader::checkCallImplicitClose()
if (m_didCallImplicitClose || m_frame->document()->parsing())
return;
- for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
- if (!child->loader()->m_isComplete) // still got a frame running -> too early
- return;
+ if (!allChildrenAreComplete())
+ return; // still got a frame running -> too early
m_didCallImplicitClose = true;
m_wasUnloadEventEmitted = false;
@@ -1332,183 +1272,6 @@ KURL FrameLoader::completeURL(const String& url)
return m_frame->document()->completeURL(url);
}
-void FrameLoader::scheduleHTTPRedirection(double delay, const String& url)
-{
- if (delay < 0 || delay > INT_MAX / 1000)
- return;
-
- if (!m_frame->page())
- return;
-
- if (url.isEmpty())
- return;
-
- // We want a new history item if the refresh timeout is > 1 second.
- if (!m_scheduledRedirection || delay <= m_scheduledRedirection->delay)
- 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())
- return;
-
- 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.hasFragmentIdentifier() && equalIgnoringFragmentIdentifier(m_URL, parsedURL)) {
- changeLocation(completeURL(url), referrer, lockHistory, lockBackForwardList, wasUserGesture);
- return;
- }
-
- // Handle a location change of a page with no document as a special case.
- // This may happen when a frame changes the location of another frame.
- bool duringLoad = !m_committedFirstRealDocumentLoad;
-
- scheduleRedirection(new ScheduledRedirection(url, referrer, lockHistory, lockBackForwardList, wasUserGesture, false, duringLoad));
-}
-
-void FrameLoader::scheduleFormSubmission(const FrameLoadRequest& frameRequest,
- bool lockHistory, PassRefPtr<Event> event, PassRefPtr<FormState> formState)
-{
- ASSERT(m_frame->page());
- ASSERT(!frameRequest.isEmpty());
-
- // FIXME: Do we need special handling for form submissions where the URL is the same
- // as the current one except for the fragment part? See scheduleLocationChange above.
-
- // Handle a location change of a page with no document as a special case.
- // This may happen when a frame changes the location of another frame.
- bool duringLoad = !m_committedFirstRealDocumentLoad;
-
- scheduleRedirection(new ScheduledRedirection(frameRequest, lockHistory, mustLockBackForwardList(m_frame), event, formState, duringLoad));
-}
-
-void FrameLoader::scheduleRefresh(bool wasUserGesture)
-{
- if (!m_frame->page())
- return;
-
- if (m_URL.isEmpty())
- return;
-
- scheduleRedirection(new ScheduledRedirection(m_URL.string(), m_outgoingReferrer, true, true, wasUserGesture, true, false));
-}
-
-bool FrameLoader::isLocationChange(const ScheduledRedirection& redirection)
-{
- switch (redirection.type) {
- case ScheduledRedirection::redirection:
- return false;
- case ScheduledRedirection::historyNavigation:
- case ScheduledRedirection::locationChange:
- case ScheduledRedirection::formSubmission:
- return true;
- }
- ASSERT_NOT_REACHED();
- return false;
-}
-
-void FrameLoader::scheduleHistoryNavigation(int steps)
-{
- if (!m_frame->page())
- return;
-
- // navigation will always be allowed in the 0 steps case, which is OK because that's supposed to force a reload.
- if (!canGoBackOrForward(steps)) {
- cancelRedirection();
- return;
- }
-
- scheduleRedirection(new ScheduledRedirection(steps));
-}
-
-void FrameLoader::goBackOrForward(int distance)
-{
- if (distance == 0)
- return;
-
- Page* page = m_frame->page();
- if (!page)
- return;
- BackForwardList* list = page->backForwardList();
- if (!list)
- return;
-
- HistoryItem* item = list->itemAtIndex(distance);
- if (!item) {
- if (distance > 0) {
- int forwardListCount = list->forwardListCount();
- if (forwardListCount > 0)
- item = list->itemAtIndex(forwardListCount);
- } else {
- int backListCount = list->backListCount();
- if (backListCount > 0)
- item = list->itemAtIndex(-backListCount);
- }
- }
-
- ASSERT(item); // we should not reach this line with an empty back/forward list
- if (item)
- page->goToItem(item, FrameLoadTypeIndexedBackForward);
-}
-
-void FrameLoader::redirectionTimerFired(Timer<FrameLoader>*)
-{
- ASSERT(m_frame->page());
-
- OwnPtr<ScheduledRedirection> redirection(m_scheduledRedirection.release());
-
- switch (redirection->type) {
- case ScheduledRedirection::redirection:
- case ScheduledRedirection::locationChange:
- changeLocation(KURL(redirection->url), redirection->referrer,
- redirection->lockHistory, redirection->lockBackForwardList, redirection->wasUserGesture, redirection->wasRefresh);
- return;
- case ScheduledRedirection::historyNavigation:
- if (redirection->historySteps == 0) {
- // Special case for go(0) from a frame -> reload only the frame
- urlSelected(m_URL, "", 0, redirection->lockHistory, redirection->lockBackForwardList, redirection->wasUserGesture);
- return;
- }
- // go(i!=0) from a frame navigates into the history of the frame only,
- // in both IE and NS (but not in Mozilla). We can't easily do that.
- goBackOrForward(redirection->historySteps);
- return;
- case ScheduledRedirection::formSubmission:
- // The submitForm function will find a target frame before using the redirection timer.
- // Now that the timer has fired, we need to repeat the security check which normally is done when
- // selecting a target, in case conditions have changed. Other code paths avoid this by targeting
- // without leaving a time window. If we fail the check just silently drop the form submission.
- if (!redirection->formState->sourceFrame()->loader()->shouldAllowNavigation(m_frame))
- return;
- loadFrameRequest(redirection->frameRequest, redirection->lockHistory, redirection->lockBackForwardList,
- redirection->event, redirection->formState);
- return;
- }
-
- ASSERT_NOT_REACHED();
-}
-
void FrameLoader::loadURLIntoChildFrame(const KURL& url, const String& referer, Frame* childFrame)
{
ASSERT(childFrame);
@@ -1527,7 +1290,7 @@ void FrameLoader::loadURLIntoChildFrame(const KURL& url, const String& referer,
// Use the original URL to ensure we get all the side-effects, such as
// onLoad handlers, of any redirects that happened. An example of where
// this is needed is Radar 3213556.
- workingURL = KURL(childItem->originalURLString());
+ workingURL = KURL(ParsedURLString, childItem->originalURLString());
childLoadType = loadType;
childFrame->loader()->m_provisionalHistoryItem = childItem;
}
@@ -1716,7 +1479,7 @@ bool FrameLoader::loadPlugin(RenderPart* renderer, const KURL& url, const String
if (renderer && !useFallback) {
HTMLPlugInElement* element = toPlugInElement(renderer->node());
- if (!canLoad(url, String(), frame()->document())) {
+ if (!SecurityOrigin::canLoad(url, String(), frame()->document())) {
FrameLoader::reportLocalLoadFailed(m_frame, url.string());
return false;
}
@@ -1733,12 +1496,6 @@ bool FrameLoader::loadPlugin(RenderPart* renderer, const KURL& url, const String
return widget != 0;
}
-void FrameLoader::parentCompleted()
-{
- if (m_scheduledRedirection && !m_redirectionTimer.isActive())
- startRedirectionTimer();
-}
-
String FrameLoader::outgoingReferrer() const
{
return m_outgoingReferrer;
@@ -1749,6 +1506,33 @@ String FrameLoader::outgoingOrigin() const
return m_frame->document()->securityOrigin()->toString();
}
+bool FrameLoader::isMixedContent(SecurityOrigin* context, const KURL& url)
+{
+ if (context->protocol() != "https")
+ return false; // We only care about HTTPS security origins.
+
+ if (url.protocolIs("https") || url.protocolIs("about") || url.protocolIs("data"))
+ return false; // Loading these protocols is secure.
+
+ return true;
+}
+
+void FrameLoader::checkIfDisplayInsecureContent(SecurityOrigin* context, const KURL& url)
+{
+ if (!isMixedContent(context, url))
+ return;
+
+ m_client->didDisplayInsecureContent();
+}
+
+void FrameLoader::checkIfRunInsecureContent(SecurityOrigin* context, const KURL& url)
+{
+ if (!isMixedContent(context, url))
+ return;
+
+ m_client->didRunInsecureContent(context);
+}
+
Frame* FrameLoader::opener()
{
return m_opener;
@@ -1768,16 +1552,6 @@ void FrameLoader::setOpener(Frame* opener)
}
}
-bool FrameLoader::openedByDOM() const
-{
- return m_openedByDOM;
-}
-
-void FrameLoader::setOpenedByDOM()
-{
- m_openedByDOM = true;
-}
-
void FrameLoader::handleFallbackContent()
{
HTMLFrameOwnerElement* owner = m_frame->ownerElement();
@@ -1793,7 +1567,7 @@ void FrameLoader::provisionalLoadStarted()
android::TimeCounter::reset();
#endif
m_firstLayoutDone = false;
- cancelRedirection(true);
+ m_frame->redirectScheduler()->cancel(true);
m_client->provisionalLoadStarted();
}
@@ -1839,9 +1613,13 @@ static inline bool frameContainsWMLContent(Frame* frame)
bool FrameLoader::canCachePageContainingThisFrame()
{
+ for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling()) {
+ if (!child->loader()->canCachePageContainingThisFrame())
+ return false;
+ }
+
return m_documentLoader
&& m_documentLoader->mainDocumentError().isNull()
- && !m_frame->tree()->childCount()
// FIXME: If we ever change this so that frames with plug-ins will be cached,
// we need to make sure that we don't cache frames that have outstanding NPObjects
// (objects created by the plug-in). Since there is no way to pause/resume a Netscape plug-in,
@@ -1849,10 +1627,15 @@ bool FrameLoader::canCachePageContainingThisFrame()
// the right NPObjects. See <rdar://problem/5197041> for more information.
&& !m_containsPlugIns
&& !m_URL.protocolIs("https")
- && (!m_frame->domWindow() || !m_frame->domWindow()->hasEventListener(eventNames().unloadEvent))
+#ifndef PAGE_CACHE_ACCEPTS_UNLOAD_HANDLERS
+ && (!m_frame->domWindow() || !m_frame->domWindow()->hasEventListeners(eventNames().unloadEvent))
+#endif
#if ENABLE(DATABASE)
&& !m_frame->document()->hasOpenDatabases()
#endif
+#if ENABLE(SHARED_WORKERS)
+ && !SharedWorkerRepository::hasSharedWorkers(m_frame->document())
+#endif
&& !m_frame->document()->usingGeolocation()
&& m_currentHistoryItem
&& !m_quickRedirectComing
@@ -1987,18 +1770,22 @@ bool FrameLoader::logCanCacheFrameDecision(int indentLevel)
}
if (!m_documentLoader->mainDocumentError().isNull())
{ PCLOG(" -Main document has an error"); cannotCache = true; }
- if (m_frame->tree()->childCount())
- { PCLOG(" -Frame has child frames"); cannotCache = true; }
if (m_containsPlugIns)
{ PCLOG(" -Frame contains plugins"); cannotCache = true; }
if (m_URL.protocolIs("https"))
{ PCLOG(" -Frame is HTTPS"); cannotCache = true; }
- if (m_frame->domWindow() && m_frame->domWindow()->hasEventListener(eventNames().unloadEvent))
+#ifndef PAGE_CACHE_ACCEPTS_UNLOAD_HANDLERS
+ if (m_frame->domWindow() && m_frame->domWindow()->hasEventListeners(eventNames().unloadEvent))
{ PCLOG(" -Frame has an unload event listener"); cannotCache = true; }
+#endif
#if ENABLE(DATABASE)
if (m_frame->document()->hasOpenDatabases())
{ PCLOG(" -Frame has open database handles"); cannotCache = true; }
#endif
+#if ENABLE(SHARED_WORKERS)
+ if (SharedWorkerRepository::hasSharedWorkers(m_frame->document()))
+ { PCLOG(" -Frame has associated SharedWorkers"); cannotCache = true; }
+#endif
if (m_frame->document()->usingGeolocation())
{ PCLOG(" -Frame uses Geolocation"); cannotCache = true; }
if (!m_currentHistoryItem)
@@ -2055,7 +1842,7 @@ public:
virtual void performTask(ScriptExecutionContext* context)
{
ASSERT_UNUSED(context, context->isDocument());
- m_document->dispatchWindowEvent(eventNames().hashchangeEvent, false, false);
+ m_document->dispatchWindowEvent(Event::create(eventNames().hashchangeEvent, false, false));
}
private:
@@ -2067,7 +1854,7 @@ private:
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)
@@ -2097,86 +1884,11 @@ bool FrameLoader::isComplete() const
return m_isComplete;
}
-void FrameLoader::scheduleRedirection(ScheduledRedirection* redirection)
-{
- ASSERT(m_frame->page());
-
- // If a redirect was scheduled during a load, then stop the current load.
- // Otherwise when the current load transitions from a provisional to a
- // committed state, pending redirects may be cancelled.
- if (redirection->wasDuringLoad) {
- if (m_provisionalDocumentLoader)
- m_provisionalDocumentLoader->stopLoading();
- stopLoading(true);
- }
-
- stopRedirectionTimer();
- m_scheduledRedirection.set(redirection);
- if (!m_isComplete && redirection->type != ScheduledRedirection::redirection)
- completed();
- if (m_isComplete || redirection->type != ScheduledRedirection::redirection)
- startRedirectionTimer();
-}
-
-void FrameLoader::startRedirectionTimer()
-{
- ASSERT(m_frame->page());
- ASSERT(m_scheduledRedirection);
-
- m_redirectionTimer.stop();
- m_redirectionTimer.startOneShot(m_scheduledRedirection->delay);
-
- switch (m_scheduledRedirection->type) {
- case ScheduledRedirection::locationChange:
- case ScheduledRedirection::redirection:
- clientRedirected(KURL(m_scheduledRedirection->url),
- m_scheduledRedirection->delay,
- currentTime() + m_redirectionTimer.nextFireInterval(),
- m_scheduledRedirection->lockBackForwardList);
- return;
- case ScheduledRedirection::formSubmission:
- // FIXME: It would make sense to report form submissions as client redirects too.
- // But we didn't do that in the past when form submission used a separate delay
- // mechanism, so doing it will be a behavior change.
- return;
- case ScheduledRedirection::historyNavigation:
- // Don't report history navigations.
- return;
- }
- ASSERT_NOT_REACHED();
-}
-
-void FrameLoader::stopRedirectionTimer()
-{
- if (!m_redirectionTimer.isActive())
- return;
-
- m_redirectionTimer.stop();
-
- if (m_scheduledRedirection) {
- switch (m_scheduledRedirection->type) {
- case ScheduledRedirection::locationChange:
- case ScheduledRedirection::redirection:
- clientRedirectCancelledOrFinished(m_cancellingWithLoadInProgress);
- return;
- case ScheduledRedirection::formSubmission:
- // FIXME: It would make sense to report form submissions as client redirects too.
- // But we didn't do that in the past when form submission used a separate delay
- // mechanism, so doing it will be a behavior change.
- return;
- case ScheduledRedirection::historyNavigation:
- // Don't report history navigations.
- return;
- }
- ASSERT_NOT_REACHED();
- }
-}
-
void FrameLoader::completed()
{
RefPtr<Frame> protect(m_frame);
for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
- child->loader()->parentCompleted();
+ child->redirectScheduler()->startTimer();
if (Frame* parent = m_frame->tree()->parent())
parent->loader()->checkCompleted();
if (m_frame->view())
@@ -2243,13 +1955,13 @@ void FrameLoader::loadFrameRequest(const FrameLoadRequest& request, bool lockHis
ASSERT(frame()->document());
if (SecurityOrigin::shouldTreatURLAsLocal(url.string()) && !isFeedWithNestedProtocolInHTTPFamily(url)) {
- if (!canLoad(url, String(), frame()->document()) && !canLoad(url, referrer)) {
+ if (!SecurityOrigin::canLoad(url, String(), frame()->document()) && !SecurityOrigin::canLoad(url, referrer, 0)) {
FrameLoader::reportLocalLoadFailed(m_frame, url.string());
return;
}
}
- if (shouldHideReferrer(url, referrer))
+ if (SecurityOrigin::shouldHideReferrer(url, referrer))
referrer = String();
FrameLoadType loadType;
@@ -2319,10 +2031,14 @@ void FrameLoader::loadURL(const KURL& newURL, const String& referrer, const Stri
return;
}
+ if (m_unloadEventBeingDispatched)
+ return;
+
NavigationAction action(newURL, newLoadType, isFormSubmission, event);
if (!targetFrame && !frameName.isEmpty()) {
- checkNewWindowPolicy(action, request, formState.release(), frameName);
+ policyChecker()->checkNewWindowPolicy(action, FrameLoader::callContinueLoadAfterNewWindowPolicy,
+ request, formState.release(), frameName, this);
return;
}
@@ -2335,8 +2051,9 @@ void FrameLoader::loadURL(const KURL& newURL, const String& referrer, const Stri
// work properly.
if (shouldScrollToAnchor(isFormSubmission, newLoadType, newURL)) {
oldDocumentLoader->setTriggeringAction(action);
- stopPolicyCheck();
- checkNavigationPolicy(request, oldDocumentLoader.get(), formState.release(),
+ policyChecker()->stopCheck();
+ policyChecker()->setLoadType(newLoadType);
+ policyChecker()->checkNavigationPolicy(request, oldDocumentLoader.get(), formState.release(),
callContinueFragmentScrollAfterNavigationPolicy, this);
} else {
// must grab this now, since this load may stop the previous load and clear this flag
@@ -2385,7 +2102,7 @@ void FrameLoader::load(const ResourceRequest& request, const String& frameName,
return;
}
- checkNewWindowPolicy(NavigationAction(request.url(), NavigationTypeOther), request, 0, frameName);
+ policyChecker()->checkNewWindowPolicy(NavigationAction(request.url(), NavigationTypeOther), FrameLoader::callContinueLoadAfterNewWindowPolicy, request, 0, frameName, this);
}
void FrameLoader::loadWithNavigationAction(const ResourceRequest& request, const NavigationAction& action, bool lockHistory, FrameLoadType type, PassRefPtr<FormState> formState)
@@ -2440,54 +2157,37 @@ void FrameLoader::loadWithDocumentLoader(DocumentLoader* loader, FrameLoadType t
ASSERT(m_frame->view());
- m_policyLoadType = type;
+ if (m_unloadEventBeingDispatched)
+ return;
+
+ policyChecker()->setLoadType(type);
RefPtr<FormState> formState = prpFormState;
bool isFormSubmission = formState;
const KURL& newURL = loader->request().url();
- if (shouldScrollToAnchor(isFormSubmission, m_policyLoadType, newURL)) {
+ if (shouldScrollToAnchor(isFormSubmission, policyChecker()->loadType(), newURL)) {
RefPtr<DocumentLoader> oldDocumentLoader = m_documentLoader;
- NavigationAction action(newURL, m_policyLoadType, isFormSubmission);
+ NavigationAction action(newURL, policyChecker()->loadType(), isFormSubmission);
oldDocumentLoader->setTriggeringAction(action);
- stopPolicyCheck();
- checkNavigationPolicy(loader->request(), oldDocumentLoader.get(), formState,
+ policyChecker()->stopCheck();
+ policyChecker()->checkNavigationPolicy(loader->request(), oldDocumentLoader.get(), formState,
callContinueFragmentScrollAfterNavigationPolicy, this);
} else {
if (Frame* parent = m_frame->tree()->parent())
loader->setOverrideEncoding(parent->loader()->documentLoader()->overrideEncoding());
- stopPolicyCheck();
+ policyChecker()->stopCheck();
setPolicyDocumentLoader(loader);
if (loader->triggeringAction().isEmpty())
- loader->setTriggeringAction(NavigationAction(newURL, m_policyLoadType, isFormSubmission));
+ loader->setTriggeringAction(NavigationAction(newURL, policyChecker()->loadType(), isFormSubmission));
- checkNavigationPolicy(loader->request(), loader, formState,
+ policyChecker()->checkNavigationPolicy(loader->request(), loader, formState,
callContinueLoadAfterNavigationPolicy, this);
}
}
-bool FrameLoader::canLoad(const KURL& url, const String& referrer, const Document* doc)
-{
- return canLoad(url, referrer, doc ? doc->securityOrigin() : 0);
-}
-
-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 (!SecurityOrigin::shouldTreatURLAsLocal(url.string()))
- return true;
-
- // If we were provided a document, we let its local file policy dictate the result,
- // otherwise we allow local loads only if the supplied referrer is also local.
- if (securityOrigin)
- return securityOrigin->canLoadLocalResources();
- if (!referrer.isEmpty())
- return SecurityOrigin::shouldTreatURLAsLocal(referrer);
- return false;
-}
-
void FrameLoader::reportLocalLoadFailed(Frame* frame, const String& url)
{
ASSERT(!url.isEmpty());
@@ -2497,22 +2197,6 @@ void FrameLoader::reportLocalLoadFailed(Frame* frame, const String& url)
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)
-{
- bool referrerIsSecureURL = protocolIs(referrer, "https");
- bool referrerIsWebURL = referrerIsSecureURL || protocolIs(referrer, "http");
-
- if (!referrerIsWebURL)
- return true;
-
- if (!referrerIsSecureURL)
- return false;
-
- bool URLIsSecureURL = url.protocolIs("https");
-
- return !URLIsSecureURL;
-}
-
const ResourceRequest& FrameLoader::initialRequest() const
{
return activeDocumentLoader()->originalRequest();
@@ -2523,50 +2207,26 @@ void FrameLoader::receivedData(const char* data, int length)
activeDocumentLoader()->receivedData(data, length);
}
-void FrameLoader::handleUnimplementablePolicy(const ResourceError& error)
+bool FrameLoader::willLoadMediaElementURL(KURL& url)
{
- m_delegateIsHandlingUnimplementablePolicy = true;
- m_client->dispatchUnableToImplementPolicy(error);
- m_delegateIsHandlingUnimplementablePolicy = false;
-}
+ if (!m_client->shouldLoadMediaElementURL(url))
+ return false;
-void FrameLoader::cannotShowMIMEType(const ResourceResponse& response)
-{
- handleUnimplementablePolicy(m_client->cannotShowMIMETypeError(response));
-}
+ ResourceRequest request(url);
-ResourceError FrameLoader::interruptionForPolicyChangeError(const ResourceRequest& request)
-{
- return m_client->interruptForPolicyChangeError(request);
-}
+ unsigned long identifier;
+ ResourceError error;
+ requestFromDelegate(request, identifier, error);
+ sendRemainingDelegateMessages(identifier, ResourceResponse(url, String(), -1, String(), String()), -1, error);
-void FrameLoader::checkNavigationPolicy(const ResourceRequest& newRequest, NavigationPolicyDecisionFunction function, void* argument)
-{
- checkNavigationPolicy(newRequest, activeDocumentLoader(), 0, function, argument);
+ url = request.url();
+
+ return error.isNull();
}
-void FrameLoader::checkContentPolicy(const String& MIMEType, ContentPolicyDecisionFunction function, void* argument)
+ResourceError FrameLoader::interruptionForPolicyChangeError(const ResourceRequest& request)
{
- ASSERT(activeDocumentLoader());
-
- // Always show content with valid substitute data.
- if (activeDocumentLoader()->substituteData().isValid()) {
- function(argument, PolicyUse);
- return;
- }
-
-#if ENABLE(FTPDIR)
- // Respect the hidden FTP Directory Listing pref so it can be tested even if the policy delegate might otherwise disallow it
- Settings* settings = m_frame->settings();
- if (settings && settings->forceFTPDirectoryListings() && MIMEType == "application/x-ftp-directory") {
- function(argument, PolicyUse);
- return;
- }
-#endif
-
- m_policyCheck.set(function, argument);
- m_client->dispatchDecidePolicyForMIMEType(&FrameLoader::continueAfterContentPolicy,
- MIMEType, activeDocumentLoader()->request());
+ return m_client->interruptForPolicyChangeError(request);
}
bool FrameLoader::shouldReloadToHandleUnreachableURL(DocumentLoader* docLoader)
@@ -2576,7 +2236,7 @@ bool FrameLoader::shouldReloadToHandleUnreachableURL(DocumentLoader* docLoader)
if (unreachableURL.isEmpty())
return false;
- if (!isBackForwardLoadType(m_policyLoadType))
+ if (!isBackForwardLoadType(policyChecker()->loadType()))
return false;
// We only treat unreachableURLs specially during the delegate callbacks
@@ -2585,7 +2245,7 @@ bool FrameLoader::shouldReloadToHandleUnreachableURL(DocumentLoader* docLoader)
// case handles malformed URLs and unknown schemes. Loading alternate content
// at other times behaves like a standard load.
DocumentLoader* compareDocumentLoader = 0;
- if (m_delegateIsDecidingNavigationPolicy || m_delegateIsHandlingUnimplementablePolicy)
+ if (policyChecker()->delegateIsDecidingNavigationPolicy() || policyChecker()->delegateIsHandlingUnimplementablePolicy())
compareDocumentLoader = m_policyDocumentLoader.get();
else if (m_delegateIsHandlingProvisionalLoadError)
compareDocumentLoader = m_provisionalDocumentLoader.get();
@@ -2676,7 +2336,8 @@ bool FrameLoader::shouldAllowNavigation(Frame* targetFrame) const
//
// Or the target frame is:
// - a top-level frame in the frame hierarchy and the active frame can
- // navigate the target frame's opener per above.
+ // navigate the target frame's opener per above or it is the opener of
+ // the target frame.
if (!targetFrame)
return true;
@@ -2691,6 +2352,10 @@ bool FrameLoader::shouldAllowNavigation(Frame* targetFrame) const
if (targetFrame == m_frame->tree()->top())
return true;
+ // Let a frame navigate its opener if the opener is a top-level window.
+ if (!targetFrame->tree()->parent() && m_frame->loader()->opener() == targetFrame)
+ return true;
+
Document* activeDocument = m_frame->document();
ASSERT(activeDocument);
const SecurityOrigin* activeSecurityOrigin = activeDocument->securityOrigin();
@@ -2725,6 +2390,7 @@ void FrameLoader::stopLoadingSubframes()
void FrameLoader::stopAllLoaders(DatabasePolicy databasePolicy)
{
+ ASSERT(!m_frame->document() || !m_frame->document()->inPageCache());
if (m_unloadEventBeingDispatched)
return;
@@ -2734,7 +2400,7 @@ void FrameLoader::stopAllLoaders(DatabasePolicy databasePolicy)
m_inStopAllLoaders = true;
- stopPolicyCheck();
+ policyChecker()->stopCheck();
stopLoadingSubframes();
if (m_provisionalDocumentLoader)
@@ -2862,7 +2528,8 @@ void FrameLoader::commitProvisionalLoad(PassRefPtr<CachedPage> prpCachedPage)
RefPtr<CachedPage> cachedPage = prpCachedPage;
RefPtr<DocumentLoader> pdl = m_provisionalDocumentLoader;
- LOG(Loading, "WebCoreLoading %s: About to commit provisional load from previous URL %s", m_frame->tree()->name().string().utf8().data(), m_URL.string().utf8().data());
+ LOG(PageCache, "WebCoreLoading %s: About to commit provisional load from previous URL '%s' to new URL '%s'", m_frame->tree()->name().string().utf8().data(), m_URL.string().utf8().data(),
+ pdl ? pdl->url().string().utf8().data() : "<no provisional DocumentLoader>");
// Check to see if we need to cache the page we are navigating away from into the back/forward cache.
// We are doing this here because we know for sure that a new page is about to be loaded.
@@ -2883,10 +2550,9 @@ void FrameLoader::commitProvisionalLoad(PassRefPtr<CachedPage> prpCachedPage)
if (m_sentRedirectNotification)
clientRedirectCancelledOrFinished(false);
- if (cachedPage && cachedPage->document()) {
+ if (cachedPage && cachedPage->document())
open(*cachedPage);
- cachedPage->clear();
- } else {
+ else {
KURL url = pdl->substituteData().responseURL();
if (url.isEmpty())
url = pdl->url();
@@ -2903,11 +2569,11 @@ void FrameLoader::commitProvisionalLoad(PassRefPtr<CachedPage> prpCachedPage)
if (m_loadType == FrameLoadTypeStandard && m_documentLoader->isClientRedirect())
updateHistoryForClientRedirect();
- if (m_documentLoader->isLoadingFromCachedPage()) {
+ if (m_loadingFromCachedPage) {
m_frame->document()->documentDidBecomeActive();
// Force a layout to update view size and thereby update scrollbars.
- m_client->forceLayout();
+ m_frame->view()->forceLayout();
const ResponseVector& responses = m_documentLoader->responses();
size_t count = responses.size();
@@ -3104,7 +2770,7 @@ void FrameLoader::open(CachedPage& cachedPage)
ASSERT(m_frame->page());
ASSERT(m_frame->page()->mainFrame() == m_frame);
- cancelRedirection();
+ m_frame->redirectScheduler()->cancel();
// We still have to close the previous part page.
closeURL();
@@ -3115,13 +2781,12 @@ void FrameLoader::open(CachedPage& cachedPage)
m_frame->setJSDefaultStatusBarText(String());
}
- open(*cachedPage.cachedMainFrame());
cachedPage.restore(m_frame->page());
checkCompleted();
}
-void FrameLoader::open(CachedFrame& cachedFrame)
+void FrameLoader::open(CachedFrameBase& cachedFrame)
{
m_isComplete = false;
@@ -3137,8 +2802,7 @@ void FrameLoader::open(CachedFrame& cachedFrame)
m_workingURL = url;
started();
-
- clear();
+ clear(true, true, cachedFrame.isMainFrame());
Document* document = cachedFrame.document();
ASSERT(document);
@@ -3153,8 +2817,11 @@ void FrameLoader::open(CachedFrame& cachedFrame)
// When navigating to a CachedFrame its FrameView should never be null. If it is we'll crash in creative ways downstream.
ASSERT(view);
- if (view)
- view->setWasScrolledByUser(false);
+ view->setWasScrolledByUser(false);
+
+ // Use the current ScrollView's frame rect.
+ if (m_frame->view())
+ view->setFrameRect(m_frame->view()->frameRect());
m_frame->setView(view);
m_frame->setDocument(document);
@@ -3215,12 +2882,6 @@ String FrameLoader::generatedMIMETypeForURLScheme(const String& URLScheme)
return m_client->generatedMIMETypeForURLScheme(URLScheme);
}
-void FrameLoader::cancelContentPolicyCheck()
-{
- m_client->cancelPolicyCheck();
- m_policyCheck.clear();
-}
-
void FrameLoader::didReceiveServerRedirectForProvisionalLoadForFrame()
{
m_client->dispatchDidReceiveServerRedirectForProvisionalLoad();
@@ -3344,14 +3005,6 @@ CachePolicy FrameLoader::subresourceCachePolicy() const
return CachePolicyVerify;
}
-void FrameLoader::stopPolicyCheck()
-{
- m_client->cancelPolicyCheck();
- PolicyCheck check = m_policyCheck;
- m_policyCheck.clear();
- check.cancel();
-}
-
void FrameLoader::checkLoadCompleteForThisFrame()
{
ASSERT(m_client->hasWebView());
@@ -3456,14 +3109,7 @@ void FrameLoader::checkLoadCompleteForThisFrame()
ASSERT_NOT_REACHED();
}
-void FrameLoader::continueAfterContentPolicy(PolicyAction policy)
-{
- PolicyCheck check = m_policyCheck;
- m_policyCheck.clear();
- check.call(policy);
-}
-
-void FrameLoader::continueLoadAfterWillSubmitForm(PolicyAction)
+void FrameLoader::continueLoadAfterWillSubmitForm()
{
if (!m_provisionalDocumentLoader)
return;
@@ -3480,7 +3126,7 @@ void FrameLoader::continueLoadAfterWillSubmitForm(PolicyAction)
if (activeDocLoader && activeDocLoader->isLoadingMainResource())
return;
- m_provisionalDocumentLoader->setLoadingFromCachedPage(false);
+ m_loadingFromCachedPage = false;
unsigned long identifier = 0;
@@ -3544,7 +3190,7 @@ void FrameLoader::closeAndRemoveChild(Frame* child)
child->tree()->detachFromParent();
child->setView(0);
- if (child->ownerElement())
+ if (child->ownerElement() && child->page())
child->page()->decrementFrameCount();
child->pageDestroyed();
@@ -3570,6 +3216,8 @@ void FrameLoader::checkLoadComplete()
{
ASSERT(m_client->hasWebView());
+ m_shouldCallCheckLoadComplete = false;
+
// FIXME: Always traversing the entire frame tree is a bit inefficient, but
// is currently needed in order to null out the previous history item for all frames.
if (Page* page = m_frame->page())
@@ -3618,12 +3266,13 @@ void FrameLoader::detachFromParent()
saveScrollPositionAndViewStateToItem(currentHistoryItem());
detachChildren();
+#if ENABLE(INSPECTOR)
if (Page* page = m_frame->page())
page->inspectorController()->frameDetachedFromParent(m_frame);
+#endif
+
+ detachViewsAndDocumentLoader();
- m_client->detachedFromParent2();
- setDocumentLoader(0);
- m_client->detachedFromParent3();
if (Frame* parent = m_frame->tree()->parent()) {
parent->loader()->closeAndRemoveChild(m_frame);
parent->loader()->scheduleCheckCompleted();
@@ -3632,6 +3281,13 @@ void FrameLoader::detachFromParent()
m_frame->pageDestroyed();
}
}
+
+void FrameLoader::detachViewsAndDocumentLoader()
+{
+ m_client->detachedFromParent2();
+ setDocumentLoader(0);
+ m_client->detachedFromParent3();
+}
void FrameLoader::addExtraFieldsToSubresourceRequest(ResourceRequest& request)
{
@@ -3759,7 +3415,7 @@ void FrameLoader::loadPostRequest(const ResourceRequest& inRequest, const String
if (Frame* targetFrame = formState ? 0 : findFrameForNavigation(frameName))
targetFrame->loader()->loadWithNavigationAction(workingResourceRequest, action, lockHistory, loadType, formState.release());
else
- checkNewWindowPolicy(action, workingResourceRequest, formState.release(), frameName);
+ policyChecker()->checkNewWindowPolicy(action, FrameLoader::callContinueLoadAfterNewWindowPolicy, workingResourceRequest, formState.release(), frameName, this);
} else
loadWithNavigationAction(workingResourceRequest, action, lockHistory, loadType, formState.release());
}
@@ -3767,7 +3423,7 @@ void FrameLoader::loadPostRequest(const ResourceRequest& inRequest, const String
unsigned long FrameLoader::loadResourceSynchronously(const ResourceRequest& request, StoredCredentials storedCredentials, ResourceError& error, ResourceResponse& response, Vector<char>& data)
{
String referrer = m_outgoingReferrer;
- if (shouldHideReferrer(request.url(), referrer))
+ if (SecurityOrigin::shouldHideReferrer(request.url(), referrer))
referrer = String();
ResourceRequest initialRequest = request;
@@ -3898,7 +3554,7 @@ void FrameLoader::callContinueFragmentScrollAfterNavigationPolicy(void* argument
void FrameLoader::continueFragmentScrollAfterNavigationPolicy(const ResourceRequest& request, bool shouldContinue)
{
- bool isRedirect = m_quickRedirectComing || m_policyLoadType == FrameLoadTypeRedirectWithLockedBackForwardList;
+ bool isRedirect = m_quickRedirectComing || policyChecker()->loadType() == FrameLoadTypeRedirectWithLockedBackForwardList;
m_quickRedirectComing = false;
if (!shouldContinue)
@@ -3961,101 +3617,6 @@ bool FrameLoader::shouldScrollToAnchor(bool isFormSubmission, FrameLoadType load
&& !m_frame->document()->isFrameSet();
}
-void FrameLoader::checkNewWindowPolicy(const NavigationAction& action, const ResourceRequest& request,
- PassRefPtr<FormState> formState, const String& frameName)
-{
- m_policyCheck.set(request, formState, frameName,
- callContinueLoadAfterNewWindowPolicy, this);
- m_client->dispatchDecidePolicyForNewWindowAction(&FrameLoader::continueAfterNewWindowPolicy,
- action, request, formState, frameName);
-}
-
-void FrameLoader::continueAfterNewWindowPolicy(PolicyAction policy)
-{
- PolicyCheck check = m_policyCheck;
- m_policyCheck.clear();
-
- switch (policy) {
- case PolicyIgnore:
- check.clearRequest();
- break;
- case PolicyDownload:
- m_client->startDownload(check.request());
- check.clearRequest();
- break;
- case PolicyUse:
- break;
- }
-
- check.call(policy == PolicyUse);
-}
-
-void FrameLoader::checkNavigationPolicy(const ResourceRequest& request, DocumentLoader* loader,
- PassRefPtr<FormState> formState, NavigationPolicyDecisionFunction function, void* argument)
-{
- NavigationAction action = loader->triggeringAction();
- if (action.isEmpty()) {
- action = NavigationAction(request.url(), NavigationTypeOther);
- loader->setTriggeringAction(action);
- }
-
- // Don't ask more than once for the same request or if we are loading an empty URL.
- // This avoids confusion on the part of the client.
- if (equalIgnoringHeaderFields(request, loader->lastCheckedRequest()) || (!request.isNull() && request.url().isEmpty())) {
- function(argument, request, 0, true);
- loader->setLastCheckedRequest(request);
- return;
- }
-
- // We are always willing to show alternate content for unreachable URLs;
- // treat it like a reload so it maintains the right state for b/f list.
- if (loader->substituteData().isValid() && !loader->substituteData().failingURL().isEmpty()) {
- if (isBackForwardLoadType(m_policyLoadType))
- m_policyLoadType = FrameLoadTypeReload;
- function(argument, request, 0, true);
- return;
- }
-
- loader->setLastCheckedRequest(request);
-
- m_policyCheck.set(request, formState.get(), function, argument);
-
- m_delegateIsDecidingNavigationPolicy = true;
- m_client->dispatchDecidePolicyForNavigationAction(&FrameLoader::continueAfterNavigationPolicy,
- action, request, formState);
- m_delegateIsDecidingNavigationPolicy = false;
-}
-
-void FrameLoader::continueAfterNavigationPolicy(PolicyAction policy)
-{
- PolicyCheck check = m_policyCheck;
- m_policyCheck.clear();
-
- bool shouldContinue = policy == PolicyUse;
-
- switch (policy) {
- case PolicyIgnore:
- check.clearRequest();
- break;
- case PolicyDownload:
- m_client->startDownload(check.request());
- check.clearRequest();
- break;
- case PolicyUse: {
- ResourceRequest request(check.request());
-
- if (!m_client->canHandleRequest(request)) {
- handleUnimplementablePolicy(m_client->cannotShowURLError(check.request()));
- check.clearRequest();
- shouldContinue = false;
- }
- break;
- }
- }
-
- check.call(shouldContinue);
-}
-
void FrameLoader::callContinueLoadAfterNavigationPolicy(void* argument,
const ResourceRequest& request, PassRefPtr<FormState> formState, bool shouldContinue)
{
@@ -4090,7 +3651,7 @@ void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest&, Pass
// If the navigation request came from the back/forward menu, and we punt on it, we have the
// problem that we have optimistically moved the b/f cursor already, so move it back. For sanity,
// we only do this when punting a navigation for the target frame or top-level frame.
- if ((isTargetItem || isLoadingMainFrame()) && isBackForwardLoadType(m_policyLoadType))
+ if ((isTargetItem || isLoadingMainFrame()) && isBackForwardLoadType(policyChecker()->loadType()))
if (Page* page = m_frame->page()) {
Frame* mainFrame = page->mainFrame();
if (HistoryItem* resetItem = mainFrame->loader()->m_currentHistoryItem.get()) {
@@ -4102,7 +3663,7 @@ void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest&, Pass
return;
}
- FrameLoadType type = m_policyLoadType;
+ FrameLoadType type = policyChecker()->loadType();
stopAllLoaders();
// <rdar://problem/6250856> - In certain circumstances on pages with multiple frames, stopAllLoaders()
@@ -4110,7 +3671,7 @@ void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest&, Pass
if (!m_frame->page())
return;
-#if ENABLE(JAVASCRIPT_DEBUGGER)
+#if ENABLE(JAVASCRIPT_DEBUGGER) && ENABLE(INSPECTOR)
if (Page* page = m_frame->page()) {
if (page->mainFrame() == m_frame)
page->inspectorController()->resumeDebugger();
@@ -4127,12 +3688,11 @@ void FrameLoader::continueLoadAfterNavigationPolicy(const ResourceRequest&, Pass
return;
if (formState)
- m_client->dispatchWillSubmitForm(&FrameLoader::continueLoadAfterWillSubmitForm, formState);
+ m_client->dispatchWillSubmitForm(&PolicyChecker::continueLoadAfterWillSubmitForm, formState);
else
continueLoadAfterWillSubmitForm();
}
-
void FrameLoader::callContinueLoadAfterNewWindowPolicy(void* argument,
const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName, bool shouldContinue)
{
@@ -4154,7 +3714,7 @@ void FrameLoader::continueLoadAfterNewWindowPolicy(const ResourceRequest& reques
if (frameName != "_blank")
mainFrame->tree()->setName(frameName);
- mainFrame->loader()->setOpenedByDOM();
+ mainFrame->page()->setOpenedByDOM();
mainFrame->loader()->m_client->dispatchShow();
mainFrame->loader()->setOpener(frame.get());
mainFrame->loader()->loadWithNavigationAction(request, NavigationAction(), false, FrameLoadTypeStandard, formState);
@@ -4201,7 +3761,9 @@ void FrameLoader::loadedResourceFromMemoryCache(const CachedResource* resource)
if (!page)
return;
+#if ENABLE(INSPECTOR)
page->inspectorController()->didLoadResourceFromMemoryCache(m_documentLoader.get(), resource);
+#endif
if (!resource->sendResourceLoadCallbacks() || m_documentLoader->haveToldClientAboutLoad(resource->url()))
return;
@@ -4249,26 +3811,6 @@ bool FrameLoader::shouldInterruptLoadForXFrameOptions(const String& content, con
return false;
}
-bool FrameLoader::canGoBackOrForward(int distance) const
-{
- if (Page* page = m_frame->page()) {
- if (distance == 0)
- return true;
- if (distance > 0 && distance <= page->backForwardList()->forwardListCount())
- return true;
- if (distance < 0 && -distance <= page->backForwardList()->backListCount())
- return true;
- }
- return false;
-}
-
-int FrameLoader::getHistoryLength()
-{
- if (Page* page = m_frame->page())
- return page->backForwardList()->backListCount() + 1;
- return 0;
-}
-
void FrameLoader::addHistoryItemForFragmentScroll()
{
addBackForwardItemClippedAtTarget(false);
@@ -4279,7 +3821,17 @@ bool FrameLoader::loadProvisionalItemFromCachedPage()
RefPtr<CachedPage> cachedPage = pageCache()->get(m_provisionalHistoryItem.get());
if (!cachedPage || !cachedPage->document())
return false;
- provisionalDocumentLoader()->loadFromCachedPage(cachedPage.release());
+
+ DocumentLoader *provisionalLoader = provisionalDocumentLoader();
+ LOG(PageCache, "WebCorePageCache: FrameLoader %p loading provisional DocumentLoader %p with URL '%s' from CachedPage %p", this, provisionalLoader, provisionalLoader->url().string().utf8().data(), cachedPage.get());
+
+ provisionalLoader->prepareForLoadStart();
+
+ m_loadingFromCachedPage = true;
+
+ provisionalLoader->setCommitted(true);
+ commitProvisionalLoad(cachedPage);
+
return true;
}
@@ -4288,12 +3840,26 @@ void FrameLoader::cachePageForHistoryItem(HistoryItem* item)
if (!canCachePage() || item->isInPageCache())
return;
+ pageHidden();
+
if (Page* page = m_frame->page()) {
RefPtr<CachedPage> cachedPage = CachedPage::create(page);
pageCache()->add(item, cachedPage.release());
}
}
+void FrameLoader::pageHidden()
+{
+ m_unloadEventBeingDispatched = true;
+ if (m_frame->domWindow())
+ m_frame->domWindow()->dispatchEvent(PageTransitionEvent::create(EventNames().pagehideEvent, true), m_frame->document());
+ m_unloadEventBeingDispatched = false;
+
+ // Send pagehide event for subframes as well
+ for (Frame* child = m_frame->tree()->firstChild(); child; child = child->tree()->nextSibling())
+ child->loader()->pageHidden();
+}
+
bool FrameLoader::shouldTreatURLAsSameAsCurrent(const KURL& url) const
{
if (!m_currentHistoryItem)
@@ -5038,94 +4604,6 @@ void FrameLoader::didCancelAuthenticationChallenge(ResourceLoader* loader, const
m_client->dispatchDidCancelAuthenticationChallenge(loader->documentLoader(), loader->identifier(), currentWebChallenge);
}
-PolicyCheck::PolicyCheck()
- : m_navigationFunction(0)
- , m_newWindowFunction(0)
- , m_contentFunction(0)
-{
-}
-
-void PolicyCheck::clear()
-{
- clearRequest();
- m_navigationFunction = 0;
- m_newWindowFunction = 0;
- m_contentFunction = 0;
-}
-
-void PolicyCheck::set(const ResourceRequest& request, PassRefPtr<FormState> formState,
- NavigationPolicyDecisionFunction function, void* argument)
-{
- m_request = request;
- m_formState = formState;
- m_frameName = String();
-
- m_navigationFunction = function;
- m_newWindowFunction = 0;
- m_contentFunction = 0;
- m_argument = argument;
-}
-
-void PolicyCheck::set(const ResourceRequest& request, PassRefPtr<FormState> formState,
- const String& frameName, NewWindowPolicyDecisionFunction function, void* argument)
-{
- m_request = request;
- m_formState = formState;
- m_frameName = frameName;
-
- m_navigationFunction = 0;
- m_newWindowFunction = function;
- m_contentFunction = 0;
- m_argument = argument;
-}
-
-void PolicyCheck::set(ContentPolicyDecisionFunction function, void* argument)
-{
- m_request = ResourceRequest();
- m_formState = 0;
- m_frameName = String();
-
- m_navigationFunction = 0;
- m_newWindowFunction = 0;
- m_contentFunction = function;
- m_argument = argument;
-}
-
-void PolicyCheck::call(bool shouldContinue)
-{
- if (m_navigationFunction)
- m_navigationFunction(m_argument, m_request, m_formState.get(), shouldContinue);
- if (m_newWindowFunction)
- m_newWindowFunction(m_argument, m_request, m_formState.get(), m_frameName, shouldContinue);
- ASSERT(!m_contentFunction);
-}
-
-void PolicyCheck::call(PolicyAction action)
-{
- ASSERT(!m_navigationFunction);
- ASSERT(!m_newWindowFunction);
- ASSERT(m_contentFunction);
- m_contentFunction(m_argument, action);
-}
-
-void PolicyCheck::clearRequest()
-{
- m_request = ResourceRequest();
- m_formState = 0;
- m_frameName = String();
-}
-
-void PolicyCheck::cancel()
-{
- clearRequest();
- if (m_navigationFunction)
- m_navigationFunction(m_argument, m_request, m_formState.get(), false);
- if (m_newWindowFunction)
- m_newWindowFunction(m_argument, m_request, m_formState.get(), m_frameName, false);
- if (m_contentFunction)
- m_contentFunction(m_argument, PolicyIgnore);
-}
-
void FrameLoader::setTitle(const String& title)
{
documentLoader()->setTitle(title);
@@ -5143,6 +4621,7 @@ String FrameLoader::referrer() const
void FrameLoader::dispatchDocumentElementAvailable()
{
+ m_frame->injectUserScripts(InjectAtDocumentStart);
m_client->documentElementAvailable();
}
@@ -5153,12 +4632,14 @@ void FrameLoader::dispatchWindowObjectAvailable()
m_client->windowObjectCleared();
+#if ENABLE(INSPECTOR)
if (Page* page = m_frame->page()) {
if (InspectorController* inspector = page->inspectorController())
inspector->inspectedWindowScriptObjectCleared(m_frame);
if (InspectorController* inspector = page->parentInspectorController())
inspector->windowScriptObjectAvailable();
}
+#endif
}
PassRefPtr<Widget> FrameLoader::createJavaAppletWidget(const IntSize& size, HTMLAppletElement* element, const HashMap<String, String>& args)
@@ -5179,7 +4660,7 @@ PassRefPtr<Widget> FrameLoader::createJavaAppletWidget(const IntSize& size, HTML
if (!codeBaseURLString.isEmpty()) {
KURL codeBaseURL = completeURL(codeBaseURLString);
- if (!canLoad(codeBaseURL, String(), element->document())) {
+ if (!SecurityOrigin::canLoad(codeBaseURL, String(), element->document())) {
FrameLoader::reportLocalLoadFailed(m_frame, codeBaseURL.string());
return 0;
}
@@ -5223,16 +4704,20 @@ void FrameLoader::dispatchDidCommitLoad()
m_client->dispatchDidCommitLoad();
+#if ENABLE(INSPECTOR)
if (Page* page = m_frame->page())
page->inspectorController()->didCommitLoad(m_documentLoader.get());
+#endif
}
void FrameLoader::dispatchAssignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader* loader, const ResourceRequest& request)
{
m_client->assignIdentifierToInitialRequest(identifier, loader, request);
+#if ENABLE(INSPECTOR)
if (Page* page = m_frame->page())
page->inspectorController()->identifierForInitialRequest(identifier, loader, request);
+#endif
}
void FrameLoader::dispatchWillSendRequest(DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
@@ -5246,32 +4731,40 @@ void FrameLoader::dispatchWillSendRequest(DocumentLoader* loader, unsigned long
if (!request.isNull() && oldRequestURL != request.url().string().impl())
m_documentLoader->didTellClientAboutLoad(request.url());
+#if ENABLE(INSPECTOR)
if (Page* page = m_frame->page())
page->inspectorController()->willSendRequest(loader, identifier, request, redirectResponse);
+#endif
}
void FrameLoader::dispatchDidReceiveResponse(DocumentLoader* loader, unsigned long identifier, const ResourceResponse& r)
{
m_client->dispatchDidReceiveResponse(loader, identifier, r);
+#if ENABLE(INSPECTOR)
if (Page* page = m_frame->page())
page->inspectorController()->didReceiveResponse(loader, identifier, r);
+#endif
}
void FrameLoader::dispatchDidReceiveContentLength(DocumentLoader* loader, unsigned long identifier, int length)
{
m_client->dispatchDidReceiveContentLength(loader, identifier, length);
+#if ENABLE(INSPECTOR)
if (Page* page = m_frame->page())
page->inspectorController()->didReceiveContentLength(loader, identifier, length);
+#endif
}
void FrameLoader::dispatchDidFinishLoading(DocumentLoader* loader, unsigned long identifier)
{
m_client->dispatchDidFinishLoading(loader, identifier);
+#if ENABLE(INSPECTOR)
if (Page* page = m_frame->page())
page->inspectorController()->didFinishLoading(loader, identifier);
+#endif
}
void FrameLoader::tellClientAboutPastMemoryCacheLoads()
diff --git a/WebCore/loader/FrameLoader.h b/WebCore/loader/FrameLoader.h
index 3d3f9c3..3a1d27f 100644
--- a/WebCore/loader/FrameLoader.h
+++ b/WebCore/loader/FrameLoader.h
@@ -32,9 +32,13 @@
#include "CachePolicy.h"
#include "FrameLoaderTypes.h"
+#include "PolicyCallback.h"
+#include "PolicyChecker.h"
+#include "RedirectScheduler.h"
#include "ResourceRequest.h"
#include "ThreadableLoader.h"
#include "Timer.h"
+#include <wtf/Forward.h>
namespace WebCore {
@@ -42,7 +46,7 @@ namespace WebCore {
class Archive;
#endif
class AuthenticationChallenge;
- class CachedFrame;
+ class CachedFrameBase;
class CachedPage;
class CachedResource;
class Document;
@@ -73,46 +77,10 @@ namespace WebCore {
class Widget;
struct FrameLoadRequest;
- struct ScheduledRedirection;
struct WindowFeatures;
bool isBackForwardLoadType(FrameLoadType);
- typedef void (*NavigationPolicyDecisionFunction)(void* argument,
- const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue);
- typedef void (*NewWindowPolicyDecisionFunction)(void* argument,
- const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, bool shouldContinue);
- typedef void (*ContentPolicyDecisionFunction)(void* argument, PolicyAction);
-
- class PolicyCheck {
- public:
- PolicyCheck();
-
- void clear();
- void set(const ResourceRequest&, PassRefPtr<FormState>,
- NavigationPolicyDecisionFunction, void* argument);
- void set(const ResourceRequest&, PassRefPtr<FormState>, const String& frameName,
- NewWindowPolicyDecisionFunction, void* argument);
- void set(ContentPolicyDecisionFunction, void* argument);
-
- const ResourceRequest& request() const { return m_request; }
- void clearRequest();
-
- void call(bool shouldContinue);
- void call(PolicyAction);
- void cancel();
-
- private:
- ResourceRequest m_request;
- RefPtr<FormState> m_formState;
- String m_frameName;
-
- NavigationPolicyDecisionFunction m_navigationFunction;
- NewWindowPolicyDecisionFunction m_newWindowFunction;
- ContentPolicyDecisionFunction m_contentFunction;
- void* m_argument;
- };
-
class FrameLoader : public Noncopyable {
public:
FrameLoader(Frame*, FrameLoaderClient*);
@@ -122,6 +90,8 @@ namespace WebCore {
Frame* frame() const { return m_frame; }
+ PolicyChecker* policyChecker() { return &m_policyChecker; }
+
// FIXME: This is not cool, people. There are too many different functions that all start loads.
// We should aim to consolidate these into a smaller set of functions, and try to reuse more of
// the logic by extracting common code paths.
@@ -144,14 +114,8 @@ namespace WebCore {
void loadArchive(PassRefPtr<Archive>);
#endif
- // Returns true for any non-local URL. If document parameter is supplied, its local load policy dictates,
- // otherwise if referrer is non-empty and represents a local file, then the local load is allowed.
- static bool canLoad(const KURL&, const String& referrer, const Document*);
- static bool canLoad(const KURL&, const String& referrer, const SecurityOrigin* = 0);
static void reportLocalLoadFailed(Frame*, const String& url);
- static bool shouldHideReferrer(const KURL&, const String& referrer);
-
// Called by createWindow in JSDOMWindowBase.cpp, e.g. to fulfill a modal dialog creation
Frame* createWindow(FrameLoader* frameLoaderForFrameLookup, const FrameLoadRequest&, const WindowFeatures&, bool& created);
@@ -195,6 +159,8 @@ namespace WebCore {
void receivedMainResourceError(const ResourceError&, bool isComplete);
void receivedData(const char*, int);
+ bool willLoadMediaElementURL(KURL&);
+
void handleFallbackContent();
bool isStopping() const;
@@ -204,8 +170,6 @@ namespace WebCore {
ResourceError fileDoesNotExistError(const ResourceResponse&) const;
ResourceError blockedError(const ResourceRequest&) const;
ResourceError cannotShowURLError(const ResourceRequest&) const;
-
- void cannotShowMIMEType(const ResourceResponse&);
ResourceError interruptionForPolicyChangeError(const ResourceRequest&);
bool isHostedByObjectElement() const;
@@ -214,10 +178,6 @@ namespace WebCore {
bool representationExistsForURLScheme(const String& URLScheme);
String generatedMIMETypeForURLScheme(const String& URLScheme);
- void checkNavigationPolicy(const ResourceRequest&, NavigationPolicyDecisionFunction function, void* argument);
- void checkContentPolicy(const String& MIMEType, ContentPolicyDecisionFunction, void* argument);
- void cancelContentPolicyCheck();
-
void reload(bool endToEndReload = false);
void reloadWithOverrideEncoding(const String& overrideEncoding);
@@ -246,6 +206,7 @@ namespace WebCore {
void checkLoadComplete();
void detachFromParent();
+ void detachViewsAndDocumentLoader();
void addExtraFieldsToSubresourceRequest(ResourceRequest&);
void addExtraFieldsToMainResourceRequest(ResourceRequest&);
@@ -265,7 +226,7 @@ namespace WebCore {
bool lockHistory, PassRefPtr<Event>, PassRefPtr<FormState>);
void stop();
- void stopLoading(bool sendUnload, DatabasePolicy = DatabasePolicyStop);
+ void stopLoading(UnloadEventPolicy, DatabasePolicy = DatabasePolicyStop);
bool closeURL();
void didExplicitOpen();
@@ -275,16 +236,6 @@ namespace WebCore {
KURL baseURL() const;
- bool isScheduledLocationChangePending() const { return m_scheduledRedirection && isLocationChange(*m_scheduledRedirection); }
- void scheduleHTTPRedirection(double delay, const String& url);
- void scheduleLocationChange(const String& url, const String& referrer, bool lockHistory = true, bool lockBackForwardList = true, bool userGesture = false);
- void scheduleRefresh(bool userGesture = false);
- void scheduleHistoryNavigation(int steps);
-
- bool canGoBackOrForward(int distance) const;
- void goBackOrForward(int distance);
- int getHistoryLength();
-
void begin();
void begin(const KURL&, bool dispatchWindowObjectAvailable = true, SecurityOrigin* forcedSecurityOrigin = 0);
@@ -312,10 +263,13 @@ namespace WebCore {
void dispatchDocumentElementAvailable();
void restoreDocumentState();
+ // Mixed content related functions.
+ static bool isMixedContent(SecurityOrigin* context, const KURL&);
+ void checkIfDisplayInsecureContent(SecurityOrigin* context, const KURL&);
+ void checkIfRunInsecureContent(SecurityOrigin* context, const KURL&);
+
Frame* opener();
void setOpener(Frame*);
- bool openedByDOM() const;
- void setOpenedByDOM();
bool isProcessingUserGesture();
@@ -350,6 +304,7 @@ namespace WebCore {
void setTitle(const String&);
void commitProvisionalLoad(PassRefPtr<CachedPage>);
+ bool isLoadingFromCachedPage() const { return m_loadingFromCachedPage; }
void goToItem(HistoryItem*, FrameLoadType);
void saveDocumentAndScrollState();
@@ -357,16 +312,8 @@ namespace WebCore {
HistoryItem* currentHistoryItem();
void setCurrentHistoryItem(PassRefPtr<HistoryItem>);
- enum LocalLoadPolicy {
- AllowLocalLoadsForAll, // No restriction on local loads.
- AllowLocalLoadsForLocalAndSubstituteData,
- AllowLocalLoadsForLocalOnly,
- };
- static void setLocalLoadPolicy(LocalLoadPolicy);
- static bool restrictAccessToLocal();
- static bool allowSubstituteDataAccessToLocal();
-
bool committingFirstRealLoad() const { return !m_creatingInitialEmptyDocument && !m_committedFirstRealDocumentLoad; }
+ bool committedFirstRealDocumentLoad() const { return m_committedFirstRealDocumentLoad; }
void iconLoadDecisionAvailable();
@@ -379,6 +326,20 @@ namespace WebCore {
bool shouldInterruptLoadForXFrameOptions(const String&, const KURL&);
+ void open(CachedFrameBase&);
+
+ // FIXME: Should these really be public?
+ void completed();
+ bool allAncestorsAreComplete() const; // including this
+ bool allChildrenAreComplete() const; // immediate children, not all descendants
+ void clientRedirected(const KURL&, double delay, double fireDate, bool lockBackForwardList);
+ void clientRedirectCancelledOrFinished(bool cancelWithLoadInProgress);
+
+ // FIXME: This is public because this asynchronous callback from the FrameLoaderClient
+ // uses the policy machinery (and therefore is called via the PolicyChecker). Once we
+ // introduce a proper callback type for this function, we should make it private again.
+ void continueLoadAfterWillSubmitForm();
+
private:
PassRefPtr<HistoryItem> createHistoryItem(bool useOriginal);
PassRefPtr<HistoryItem> createHistoryItemTree(Frame* targetFrame, bool clipAtTarget);
@@ -405,17 +366,10 @@ namespace WebCore {
void updateHistoryForClientRedirect();
void updateHistoryForCommit();
void updateHistoryForAnchorScroll();
-
- void redirectionTimerFired(Timer<FrameLoader>*);
- void checkCompletedTimerFired(Timer<FrameLoader>*);
- void checkLoadCompleteTimerFired(Timer<FrameLoader>*);
-
- void cancelRedirection(bool newLoadInProgress = false);
- void started();
+ void checkTimerFired(Timer<FrameLoader>*);
- void completed();
- void parentCompleted();
+ void started();
bool shouldUsePlugin(const KURL&, const String& mimeType, bool hasFallback, bool& useFallback);
bool loadPlugin(RenderPart*, const KURL&, const String& mimeType,
@@ -423,6 +377,7 @@ namespace WebCore {
bool loadProvisionalItemFromCachedPage();
void cachePageForHistoryItem(HistoryItem*);
+ void pageHidden();
void receivedFirstData();
@@ -443,25 +398,17 @@ namespace WebCore {
void setLoadType(FrameLoadType);
- void checkNavigationPolicy(const ResourceRequest&, DocumentLoader*, PassRefPtr<FormState>, NavigationPolicyDecisionFunction, void* argument);
- void checkNewWindowPolicy(const NavigationAction&, const ResourceRequest&, PassRefPtr<FormState>, const String& frameName);
-
- void continueAfterNavigationPolicy(PolicyAction);
- void continueAfterNewWindowPolicy(PolicyAction);
- void continueAfterContentPolicy(PolicyAction);
- void continueLoadAfterWillSubmitForm(PolicyAction = PolicyUse);
-
static void callContinueLoadAfterNavigationPolicy(void*, const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue);
- void continueLoadAfterNavigationPolicy(const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue);
static void callContinueLoadAfterNewWindowPolicy(void*, const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, bool shouldContinue);
- void continueLoadAfterNewWindowPolicy(const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, bool shouldContinue);
static void callContinueFragmentScrollAfterNavigationPolicy(void*, const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue);
+
+ void continueLoadAfterNavigationPolicy(const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue);
+ void continueLoadAfterNewWindowPolicy(const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, bool shouldContinue);
void continueFragmentScrollAfterNavigationPolicy(const ResourceRequest&, bool shouldContinue);
+
bool shouldScrollToAnchor(bool isFormSubmission, FrameLoadType, const KURL&);
void addHistoryItemForFragmentScroll();
- void stopPolicyCheck();
-
void checkLoadCompleteForThisFrame();
void setDocumentLoader(DocumentLoader*);
@@ -472,18 +419,12 @@ namespace WebCore {
void closeOldDataSources();
void open(CachedPage&);
- void open(CachedFrame&);
void updateHistoryAfterClientRedirect();
- void clear(bool clearWindowProperties = true, bool clearScriptObjects = true);
+ void clear(bool clearWindowProperties = true, bool clearScriptObjects = true, bool clearFrameView = true);
bool shouldReloadToHandleUnreachableURL(DocumentLoader*);
- void handleUnimplementablePolicy(const ResourceError&);
-
- void scheduleRedirection(ScheduledRedirection*);
- void startRedirectionTimer();
- void stopRedirectionTimer();
void dispatchDidCommitLoad();
void dispatchAssignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader*, const ResourceRequest&);
@@ -492,9 +433,6 @@ namespace WebCore {
void dispatchDidReceiveContentLength(DocumentLoader*, unsigned long identifier, int length);
void dispatchDidFinishLoading(DocumentLoader*, unsigned long identifier);
- static bool isLocationChange(const ScheduledRedirection&);
- void scheduleFormSubmission(const FrameLoadRequest&, bool lockHistory, PassRefPtr<Event>, PassRefPtr<FormState>);
-
void loadWithDocumentLoader(DocumentLoader*, FrameLoadType, PassRefPtr<FormState>); // Calls continueLoadAfterNavigationPolicy
void load(DocumentLoader*); // Calls loadWithDocumentLoader
@@ -513,8 +451,6 @@ namespace WebCore {
bool lockHistory, FrameLoadType, PassRefPtr<Event>, PassRefPtr<FormState>);
#endif
- void clientRedirectCancelledOrFinished(bool cancelWithLoadInProgress);
- void clientRedirected(const KURL&, double delay, double fireDate, bool lockBackForwardList);
bool shouldReload(const KURL& currentURL, const KURL& destinationURL);
void sendRemainingDelegateMessages(unsigned long identifier, const ResourceResponse&, int length, const ResourceError&);
@@ -541,6 +477,7 @@ namespace WebCore {
void scheduleCheckCompleted();
void scheduleCheckLoadComplete();
+ void startCheckCompleteTimer();
KURL originalRequestURL() const;
@@ -551,6 +488,8 @@ namespace WebCore {
Frame* m_frame;
FrameLoaderClient* m_client;
+ PolicyChecker m_policyChecker;
+
FrameState m_state;
FrameLoadType m_loadType;
@@ -562,15 +501,7 @@ namespace WebCore {
RefPtr<DocumentLoader> m_provisionalDocumentLoader;
RefPtr<DocumentLoader> m_policyDocumentLoader;
- // This identifies the type of navigation action which prompted this load. Note
- // that WebKit conveys this value as the WebActionNavigationTypeKey value
- // on navigation action delegate callbacks.
- FrameLoadType m_policyLoadType;
- PolicyCheck m_policyCheck;
-
bool m_delegateIsHandlingProvisionalLoadError;
- bool m_delegateIsDecidingNavigationPolicy;
- bool m_delegateIsHandlingUnimplementablePolicy;
bool m_firstLayoutDone;
bool m_quickRedirectComing;
@@ -598,8 +529,6 @@ namespace WebCore {
bool m_cancellingWithLoadInProgress;
- OwnPtr<ScheduledRedirection> m_scheduledRedirection;
-
bool m_needsClear;
bool m_receivedData;
@@ -610,16 +539,14 @@ namespace WebCore {
bool m_containsPlugIns;
KURL m_submittedFormURL;
-
- Timer<FrameLoader> m_redirectionTimer;
- Timer<FrameLoader> m_checkCompletedTimer;
- Timer<FrameLoader> m_checkLoadCompleteTimer;
+
+ Timer<FrameLoader> m_checkTimer;
+ bool m_shouldCallCheckCompleted;
+ bool m_shouldCallCheckLoadComplete;
Frame* m_opener;
HashSet<Frame*> m_openedFrames;
- bool m_openedByDOM;
-
bool m_creatingInitialEmptyDocument;
bool m_isDisplayingInitialEmptyDocument;
bool m_committedFirstRealDocumentLoad;
@@ -629,6 +556,7 @@ namespace WebCore {
RefPtr<HistoryItem> m_provisionalHistoryItem;
bool m_didPerformFirstNavigation;
+ bool m_loadingFromCachedPage;
#ifndef NDEBUG
bool m_didDispatchDidCommitLoad;
diff --git a/WebCore/loader/FrameLoaderClient.h b/WebCore/loader/FrameLoaderClient.h
index bca0d0b..7973ca5 100644
--- a/WebCore/loader/FrameLoaderClient.h
+++ b/WebCore/loader/FrameLoaderClient.h
@@ -60,22 +60,28 @@ namespace WebCore {
class KURL;
class NavigationAction;
class PluginView;
+ class PolicyChecker;
class ResourceError;
class ResourceHandle;
class ResourceLoader;
struct ResourceRequest;
class ResourceResponse;
class ScriptString;
+ class SecurityOrigin;
class SharedBuffer;
class SubstituteData;
class String;
class Widget;
+<<<<<<< HEAD:WebCore/loader/FrameLoaderClient.h
#ifdef ANDROID_HISTORY_CLIENT
class BackForwardList;
#endif
typedef void (FrameLoader::*FramePolicyFunction)(PolicyAction);
+=======
+ typedef void (PolicyChecker::*FramePolicyFunction)(PolicyAction);
+>>>>>>> webkit.org at 49305:WebCore/loader/FrameLoaderClient.h
class FrameLoaderClient {
public:
@@ -173,6 +179,15 @@ namespace WebCore {
virtual void dispatchDidChangeHistoryIndex(BackForwardList*) const = 0;
#endif
+ // This frame has displayed inactive content (such as an image) from an
+ // insecure source. Inactive content cannot spread to other frames.
+ virtual void didDisplayInsecureContent() = 0;
+
+ // The indicated security origin has run active content (such as a
+ // script) from an insecure source. Note that the insecure content can
+ // spread to other frames in the same origin.
+ virtual void didRunInsecureContent(SecurityOrigin*) = 0;
+
virtual ResourceError cancelledError(const ResourceRequest&) = 0;
virtual ResourceError blockedError(const ResourceRequest&) = 0;
virtual ResourceError cannotShowURLError(const ResourceRequest&) = 0;
@@ -246,6 +261,7 @@ namespace WebCore {
#endif
virtual bool shouldUsePluginDocument(const String& /*mimeType*/) const { return false; }
+ virtual bool shouldLoadMediaElementURL(const KURL&) const { return true; }
};
} // namespace WebCore
diff --git a/WebCore/loader/FrameLoaderTypes.h b/WebCore/loader/FrameLoaderTypes.h
index 940bb7f..76299f5 100644
--- a/WebCore/loader/FrameLoaderTypes.h
+++ b/WebCore/loader/FrameLoaderTypes.h
@@ -81,6 +81,12 @@ namespace WebCore {
ObjectContentNetscapePlugin,
ObjectContentOtherPlugin
};
+
+ enum UnloadEventPolicy {
+ UnloadEventPolicyNone,
+ UnloadEventPolicyUnloadOnly,
+ UnloadEventPolicyUnloadAndPageHide
+ };
}
#endif
diff --git a/WebCore/loader/ImageDocument.cpp b/WebCore/loader/ImageDocument.cpp
index 08f2e9a..9b5598d 100644
--- a/WebCore/loader/ImageDocument.cpp
+++ b/WebCore/loader/ImageDocument.cpp
@@ -54,10 +54,24 @@ using namespace HTMLNames;
class ImageEventListener : public EventListener {
public:
static PassRefPtr<ImageEventListener> create(ImageDocument* document) { return adoptRef(new ImageEventListener(document)); }
- virtual void handleEvent(Event*, bool isWindowEvent);
+ static const ImageEventListener* cast(const EventListener* listener)
+ {
+ return listener->type() == ImageEventListenerType
+ ? static_cast<const ImageEventListener*>(listener)
+ : 0;
+ }
+
+ virtual bool operator==(const EventListener& other);
private:
- ImageEventListener(ImageDocument* document) : m_doc(document) { }
+ ImageEventListener(ImageDocument* document)
+ : EventListener(ImageEventListenerType)
+ , m_doc(document)
+ {
+ }
+
+ virtual void handleEvent(ScriptExecutionContext*, Event*);
+
ImageDocument* m_doc;
};
@@ -344,7 +358,7 @@ bool ImageDocument::shouldShrinkToFit() const
// --------
-void ImageEventListener::handleEvent(Event* event, bool)
+void ImageEventListener::handleEvent(ScriptExecutionContext*, Event* event)
{
if (event->type() == eventNames().resizeEvent)
m_doc->windowSizeChanged();
@@ -354,6 +368,13 @@ void ImageEventListener::handleEvent(Event* event, bool)
}
}
+bool ImageEventListener::operator==(const EventListener& listener)
+{
+ if (const ImageEventListener* imageEventListener = ImageEventListener::cast(&listener))
+ return m_doc == imageEventListener->m_doc;
+ return false;
+}
+
// --------
ImageDocumentElement::~ImageDocumentElement()
diff --git a/WebCore/loader/ImageDocument.h b/WebCore/loader/ImageDocument.h
index 1bc5245..080b250 100644
--- a/WebCore/loader/ImageDocument.h
+++ b/WebCore/loader/ImageDocument.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2007, 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
@@ -35,7 +35,7 @@ class ImageDocument : public HTMLDocument {
public:
static PassRefPtr<ImageDocument> create(Frame* frame)
{
- return new ImageDocument(frame);
+ return adoptRef(new ImageDocument(frame));
}
CachedImage* cachedImage();
diff --git a/WebCore/loader/MainResourceLoader.cpp b/WebCore/loader/MainResourceLoader.cpp
index 6c843e9..e7bdbcb 100644
--- a/WebCore/loader/MainResourceLoader.cpp
+++ b/WebCore/loader/MainResourceLoader.cpp
@@ -93,7 +93,7 @@ void MainResourceLoader::didCancel(const ResourceError& error)
RefPtr<MainResourceLoader> protect(this);
if (m_waitingForContentPolicy) {
- frameLoader()->cancelContentPolicyCheck();
+ frameLoader()->policyChecker()->cancelCheck();
ASSERT(m_waitingForContentPolicy);
m_waitingForContentPolicy = false;
deref(); // balances ref in didReceiveResponse
@@ -172,13 +172,17 @@ void MainResourceLoader::willSendRequest(ResourceRequest& newRequest, const Reso
// Don't set this on the first request. It is set when the main load was started.
m_documentLoader->setRequest(newRequest);
+ Frame* top = m_frame->tree()->top();
+ if (top != m_frame)
+ frameLoader()->checkIfDisplayInsecureContent(top->document()->securityOrigin(), newRequest.url());
+
// FIXME: Ideally we'd stop the I/O until we hear back from the navigation policy delegate
// listener. But there's no way to do that in practice. So instead we cancel later if the
// listener tells us to. In practice that means the navigation policy needs to be decided
// synchronously for these redirect cases.
if (!redirectResponse.isNull()) {
ref(); // balanced by deref in continueAfterNavigationPolicy
- frameLoader()->checkNavigationPolicy(newRequest, callContinueAfterNavigationPolicy, this);
+ frameLoader()->policyChecker()->checkNavigationPolicy(newRequest, callContinueAfterNavigationPolicy, this);
}
}
@@ -201,7 +205,7 @@ void MainResourceLoader::continueAfterContentPolicy(PolicyAction contentPolicy,
// Prevent remote web archives from loading because they can claim to be from any domain and thus avoid cross-domain security checks (4120255).
bool isRemoteWebArchive = equalIgnoringCase("application/x-webarchive", mimeType) && !m_substituteData.isValid() && !url.isLocalFile();
if (!frameLoader()->canShowMIMEType(mimeType) || isRemoteWebArchive) {
- frameLoader()->cannotShowMIMEType(r);
+ frameLoader()->policyChecker()->cannotShowMIMEType(r);
// Check reachedTerminalState since the load may have already been cancelled inside of _handleUnimplementablePolicyWithErrorCode::.
if (!reachedTerminalState())
stopLoadingForPolicyChange();
@@ -316,7 +320,25 @@ void MainResourceLoader::didReceiveResponse(const ResourceResponse& r)
ASSERT(!m_waitingForContentPolicy);
m_waitingForContentPolicy = true;
ref(); // balanced by deref in continueAfterContentPolicy and didCancel
- frameLoader()->checkContentPolicy(m_response.mimeType(), callContinueAfterContentPolicy, this);
+
+ ASSERT(frameLoader()->activeDocumentLoader());
+
+ // Always show content with valid substitute data.
+ if (frameLoader()->activeDocumentLoader()->substituteData().isValid()) {
+ callContinueAfterContentPolicy(this, PolicyUse);
+ return;
+ }
+
+#if ENABLE(FTPDIR)
+ // Respect the hidden FTP Directory Listing pref so it can be tested even if the policy delegate might otherwise disallow it
+ Settings* settings = m_frame->settings();
+ if (settings && settings->forceFTPDirectoryListings() && m_response.mimeType() == "application/x-ftp-directory") {
+ callContinueAfterContentPolicy(this, PolicyUse);
+ return;
+ }
+#endif
+
+ frameLoader()->policyChecker()->checkContentPolicy(m_response.mimeType(), callContinueAfterContentPolicy, this);
}
void MainResourceLoader::didReceiveData(const char* data, int length, long long lengthReceived, bool allAtOnce)
diff --git a/WebCore/loader/MediaDocument.cpp b/WebCore/loader/MediaDocument.cpp
index 0b1fd59..656d0a0 100644
--- a/WebCore/loader/MediaDocument.cpp
+++ b/WebCore/loader/MediaDocument.cpp
@@ -226,8 +226,8 @@ void MediaDocument::replaceMediaElementTimerFired(Timer<MediaDocument>*)
embedElement->setAttribute(widthAttr, "100%");
embedElement->setAttribute(heightAttr, "100%");
embedElement->setAttribute(nameAttr, "plugin");
- embedElement->setSrc(url().string());
- embedElement->setType(frame()->loader()->responseMIMEType());
+ embedElement->setAttribute(srcAttr, url().string());
+ embedElement->setAttribute(typeAttr, frame()->loader()->responseMIMEType());
ExceptionCode ec;
videoElement->parent()->replaceChild(embedElement, videoElement, ec);
diff --git a/WebCore/loader/MediaDocument.h b/WebCore/loader/MediaDocument.h
index ac286f0..aa751ab 100644
--- a/WebCore/loader/MediaDocument.h
+++ b/WebCore/loader/MediaDocument.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * 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
@@ -36,22 +36,23 @@ class MediaDocument : public HTMLDocument {
public:
static PassRefPtr<MediaDocument> create(Frame* frame)
{
- return new MediaDocument(frame);
+ return adoptRef(new MediaDocument(frame));
}
-
- virtual void defaultEventHandler(Event*);
+ virtual ~MediaDocument();
void mediaElementSawUnsupportedTracks();
private:
MediaDocument(Frame*);
- virtual ~MediaDocument();
- Timer<MediaDocument> m_replaceMediaElementTimer;
virtual bool isMediaDocument() const { return true; }
virtual Tokenizer* createTokenizer();
+ virtual void defaultEventHandler(Event*);
+
void replaceMediaElementTimerFired(Timer<MediaDocument>*);
+
+ Timer<MediaDocument> m_replaceMediaElementTimer;
};
}
diff --git a/WebCore/loader/PlaceholderDocument.cpp b/WebCore/loader/PlaceholderDocument.cpp
index e071aa8..af14c72 100644
--- a/WebCore/loader/PlaceholderDocument.cpp
+++ b/WebCore/loader/PlaceholderDocument.cpp
@@ -37,7 +37,7 @@ void PlaceholderDocument::attach()
if (!styleSelector()) {
RefPtr<StyleSheetList> styleSheetList = StyleSheetList::create(this);
- setStyleSelector(new CSSStyleSelector(this, userStyleSheet(), styleSheetList.get(), 0, true, false));
+ setStyleSelector(new CSSStyleSelector(this, styleSheetList.get(), 0, pageUserSheet(), pageGroupUserSheets(), true, false));
}
// Skipping Document::attach().
diff --git a/WebCore/loader/PlaceholderDocument.h b/WebCore/loader/PlaceholderDocument.h
index c542370..a759266 100644
--- a/WebCore/loader/PlaceholderDocument.h
+++ b/WebCore/loader/PlaceholderDocument.h
@@ -34,7 +34,7 @@ class PlaceholderDocument : public Document {
public:
static PassRefPtr<PlaceholderDocument> create(Frame* frame)
{
- return new PlaceholderDocument(frame);
+ return adoptRef(new PlaceholderDocument(frame));
}
virtual void attach();
diff --git a/WebCore/loader/PluginDocument.cpp b/WebCore/loader/PluginDocument.cpp
index 3500c98..788691f 100644
--- a/WebCore/loader/PluginDocument.cpp
+++ b/WebCore/loader/PluginDocument.cpp
@@ -88,8 +88,8 @@ void PluginTokenizer::createDocumentStructure()
m_embedElement->setAttribute(heightAttr, "100%");
m_embedElement->setAttribute(nameAttr, "plugin");
- m_embedElement->setSrc(m_doc->url().string());
- m_embedElement->setType(m_doc->frame()->loader()->responseMIMEType());
+ m_embedElement->setAttribute(srcAttr, m_doc->url().string());
+ m_embedElement->setAttribute(typeAttr, m_doc->frame()->loader()->responseMIMEType());
body->appendChild(embedElement, ec);
}
diff --git a/WebCore/loader/PluginDocument.h b/WebCore/loader/PluginDocument.h
index 35e4038..1d5c964 100644
--- a/WebCore/loader/PluginDocument.h
+++ b/WebCore/loader/PluginDocument.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 2008, 2009Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -33,7 +33,7 @@ class PluginDocument : public HTMLDocument {
public:
static PassRefPtr<PluginDocument> create(Frame* frame)
{
- return new PluginDocument(frame);
+ return adoptRef(new PluginDocument(frame));
}
private:
diff --git a/WebCore/loader/PolicyCallback.cpp b/WebCore/loader/PolicyCallback.cpp
new file mode 100644
index 0000000..14799cf
--- /dev/null
+++ b/WebCore/loader/PolicyCallback.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * 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
+ * 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 "PolicyCallback.h"
+
+#include "FormState.h"
+#include "Frame.h"
+#include "FrameLoader.h"
+#include "HTMLFormElement.h"
+
+namespace WebCore {
+
+PolicyCallback::PolicyCallback()
+ : m_navigationFunction(0)
+ , m_newWindowFunction(0)
+ , m_contentFunction(0)
+{
+}
+
+PolicyCallback::~PolicyCallback()
+{
+}
+
+void PolicyCallback::clear()
+{
+ clearRequest();
+ m_navigationFunction = 0;
+ m_newWindowFunction = 0;
+ m_contentFunction = 0;
+}
+
+void PolicyCallback::set(const ResourceRequest& request, PassRefPtr<FormState> formState,
+ NavigationPolicyDecisionFunction function, void* argument)
+{
+ m_request = request;
+ m_formState = formState;
+ m_frameName = String();
+
+ m_navigationFunction = function;
+ m_newWindowFunction = 0;
+ m_contentFunction = 0;
+ m_argument = argument;
+}
+
+void PolicyCallback::set(const ResourceRequest& request, PassRefPtr<FormState> formState,
+ const String& frameName, NewWindowPolicyDecisionFunction function, void* argument)
+{
+ m_request = request;
+ m_formState = formState;
+ m_frameName = frameName;
+
+ m_navigationFunction = 0;
+ m_newWindowFunction = function;
+ m_contentFunction = 0;
+ m_argument = argument;
+}
+
+void PolicyCallback::set(ContentPolicyDecisionFunction function, void* argument)
+{
+ m_request = ResourceRequest();
+ m_formState = 0;
+ m_frameName = String();
+
+ m_navigationFunction = 0;
+ m_newWindowFunction = 0;
+ m_contentFunction = function;
+ m_argument = argument;
+}
+
+void PolicyCallback::call(bool shouldContinue)
+{
+ if (m_navigationFunction)
+ m_navigationFunction(m_argument, m_request, m_formState.get(), shouldContinue);
+ if (m_newWindowFunction)
+ m_newWindowFunction(m_argument, m_request, m_formState.get(), m_frameName, shouldContinue);
+ ASSERT(!m_contentFunction);
+}
+
+void PolicyCallback::call(PolicyAction action)
+{
+ ASSERT(!m_navigationFunction);
+ ASSERT(!m_newWindowFunction);
+ ASSERT(m_contentFunction);
+ m_contentFunction(m_argument, action);
+}
+
+void PolicyCallback::clearRequest()
+{
+ m_request = ResourceRequest();
+ m_formState = 0;
+ m_frameName = String();
+}
+
+void PolicyCallback::cancel()
+{
+ clearRequest();
+ if (m_navigationFunction)
+ m_navigationFunction(m_argument, m_request, m_formState.get(), false);
+ if (m_newWindowFunction)
+ m_newWindowFunction(m_argument, m_request, m_formState.get(), m_frameName, false);
+ if (m_contentFunction)
+ m_contentFunction(m_argument, PolicyIgnore);
+}
+
+} // namespace WebCore
diff --git a/WebCore/loader/PolicyCallback.h b/WebCore/loader/PolicyCallback.h
new file mode 100644
index 0000000..2aa7c7c
--- /dev/null
+++ b/WebCore/loader/PolicyCallback.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * 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
+ * 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 PolicyCallback_h
+#define PolicyCallback_h
+
+#include "FrameLoaderTypes.h"
+#include "PlatformString.h"
+#include "ResourceRequest.h"
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+ class FormState;
+
+ typedef void (*NavigationPolicyDecisionFunction)(void* argument,
+ const ResourceRequest&, PassRefPtr<FormState>, bool shouldContinue);
+ typedef void (*NewWindowPolicyDecisionFunction)(void* argument,
+ const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, bool shouldContinue);
+ typedef void (*ContentPolicyDecisionFunction)(void* argument, PolicyAction);
+
+ class PolicyCallback {
+ public:
+ PolicyCallback();
+ ~PolicyCallback();
+
+ void clear();
+ void set(const ResourceRequest&, PassRefPtr<FormState>,
+ NavigationPolicyDecisionFunction, void* argument);
+ void set(const ResourceRequest&, PassRefPtr<FormState>, const String& frameName,
+ NewWindowPolicyDecisionFunction, void* argument);
+ void set(ContentPolicyDecisionFunction, void* argument);
+
+ const ResourceRequest& request() const { return m_request; }
+ void clearRequest();
+
+ void call(bool shouldContinue);
+ void call(PolicyAction);
+ void cancel();
+
+ private:
+ ResourceRequest m_request;
+ RefPtr<FormState> m_formState;
+ String m_frameName;
+
+ NavigationPolicyDecisionFunction m_navigationFunction;
+ NewWindowPolicyDecisionFunction m_newWindowFunction;
+ ContentPolicyDecisionFunction m_contentFunction;
+ void* m_argument;
+ };
+
+} // namespace WebCore
+
+#endif // PolicyCallback_h
diff --git a/WebCore/loader/PolicyChecker.cpp b/WebCore/loader/PolicyChecker.cpp
new file mode 100644
index 0000000..196ab4f
--- /dev/null
+++ b/WebCore/loader/PolicyChecker.cpp
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * 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
+ * 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 "PolicyChecker.h"
+
+#include "DocumentLoader.h"
+#include "FormState.h"
+#include "Frame.h"
+#include "FrameLoader.h"
+#include "FrameLoaderClient.h"
+#include "HTMLFormElement.h"
+
+namespace WebCore {
+
+PolicyChecker::PolicyChecker(Frame* frame)
+ : m_frame(frame)
+ , m_delegateIsDecidingNavigationPolicy(false)
+ , m_delegateIsHandlingUnimplementablePolicy(false)
+ , m_loadType(FrameLoadTypeStandard)
+{
+}
+
+void PolicyChecker::checkNavigationPolicy(const ResourceRequest& newRequest, NavigationPolicyDecisionFunction function, void* argument)
+{
+ checkNavigationPolicy(newRequest, m_frame->loader()->activeDocumentLoader(), 0, function, argument);
+}
+
+void PolicyChecker::checkNavigationPolicy(const ResourceRequest& request, DocumentLoader* loader,
+ PassRefPtr<FormState> formState, NavigationPolicyDecisionFunction function, void* argument)
+{
+ NavigationAction action = loader->triggeringAction();
+ if (action.isEmpty()) {
+ action = NavigationAction(request.url(), NavigationTypeOther);
+ loader->setTriggeringAction(action);
+ }
+
+ // Don't ask more than once for the same request or if we are loading an empty URL.
+ // This avoids confusion on the part of the client.
+ if (equalIgnoringHeaderFields(request, loader->lastCheckedRequest()) || (!request.isNull() && request.url().isEmpty())) {
+ function(argument, request, 0, true);
+ loader->setLastCheckedRequest(request);
+ return;
+ }
+
+ // We are always willing to show alternate content for unreachable URLs;
+ // treat it like a reload so it maintains the right state for b/f list.
+ if (loader->substituteData().isValid() && !loader->substituteData().failingURL().isEmpty()) {
+ if (isBackForwardLoadType(m_loadType))
+ m_loadType = FrameLoadTypeReload;
+ function(argument, request, 0, true);
+ return;
+ }
+
+ loader->setLastCheckedRequest(request);
+
+ m_callback.set(request, formState.get(), function, argument);
+
+ m_delegateIsDecidingNavigationPolicy = true;
+ m_frame->loader()->client()->dispatchDecidePolicyForNavigationAction(&PolicyChecker::continueAfterNavigationPolicy,
+ action, request, formState);
+ m_delegateIsDecidingNavigationPolicy = false;
+}
+
+void PolicyChecker::checkNewWindowPolicy(const NavigationAction& action, NewWindowPolicyDecisionFunction function,
+ const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName, void* argument)
+{
+ m_callback.set(request, formState, frameName, function, argument);
+ m_frame->loader()->client()->dispatchDecidePolicyForNewWindowAction(&PolicyChecker::continueAfterNewWindowPolicy,
+ action, request, formState, frameName);
+}
+
+void PolicyChecker::checkContentPolicy(const String& MIMEType, ContentPolicyDecisionFunction function, void* argument)
+{
+ m_callback.set(function, argument);
+ m_frame->loader()->client()->dispatchDecidePolicyForMIMEType(&PolicyChecker::continueAfterContentPolicy,
+ MIMEType, m_frame->loader()->activeDocumentLoader()->request());
+}
+
+void PolicyChecker::cancelCheck()
+{
+ m_frame->loader()->client()->cancelPolicyCheck();
+ m_callback.clear();
+}
+
+void PolicyChecker::stopCheck()
+{
+ m_frame->loader()->client()->cancelPolicyCheck();
+ PolicyCallback callback = m_callback;
+ m_callback.clear();
+ callback.cancel();
+}
+
+void PolicyChecker::cannotShowMIMEType(const ResourceResponse& response)
+{
+ handleUnimplementablePolicy(m_frame->loader()->client()->cannotShowMIMETypeError(response));
+}
+
+void PolicyChecker::continueLoadAfterWillSubmitForm(PolicyAction)
+{
+ // See header file for an explaination of why this function
+ // isn't like the others.
+ m_frame->loader()->continueLoadAfterWillSubmitForm();
+}
+
+void PolicyChecker::continueAfterNavigationPolicy(PolicyAction policy)
+{
+ PolicyCallback callback = m_callback;
+ m_callback.clear();
+
+ bool shouldContinue = policy == PolicyUse;
+
+ switch (policy) {
+ case PolicyIgnore:
+ callback.clearRequest();
+ break;
+ case PolicyDownload:
+ m_frame->loader()->client()->startDownload(callback.request());
+ callback.clearRequest();
+ break;
+ case PolicyUse: {
+ ResourceRequest request(callback.request());
+
+ if (!m_frame->loader()->client()->canHandleRequest(request)) {
+ handleUnimplementablePolicy(m_frame->loader()->cannotShowURLError(callback.request()));
+ callback.clearRequest();
+ shouldContinue = false;
+ }
+ break;
+ }
+ }
+
+ callback.call(shouldContinue);
+}
+
+void PolicyChecker::continueAfterNewWindowPolicy(PolicyAction policy)
+{
+ PolicyCallback callback = m_callback;
+ m_callback.clear();
+
+ switch (policy) {
+ case PolicyIgnore:
+ callback.clearRequest();
+ break;
+ case PolicyDownload:
+ m_frame->loader()->client()->startDownload(callback.request());
+ callback.clearRequest();
+ break;
+ case PolicyUse:
+ break;
+ }
+
+ callback.call(policy == PolicyUse);
+}
+
+void PolicyChecker::continueAfterContentPolicy(PolicyAction policy)
+{
+ PolicyCallback callback = m_callback;
+ m_callback.clear();
+ callback.call(policy);
+}
+
+void PolicyChecker::handleUnimplementablePolicy(const ResourceError& error)
+{
+ m_delegateIsHandlingUnimplementablePolicy = true;
+ m_frame->loader()->client()->dispatchUnableToImplementPolicy(error);
+ m_delegateIsHandlingUnimplementablePolicy = false;
+}
+
+} // namespace WebCore
diff --git a/WebCore/loader/PolicyChecker.h b/WebCore/loader/PolicyChecker.h
new file mode 100644
index 0000000..c667f5b
--- /dev/null
+++ b/WebCore/loader/PolicyChecker.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * 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
+ * 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 PolicyChecker_h
+#define PolicyChecker_h
+
+#include "FrameLoaderTypes.h"
+#include "PlatformString.h"
+#include "PolicyCallback.h"
+#include "ResourceRequest.h"
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+ class DocumentLoader;
+ class FormState;
+ class Frame;
+ class NavigationAction;
+ class ResourceError;
+ class ResourceResponse;
+
+ class PolicyChecker : public Noncopyable {
+ public:
+ PolicyChecker(Frame*);
+
+ void checkNavigationPolicy(const ResourceRequest&, DocumentLoader*, PassRefPtr<FormState>, NavigationPolicyDecisionFunction, void* argument);
+ void checkNavigationPolicy(const ResourceRequest&, NavigationPolicyDecisionFunction, void* argument);
+ void checkNewWindowPolicy(const NavigationAction&, NewWindowPolicyDecisionFunction, const ResourceRequest&, PassRefPtr<FormState>, const String& frameName, void* argument);
+ void checkContentPolicy(const String& MIMEType, ContentPolicyDecisionFunction, void* argument);
+
+ // FIXME: These are different. They could use better names.
+ void cancelCheck();
+ void stopCheck();
+
+ void cannotShowMIMEType(const ResourceResponse&);
+
+ FrameLoadType loadType() const { return m_loadType; }
+ void setLoadType(FrameLoadType loadType) { m_loadType = loadType; }
+
+ bool delegateIsDecidingNavigationPolicy() const { return m_delegateIsDecidingNavigationPolicy; }
+ bool delegateIsHandlingUnimplementablePolicy() const { return m_delegateIsHandlingUnimplementablePolicy; }
+
+ // FIXME: This function is a cheat. Basically, this is just an asynchronouc callback
+ // from the FrameLoaderClient, but this callback uses the policy types and so has to
+ // live on this object. In the long term, we should create a type for non-policy
+ // callbacks from the FrameLoaderClient and remove this vestige. I just don't have
+ // the heart to hack on all the platforms to make that happen right now.
+ void continueLoadAfterWillSubmitForm(PolicyAction);
+
+ private:
+ void continueAfterNavigationPolicy(PolicyAction);
+ void continueAfterNewWindowPolicy(PolicyAction);
+ void continueAfterContentPolicy(PolicyAction);
+
+ void handleUnimplementablePolicy(const ResourceError&);
+
+ Frame* m_frame;
+
+ bool m_delegateIsDecidingNavigationPolicy;
+ bool m_delegateIsHandlingUnimplementablePolicy;
+
+ // This identifies the type of navigation action which prompted this load. Note
+ // that WebKit conveys this value as the WebActionNavigationTypeKey value
+ // on navigation action delegate callbacks.
+ FrameLoadType m_loadType;
+ PolicyCallback m_callback;
+ };
+
+} // namespace WebCore
+
+#endif // PolicyChecker_h
diff --git a/WebCore/loader/RedirectScheduler.cpp b/WebCore/loader/RedirectScheduler.cpp
new file mode 100644
index 0000000..819cbdd
--- /dev/null
+++ b/WebCore/loader/RedirectScheduler.cpp
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2009 Adam Barth. 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 "RedirectScheduler.h"
+
+#include "DocumentLoader.h"
+#include "Event.h"
+#include "FormState.h"
+#include "Frame.h"
+#include "FrameLoadRequest.h"
+#include "FrameLoader.h"
+#include "HTMLFormElement.h"
+#include <wtf/CurrentTime.h>
+
+namespace WebCore {
+
+struct ScheduledRedirection {
+ enum Type { redirection, locationChange, historyNavigation, formSubmission };
+
+ const Type type;
+ const double delay;
+ const String url;
+ const String referrer;
+ const FrameLoadRequest frameRequest;
+ const RefPtr<Event> event;
+ const RefPtr<FormState> formState;
+ const int historySteps;
+ const bool lockHistory;
+ const bool lockBackForwardList;
+ const bool wasUserGesture;
+ const bool wasRefresh;
+ const bool wasDuringLoad;
+ bool toldClient;
+
+ ScheduledRedirection(double delay, const String& url, bool lockHistory, bool lockBackForwardList, bool wasUserGesture, bool refresh)
+ : type(redirection)
+ , delay(delay)
+ , url(url)
+ , historySteps(0)
+ , lockHistory(lockHistory)
+ , lockBackForwardList(lockBackForwardList)
+ , wasUserGesture(wasUserGesture)
+ , wasRefresh(refresh)
+ , wasDuringLoad(false)
+ , toldClient(false)
+ {
+ ASSERT(!url.isEmpty());
+ }
+
+ ScheduledRedirection(const String& url, const String& referrer, bool lockHistory, bool lockBackForwardList, bool wasUserGesture, bool refresh, bool duringLoad)
+ : type(locationChange)
+ , delay(0)
+ , url(url)
+ , referrer(referrer)
+ , historySteps(0)
+ , lockHistory(lockHistory)
+ , lockBackForwardList(lockBackForwardList)
+ , wasUserGesture(wasUserGesture)
+ , wasRefresh(refresh)
+ , wasDuringLoad(duringLoad)
+ , toldClient(false)
+ {
+ ASSERT(!url.isEmpty());
+ }
+
+ explicit ScheduledRedirection(int historyNavigationSteps)
+ : type(historyNavigation)
+ , delay(0)
+ , historySteps(historyNavigationSteps)
+ , lockHistory(false)
+ , lockBackForwardList(false)
+ , wasUserGesture(false)
+ , wasRefresh(false)
+ , wasDuringLoad(false)
+ , toldClient(false)
+ {
+ }
+
+ ScheduledRedirection(const FrameLoadRequest& frameRequest,
+ bool lockHistory, bool lockBackForwardList, PassRefPtr<Event> event, PassRefPtr<FormState> formState,
+ bool duringLoad)
+ : type(formSubmission)
+ , delay(0)
+ , frameRequest(frameRequest)
+ , event(event)
+ , formState(formState)
+ , historySteps(0)
+ , lockHistory(lockHistory)
+ , lockBackForwardList(lockBackForwardList)
+ , wasUserGesture(false)
+ , wasRefresh(false)
+ , wasDuringLoad(duringLoad)
+ , toldClient(false)
+ {
+ ASSERT(!frameRequest.isEmpty());
+ ASSERT(this->formState);
+ }
+};
+
+RedirectScheduler::RedirectScheduler(Frame* frame)
+ : m_frame(frame)
+ , m_timer(this, &RedirectScheduler::timerFired)
+{
+}
+
+RedirectScheduler::~RedirectScheduler()
+{
+}
+
+bool RedirectScheduler::redirectScheduledDuringLoad()
+{
+ return m_scheduledRedirection && m_scheduledRedirection->wasDuringLoad;
+}
+
+void RedirectScheduler::clear()
+{
+ m_timer.stop();
+ m_scheduledRedirection.clear();
+}
+
+void RedirectScheduler::scheduleRedirect(double delay, const String& url)
+{
+ if (delay < 0 || delay > INT_MAX / 1000)
+ return;
+
+ if (!m_frame->page())
+ return;
+
+ if (url.isEmpty())
+ return;
+
+ // We want a new history item if the refresh timeout is > 1 second.
+ if (!m_scheduledRedirection || delay <= m_scheduledRedirection->delay)
+ schedule(new ScheduledRedirection(delay, url, true, delay <= 1, false, false));
+}
+
+bool RedirectScheduler::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 RedirectScheduler::scheduleLocationChange(const String& url, const String& referrer, bool lockHistory, bool lockBackForwardList, bool wasUserGesture)
+{
+ if (!m_frame->page())
+ return;
+
+ if (url.isEmpty())
+ return;
+
+ lockBackForwardList = lockBackForwardList || mustLockBackForwardList(m_frame);
+
+ FrameLoader* loader = m_frame->loader();
+
+ // 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(ParsedURLString, url);
+ if (parsedURL.hasFragmentIdentifier() && equalIgnoringFragmentIdentifier(loader->url(), parsedURL)) {
+ loader->changeLocation(loader->completeURL(url), referrer, lockHistory, lockBackForwardList, wasUserGesture);
+ return;
+ }
+
+ // Handle a location change of a page with no document as a special case.
+ // This may happen when a frame changes the location of another frame.
+ bool duringLoad = !loader->committedFirstRealDocumentLoad();
+
+ schedule(new ScheduledRedirection(url, referrer, lockHistory, lockBackForwardList, wasUserGesture, false, duringLoad));
+}
+
+void RedirectScheduler::scheduleFormSubmission(const FrameLoadRequest& frameRequest,
+ bool lockHistory, PassRefPtr<Event> event, PassRefPtr<FormState> formState)
+{
+ ASSERT(m_frame->page());
+ ASSERT(!frameRequest.isEmpty());
+
+ // FIXME: Do we need special handling for form submissions where the URL is the same
+ // as the current one except for the fragment part? See scheduleLocationChange above.
+
+ // Handle a location change of a page with no document as a special case.
+ // This may happen when a frame changes the location of another frame.
+ bool duringLoad = !m_frame->loader()->committedFirstRealDocumentLoad();
+
+ schedule(new ScheduledRedirection(frameRequest, lockHistory, mustLockBackForwardList(m_frame), event, formState, duringLoad));
+}
+
+void RedirectScheduler::scheduleRefresh(bool wasUserGesture)
+{
+ if (!m_frame->page())
+ return;
+
+ const KURL& url = m_frame->loader()->url();
+
+ if (url.isEmpty())
+ return;
+
+ schedule(new ScheduledRedirection(url.string(), m_frame->loader()->outgoingReferrer(), true, true, wasUserGesture, true, false));
+}
+
+bool RedirectScheduler::locationChangePending()
+{
+ if (!m_scheduledRedirection)
+ return false;
+
+ switch (m_scheduledRedirection->type) {
+ case ScheduledRedirection::redirection:
+ return false;
+ case ScheduledRedirection::historyNavigation:
+ case ScheduledRedirection::locationChange:
+ case ScheduledRedirection::formSubmission:
+ return true;
+ }
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+void RedirectScheduler::scheduleHistoryNavigation(int steps)
+{
+ if (!m_frame->page())
+ return;
+
+ schedule(new ScheduledRedirection(steps));
+}
+
+void RedirectScheduler::timerFired(Timer<RedirectScheduler>*)
+{
+ ASSERT(m_frame->page());
+
+ if (m_frame->page()->defersLoading())
+ return;
+
+ OwnPtr<ScheduledRedirection> redirection(m_scheduledRedirection.release());
+ FrameLoader* loader = m_frame->loader();
+
+ switch (redirection->type) {
+ case ScheduledRedirection::redirection:
+ case ScheduledRedirection::locationChange:
+ loader->changeLocation(KURL(ParsedURLString, redirection->url), redirection->referrer,
+ redirection->lockHistory, redirection->lockBackForwardList, redirection->wasUserGesture, redirection->wasRefresh);
+ return;
+ case ScheduledRedirection::historyNavigation:
+ if (redirection->historySteps == 0) {
+ // Special case for go(0) from a frame -> reload only the frame
+ loader->urlSelected(loader->url(), "", 0, redirection->lockHistory, redirection->lockBackForwardList, redirection->wasUserGesture);
+ return;
+ }
+ // go(i!=0) from a frame navigates into the history of the frame only,
+ // in both IE and NS (but not in Mozilla). We can't easily do that.
+ if (m_frame->page()->canGoBackOrForward(redirection->historySteps))
+ m_frame->page()->goBackOrForward(redirection->historySteps);
+ return;
+ case ScheduledRedirection::formSubmission:
+ // The submitForm function will find a target frame before using the redirection timer.
+ // Now that the timer has fired, we need to repeat the security check which normally is done when
+ // selecting a target, in case conditions have changed. Other code paths avoid this by targeting
+ // without leaving a time window. If we fail the check just silently drop the form submission.
+ if (!redirection->formState->sourceFrame()->loader()->shouldAllowNavigation(m_frame))
+ return;
+ loader->loadFrameRequest(redirection->frameRequest, redirection->lockHistory, redirection->lockBackForwardList,
+ redirection->event, redirection->formState);
+ return;
+ }
+
+ ASSERT_NOT_REACHED();
+}
+
+void RedirectScheduler::schedule(PassOwnPtr<ScheduledRedirection> redirection)
+{
+ ASSERT(m_frame->page());
+ FrameLoader* loader = m_frame->loader();
+
+ // If a redirect was scheduled during a load, then stop the current load.
+ // Otherwise when the current load transitions from a provisional to a
+ // committed state, pending redirects may be cancelled.
+ if (redirection->wasDuringLoad) {
+ if (DocumentLoader* provisionalDocumentLoader = loader->provisionalDocumentLoader())
+ provisionalDocumentLoader->stopLoading();
+ loader->stopLoading(UnloadEventPolicyUnloadAndPageHide);
+ }
+
+ cancel();
+ m_scheduledRedirection = redirection;
+ if (!loader->isComplete() && m_scheduledRedirection->type != ScheduledRedirection::redirection)
+ loader->completed();
+ startTimer();
+}
+
+void RedirectScheduler::startTimer()
+{
+ if (!m_scheduledRedirection)
+ return;
+
+ ASSERT(m_frame->page());
+
+ FrameLoader* loader = m_frame->loader();
+
+ if (m_timer.isActive())
+ return;
+
+ if (m_scheduledRedirection->type == ScheduledRedirection::redirection && !loader->allAncestorsAreComplete())
+ return;
+
+ m_timer.startOneShot(m_scheduledRedirection->delay);
+
+ switch (m_scheduledRedirection->type) {
+ case ScheduledRedirection::locationChange:
+ case ScheduledRedirection::redirection:
+ if (m_scheduledRedirection->toldClient)
+ return;
+ m_scheduledRedirection->toldClient = true;
+ loader->clientRedirected(KURL(ParsedURLString, m_scheduledRedirection->url),
+ m_scheduledRedirection->delay,
+ currentTime() + m_timer.nextFireInterval(),
+ m_scheduledRedirection->lockBackForwardList);
+ return;
+ case ScheduledRedirection::formSubmission:
+ // FIXME: It would make sense to report form submissions as client redirects too.
+ // But we didn't do that in the past when form submission used a separate delay
+ // mechanism, so doing it will be a behavior change.
+ return;
+ case ScheduledRedirection::historyNavigation:
+ // Don't report history navigations.
+ return;
+ }
+ ASSERT_NOT_REACHED();
+}
+
+void RedirectScheduler::cancel(bool newLoadInProgress)
+{
+ m_timer.stop();
+
+ OwnPtr<ScheduledRedirection> redirection(m_scheduledRedirection.release());
+ if (redirection && redirection->toldClient)
+ m_frame->loader()->clientRedirectCancelledOrFinished(newLoadInProgress);
+}
+
+} // namespace WebCore
+
diff --git a/WebCore/loader/RedirectScheduler.h b/WebCore/loader/RedirectScheduler.h
new file mode 100644
index 0000000..bf076d6
--- /dev/null
+++ b/WebCore/loader/RedirectScheduler.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2009 Adam Barth. 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.
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 RedirectScheduler_h
+#define RedirectScheduler_h
+
+#include "Event.h"
+#include "Timer.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+ class FormState;
+ class Frame;
+ class String;
+
+ struct FrameLoadRequest;
+ struct ScheduledRedirection;
+
+ class RedirectScheduler : public Noncopyable {
+ public:
+ RedirectScheduler(Frame*);
+ ~RedirectScheduler();
+
+ bool redirectScheduledDuringLoad();
+ bool locationChangePending();
+
+ void scheduleRedirect(double delay, const String& url);
+ void scheduleLocationChange(const String& url, const String& referrer, bool lockHistory = true, bool lockBackForwardList = true, bool userGesture = false);
+ void scheduleFormSubmission(const FrameLoadRequest&, bool lockHistory, PassRefPtr<Event>, PassRefPtr<FormState>);
+ void scheduleRefresh(bool userGesture = false);
+ void scheduleHistoryNavigation(int steps);
+
+ void startTimer();
+
+ void cancel(bool newLoadInProgress = false);
+ void clear();
+
+ private:
+ void timerFired(Timer<RedirectScheduler>*);
+ void schedule(PassOwnPtr<ScheduledRedirection>);
+
+ static bool mustLockBackForwardList(Frame* targetFrame);
+
+ Frame* m_frame;
+ Timer<RedirectScheduler> m_timer;
+ OwnPtr<ScheduledRedirection> m_scheduledRedirection;
+ };
+
+} // namespace WebCore
+
+#endif // FrameLoader_h
diff --git a/WebCore/loader/ResourceLoader.cpp b/WebCore/loader/ResourceLoader.cpp
index 5ad181b..2dac844 100644
--- a/WebCore/loader/ResourceLoader.cpp
+++ b/WebCore/loader/ResourceLoader.cpp
@@ -94,8 +94,9 @@ void ResourceLoader::releaseResources()
if (m_handle) {
// Clear out the ResourceHandle's client so that it doesn't try to call
- // us back after we release it.
- m_handle->setClient(0);
+ // us back after we release it, unless it has been replaced by someone else.
+ if (m_handle->client() == this)
+ m_handle->setClient(0);
m_handle = 0;
}
diff --git a/WebCore/loader/SubresourceLoader.cpp b/WebCore/loader/SubresourceLoader.cpp
index 047cc6d..2ee4626 100644
--- a/WebCore/loader/SubresourceLoader.cpp
+++ b/WebCore/loader/SubresourceLoader.cpp
@@ -33,6 +33,7 @@
#include "Frame.h"
#include "FrameLoader.h"
#include "ResourceHandle.h"
+#include "SecurityOrigin.h"
#include "SubresourceLoaderClient.h"
#include <wtf/RefCountedLeakCounter.h>
@@ -72,13 +73,13 @@ PassRefPtr<SubresourceLoader> SubresourceLoader::create(Frame* frame, Subresourc
ResourceRequest newRequest = request;
if (!skipCanLoadCheck
- && FrameLoader::restrictAccessToLocal()
- && !FrameLoader::canLoad(request.url(), String(), frame->document())) {
+ && SecurityOrigin::restrictAccessToLocal()
+ && !SecurityOrigin::canLoad(request.url(), String(), frame->document())) {
FrameLoader::reportLocalLoadFailed(frame, request.url().string());
return 0;
}
- if (FrameLoader::shouldHideReferrer(request.url(), fl->outgoingReferrer()))
+ if (SecurityOrigin::shouldHideReferrer(request.url(), fl->outgoingReferrer()))
newRequest.clearHTTPReferrer();
else if (!request.httpReferrer())
newRequest.setHTTPReferrer(fl->outgoingReferrer());
diff --git a/WebCore/loader/TextDocument.h b/WebCore/loader/TextDocument.h
index c67fea5..53e3074 100644
--- a/WebCore/loader/TextDocument.h
+++ b/WebCore/loader/TextDocument.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006, 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
@@ -35,7 +35,7 @@ class TextDocument : public HTMLDocument {
public:
static PassRefPtr<TextDocument> create(Frame* frame)
{
- return new TextDocument(frame);
+ return adoptRef(new TextDocument(frame));
}
private:
diff --git a/WebCore/loader/TextResourceDecoder.cpp b/WebCore/loader/TextResourceDecoder.cpp
index db68441..6ddd604 100644
--- a/WebCore/loader/TextResourceDecoder.cpp
+++ b/WebCore/loader/TextResourceDecoder.cpp
@@ -798,23 +798,15 @@ String TextResourceDecoder::decode(const char* data, size_t len)
if (!checkForHeadCharset(data, len, movedDataToBuffer))
return "";
- // FIXME: It seems wrong to change our encoding downstream after
- // we have already done some decoding. However, it's not possible
- // to avoid in a sense in two cases below because triggering conditions
- // for both cases depend on the information that won't be available
- // until we do partial read.
- // The first case had better be removed altogether (see bug 21990)
- // or at least be made to be invoked only when the encoding detection
- // is turned on.
- // Do the auto-detect 1) using Japanese detector if our default encoding is
- // one of the Japanese detector or 2) using detectTextEncoding if encoding
- // detection is turned on.
- if (m_source != UserChosenEncoding && m_source != AutoDetectedEncoding && m_encoding.isJapanese())
- detectJapaneseEncoding(data, len);
- else if (shouldAutoDetect()) {
- TextEncoding detectedEncoding;
- if (detectTextEncoding(data, len, m_hintEncoding, &detectedEncoding))
- setEncoding(detectedEncoding, AutoDetectedEncoding);
+ // FIXME: It is wrong to change the encoding downstream after we have already done some decoding.
+ if (shouldAutoDetect()) {
+ if (m_encoding.isJapanese())
+ detectJapaneseEncoding(data, len); // FIXME: We should use detectTextEncoding() for all languages.
+ else {
+ TextEncoding detectedEncoding;
+ if (detectTextEncoding(data, len, m_hintEncoding, &detectedEncoding))
+ setEncoding(detectedEncoding, AutoDetectedEncoding);
+ }
}
ASSERT(m_encoding.isValid());
diff --git a/WebCore/loader/ThreadableLoader.cpp b/WebCore/loader/ThreadableLoader.cpp
index b174af7..720ba4e 100644
--- a/WebCore/loader/ThreadableLoader.cpp
+++ b/WebCore/loader/ThreadableLoader.cpp
@@ -40,33 +40,33 @@
namespace WebCore {
-PassRefPtr<ThreadableLoader> ThreadableLoader::create(ScriptExecutionContext* context, ThreadableLoaderClient* client, const ResourceRequest& request, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials, CrossOriginRedirectPolicy crossOriginRedirectPolicy)
+PassRefPtr<ThreadableLoader> ThreadableLoader::create(ScriptExecutionContext* context, ThreadableLoaderClient* client, const ResourceRequest& request, const ThreadableLoaderOptions& options)
{
ASSERT(client);
ASSERT(context);
#if ENABLE(WORKERS)
if (context->isWorkerContext())
- return WorkerThreadableLoader::create(static_cast<WorkerContext*>(context), client, WorkerRunLoop::defaultMode(), request, callbacksSetting, contentSniff, storedCredentials, crossOriginRedirectPolicy);
+ return WorkerThreadableLoader::create(static_cast<WorkerContext*>(context), client, WorkerRunLoop::defaultMode(), request, options);
#endif // ENABLE(WORKERS)
ASSERT(context->isDocument());
- return DocumentThreadableLoader::create(static_cast<Document*>(context), client, request, callbacksSetting, contentSniff, storedCredentials, crossOriginRedirectPolicy);
+ return DocumentThreadableLoader::create(static_cast<Document*>(context), client, request, options);
}
-void ThreadableLoader::loadResourceSynchronously(ScriptExecutionContext* context, const ResourceRequest& request, ThreadableLoaderClient& client, StoredCredentials storedCredentials)
+void ThreadableLoader::loadResourceSynchronously(ScriptExecutionContext* context, const ResourceRequest& request, ThreadableLoaderClient& client, const ThreadableLoaderOptions& options)
{
ASSERT(context);
#if ENABLE(WORKERS)
if (context->isWorkerContext()) {
- WorkerThreadableLoader::loadResourceSynchronously(static_cast<WorkerContext*>(context), request, client, storedCredentials, DenyCrossOriginRedirect);
+ WorkerThreadableLoader::loadResourceSynchronously(static_cast<WorkerContext*>(context), request, client, options);
return;
}
#endif // ENABLE(WORKERS)
ASSERT(context->isDocument());
- DocumentThreadableLoader::loadResourceSynchronously(static_cast<Document*>(context), request, client, storedCredentials);
+ DocumentThreadableLoader::loadResourceSynchronously(static_cast<Document*>(context), request, client, options);
}
} // namespace WebCore
diff --git a/WebCore/loader/ThreadableLoader.h b/WebCore/loader/ThreadableLoader.h
index 1ac12cb..a52bfad 100644
--- a/WebCore/loader/ThreadableLoader.h
+++ b/WebCore/loader/ThreadableLoader.h
@@ -43,32 +43,32 @@ namespace WebCore {
class ScriptExecutionContext;
class ThreadableLoaderClient;
- enum LoadCallbacks {
- SendLoadCallbacks,
- DoNotSendLoadCallbacks
- };
-
- enum ContentSniff {
- SniffContent,
- DoNotSniffContent
- };
-
enum StoredCredentials {
AllowStoredCredentials,
DoNotAllowStoredCredentials
};
-
- enum CrossOriginRedirectPolicy {
- DenyCrossOriginRedirect,
- AllowCrossOriginRedirect
+
+ enum CrossOriginRequestPolicy {
+ DenyCrossOriginRequests,
+ UseAccessControl,
+ AllowCrossOriginRequests
+ };
+
+ struct ThreadableLoaderOptions {
+ ThreadableLoaderOptions() : sendLoadCallbacks(false), sniffContent(false), allowCredentials(false), forcePreflight(false), crossOriginRequestPolicy(DenyCrossOriginRequests) { }
+ bool sendLoadCallbacks;
+ bool sniffContent;
+ bool allowCredentials; // Whether HTTP credentials and cookies are sent with the request.
+ bool forcePreflight; // If AccessControl is used, whether to force a preflight.
+ CrossOriginRequestPolicy crossOriginRequestPolicy;
};
// Useful for doing loader operations from any thread (not threadsafe,
// just able to run on threads other than the main thread).
class ThreadableLoader : public Noncopyable {
public:
- static void loadResourceSynchronously(ScriptExecutionContext*, const ResourceRequest&, ThreadableLoaderClient&, StoredCredentials);
- static PassRefPtr<ThreadableLoader> create(ScriptExecutionContext*, ThreadableLoaderClient*, const ResourceRequest&, LoadCallbacks, ContentSniff, StoredCredentials, CrossOriginRedirectPolicy);
+ static void loadResourceSynchronously(ScriptExecutionContext*, const ResourceRequest&, ThreadableLoaderClient&, const ThreadableLoaderOptions&);
+ static PassRefPtr<ThreadableLoader> create(ScriptExecutionContext*, ThreadableLoaderClient*, const ResourceRequest&, const ThreadableLoaderOptions&);
virtual void cancel() = 0;
void ref() { refThreadableLoader(); }
diff --git a/WebCore/loader/UserStyleSheetLoader.cpp b/WebCore/loader/UserStyleSheetLoader.cpp
deleted file mode 100644
index 3afbc15..0000000
--- a/WebCore/loader/UserStyleSheetLoader.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 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.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 "UserStyleSheetLoader.h"
-
-#include "CachedCSSStyleSheet.h"
-#include "DocLoader.h"
-#include "Frame.h"
-
-using namespace WebCore;
-
-UserStyleSheetLoader::UserStyleSheetLoader(PassRefPtr<Document> document, const String& url)
- : m_document(document)
- , m_cachedSheet(m_document->docLoader()->requestUserCSSStyleSheet(url, ""))
-{
- if (m_cachedSheet) {
- m_document->addPendingSheet();
- m_cachedSheet->addClient(this);
- }
-}
-
-UserStyleSheetLoader::~UserStyleSheetLoader()
-{
- if (m_cachedSheet) {
- if (!m_cachedSheet->isLoaded())
- m_document->removePendingSheet();
- m_cachedSheet->removeClient(this);
- }
-}
-
-void UserStyleSheetLoader::setCSSStyleSheet(const String& /*URL*/, const String& /*charset*/, const CachedCSSStyleSheet* sheet)
-{
- m_document->removePendingSheet();
- if (Frame* frame = m_document->frame())
- frame->setUserStyleSheet(sheet->sheetText());
-}
diff --git a/WebCore/loader/UserStyleSheetLoader.h b/WebCore/loader/UserStyleSheetLoader.h
deleted file mode 100644
index 6e7a1ba..0000000
--- a/WebCore/loader/UserStyleSheetLoader.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 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.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 UserStyleSheetLoader_h
-#define UserStyleSheetLoader_h
-
-#include "CachedResourceClient.h"
-#include "CachedResourceHandle.h"
-
-#include "Document.h"
-
-namespace WebCore {
- class CachedCSSStyleSheet;
- class String;
-
- // This class is deprecated and should not be used in any new code. User
- // stylesheet loading should instead happen through Page.
- class UserStyleSheetLoader : CachedResourceClient {
- public:
- UserStyleSheetLoader(PassRefPtr<Document>, const String& url);
- ~UserStyleSheetLoader();
-
- private:
- virtual void setCSSStyleSheet(const String& URL, const String& charset, const CachedCSSStyleSheet* sheet);
-
- RefPtr<Document> m_document;
- CachedResourceHandle<CachedCSSStyleSheet> m_cachedSheet;
- };
-
-} // namespace WebCore
-
-#endif // UserStyleSheetLoader_h
diff --git a/WebCore/loader/WorkerThreadableLoader.cpp b/WebCore/loader/WorkerThreadableLoader.cpp
index 4d12b8d..bd362f4 100644
--- a/WebCore/loader/WorkerThreadableLoader.cpp
+++ b/WebCore/loader/WorkerThreadableLoader.cpp
@@ -53,11 +53,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, CrossOriginRedirectPolicy crossOriginRedirectPolicy)
+WorkerThreadableLoader::WorkerThreadableLoader(WorkerContext* workerContext, ThreadableLoaderClient* client, const String& taskMode, const ResourceRequest& request, const ThreadableLoaderOptions& options)
: m_workerContext(workerContext)
, m_workerClientWrapper(ThreadableLoaderClientWrapper::create(client))
- , m_bridge(*(new MainThreadBridge(m_workerClientWrapper, m_workerContext->thread()->workerLoaderProxy(), taskMode, request, callbacksSetting, contentSniff, storedCredentials, crossOriginRedirectPolicy)))
+ , m_bridge(*(new MainThreadBridge(m_workerClientWrapper, m_workerContext->thread()->workerLoaderProxy(), taskMode, request, options)))
{
}
@@ -66,7 +65,7 @@ WorkerThreadableLoader::~WorkerThreadableLoader()
m_bridge.destroy();
}
-void WorkerThreadableLoader::loadResourceSynchronously(WorkerContext* workerContext, const ResourceRequest& request, ThreadableLoaderClient& client, StoredCredentials storedCredentials, CrossOriginRedirectPolicy crossOriginRedirectPolicy)
+void WorkerThreadableLoader::loadResourceSynchronously(WorkerContext* workerContext, const ResourceRequest& request, ThreadableLoaderClient& client, const ThreadableLoaderOptions& options)
{
WorkerRunLoop& runLoop = workerContext->thread()->runLoop();
@@ -74,9 +73,7 @@ void WorkerThreadableLoader::loadResourceSynchronously(WorkerContext* workerCont
String mode = loadResourceSynchronouslyMode;
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, crossOriginRedirectPolicy);
-
+ RefPtr<WorkerThreadableLoader> loader = WorkerThreadableLoader::create(workerContext, &client, mode, request, options);
MessageQueueWaitResult result = MessageQueueMessageReceived;
while (!loader->done() && result != MessageQueueTerminated)
result = runLoop.runInMode(workerContext, mode);
@@ -91,21 +88,20 @@ void WorkerThreadableLoader::cancel()
}
WorkerThreadableLoader::MainThreadBridge::MainThreadBridge(PassRefPtr<ThreadableLoaderClientWrapper> workerClientWrapper, WorkerLoaderProxy& loaderProxy, const String& taskMode,
- const ResourceRequest& request, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials,
- CrossOriginRedirectPolicy crossOriginRedirectPolicy)
+ const ResourceRequest& request, const ThreadableLoaderOptions& options)
: m_workerClientWrapper(workerClientWrapper)
, m_loaderProxy(loaderProxy)
- , m_taskMode(taskMode.copy())
+ , m_taskMode(taskMode.crossThreadString())
{
ASSERT(m_workerClientWrapper.get());
- m_loaderProxy.postTaskToLoader(createCallbackTask(&MainThreadBridge::mainThreadCreateLoader, this, request, callbacksSetting, contentSniff, storedCredentials, crossOriginRedirectPolicy));
+ m_loaderProxy.postTaskToLoader(createCallbackTask(&MainThreadBridge::mainThreadCreateLoader, this, request, options));
}
WorkerThreadableLoader::MainThreadBridge::~MainThreadBridge()
{
}
-void WorkerThreadableLoader::MainThreadBridge::mainThreadCreateLoader(ScriptExecutionContext* context, MainThreadBridge* thisPtr, auto_ptr<CrossThreadResourceRequestData> requestData, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials, CrossOriginRedirectPolicy crossOriginRedirectPolicy)
+void WorkerThreadableLoader::MainThreadBridge::mainThreadCreateLoader(ScriptExecutionContext* context, MainThreadBridge* thisPtr, auto_ptr<CrossThreadResourceRequestData> requestData, ThreadableLoaderOptions options)
{
ASSERT(isMainThread());
ASSERT(context->isDocument());
@@ -117,7 +113,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, crossOriginRedirectPolicy);
+ thisPtr->m_mainThreadLoader = ThreadableLoader::create(context, thisPtr, *request, options);
ASSERT(thisPtr->m_mainThreadLoader);
}
diff --git a/WebCore/loader/WorkerThreadableLoader.h b/WebCore/loader/WorkerThreadableLoader.h
index 8b11b70..230c77d 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, CrossOriginRedirectPolicy);
- static PassRefPtr<WorkerThreadableLoader> create(WorkerContext* workerContext, ThreadableLoaderClient* client, const String& taskMode, const ResourceRequest& request, LoadCallbacks callbacksSetting, ContentSniff contentSniff, StoredCredentials storedCredentials, CrossOriginRedirectPolicy crossOriginRedirectPolicy)
+ static void loadResourceSynchronously(WorkerContext*, const ResourceRequest&, ThreadableLoaderClient&, const ThreadableLoaderOptions&);
+ static PassRefPtr<WorkerThreadableLoader> create(WorkerContext* workerContext, ThreadableLoaderClient* client, const String& taskMode, const ResourceRequest& request, const ThreadableLoaderOptions& options)
{
- return adoptRef(new WorkerThreadableLoader(workerContext, client, taskMode, request, callbacksSetting, contentSniff, storedCredentials, crossOriginRedirectPolicy));
+ return adoptRef(new WorkerThreadableLoader(workerContext, client, taskMode, request, options));
}
~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, CrossOriginRedirectPolicy);
+ MainThreadBridge(PassRefPtr<ThreadableLoaderClientWrapper>, WorkerLoaderProxy&, const String& taskMode, const ResourceRequest&, const ThreadableLoaderOptions&);
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, CrossOriginRedirectPolicy);
+ static void mainThreadCreateLoader(ScriptExecutionContext*, MainThreadBridge*, std::auto_ptr<CrossThreadResourceRequestData>, ThreadableLoaderOptions);
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, CrossOriginRedirectPolicy);
+ WorkerThreadableLoader(WorkerContext*, ThreadableLoaderClient*, const String& taskMode, const ResourceRequest&, const ThreadableLoaderOptions&);
RefPtr<WorkerContext> m_workerContext;
RefPtr<ThreadableLoaderClientWrapper> m_workerClientWrapper;
diff --git a/WebCore/loader/appcache/ApplicationCache.cpp b/WebCore/loader/appcache/ApplicationCache.cpp
index 34dace4..c0cd3ea 100644
--- a/WebCore/loader/appcache/ApplicationCache.cpp
+++ b/WebCore/loader/appcache/ApplicationCache.cpp
@@ -111,7 +111,7 @@ unsigned ApplicationCache::removeResource(const String& url)
ApplicationCacheResource* ApplicationCache::resourceForURL(const String& url)
{
- ASSERT(!KURL(url).hasFragmentIdentifier());
+ ASSERT(!KURL(ParsedURLString, url).hasFragmentIdentifier());
return m_resources.get(url).get();
}
@@ -147,6 +147,9 @@ void ApplicationCache::setOnlineWhitelist(const Vector<KURL>& onlineWhitelist)
bool ApplicationCache::isURLInOnlineWhitelist(const KURL& url)
{
+ if (m_allowAllNetworkRequests)
+ return true;
+
size_t whitelistSize = m_onlineWhitelist.size();
for (size_t i = 0; i < whitelistSize; ++i) {
if (protocolHostAndPortAreEqual(url, m_onlineWhitelist[i]) && url.string().startsWith(m_onlineWhitelist[i].string()))
diff --git a/WebCore/loader/appcache/ApplicationCache.h b/WebCore/loader/appcache/ApplicationCache.h
index b1753be..d1444c0 100644
--- a/WebCore/loader/appcache/ApplicationCache.h
+++ b/WebCore/loader/appcache/ApplicationCache.h
@@ -65,6 +65,8 @@ public:
ApplicationCacheResource* resourceForRequest(const ResourceRequest&);
ApplicationCacheResource* resourceForURL(const String& url);
+ void setAllowsAllNetworkRequests(bool value) { m_allowAllNetworkRequests = value; }
+ bool allowsAllNetworkRequests() const { return m_allowAllNetworkRequests; }
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.
@@ -96,6 +98,7 @@ private:
ResourceMap m_resources;
ApplicationCacheResource* m_manifest;
+ bool m_allowAllNetworkRequests;
Vector<KURL> m_onlineWhitelist;
FallbackURLVector m_fallbackURLs;
diff --git a/WebCore/loader/appcache/ApplicationCacheGroup.cpp b/WebCore/loader/appcache/ApplicationCacheGroup.cpp
index 41c5cac..a3d551b 100644
--- a/WebCore/loader/appcache/ApplicationCacheGroup.cpp
+++ b/WebCore/loader/appcache/ApplicationCacheGroup.cpp
@@ -158,7 +158,7 @@ void ApplicationCacheGroup::selectCache(Frame* frame, const KURL& passedManifest
// Restart the current navigation from the top of the navigation algorithm, undoing any changes that were made
// as part of the initial load.
// The navigation will not result in the same resource being loaded, because "foreign" entries are never picked during navigation.
- frame->loader()->scheduleLocationChange(documentLoader->url(), frame->loader()->referrer(), true);
+ frame->redirectScheduler()->scheduleLocationChange(documentLoader->url(), frame->loader()->referrer(), true);
}
return;
@@ -672,6 +672,7 @@ void ApplicationCacheGroup::didFinishLoadingManifest()
m_cacheBeingUpdated->setOnlineWhitelist(manifest.onlineWhitelistedURLs);
m_cacheBeingUpdated->setFallbackURLs(manifest.fallbackURLs);
+ m_cacheBeingUpdated->setAllowsAllNetworkRequests(manifest.allowAllNetworkRequests);
startLoadingEntry();
}
@@ -852,7 +853,7 @@ void ApplicationCacheGroup::startLoadingEntry()
ASSERT(!m_currentHandle);
- m_currentHandle = createResourceHandle(KURL(it->first), m_newestCache ? m_newestCache->resourceForURL(it->first) : 0);
+ m_currentHandle = createResourceHandle(KURL(ParsedURLString, it->first), m_newestCache ? m_newestCache->resourceForURL(it->first) : 0);
}
void ApplicationCacheGroup::deliverDelayedMainResources()
@@ -879,7 +880,7 @@ void ApplicationCacheGroup::deliverDelayedMainResources()
void ApplicationCacheGroup::addEntry(const String& url, unsigned type)
{
ASSERT(m_cacheBeingUpdated);
- ASSERT(!KURL(url).hasFragmentIdentifier());
+ ASSERT(!KURL(ParsedURLString, 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).
@@ -962,7 +963,7 @@ public:
ASSERT(frame->loader()->documentLoader() == m_documentLoader.get());
- m_documentLoader->applicationCacheHost()->notifyEventListener(m_eventID);
+ m_documentLoader->applicationCacheHost()->notifyDOMApplicationCache(m_eventID);
}
private:
diff --git a/WebCore/loader/appcache/ApplicationCacheGroup.h b/WebCore/loader/appcache/ApplicationCacheGroup.h
index 939646f..8df52cc 100644
--- a/WebCore/loader/appcache/ApplicationCacheGroup.h
+++ b/WebCore/loader/appcache/ApplicationCacheGroup.h
@@ -97,6 +97,10 @@ private:
PassRefPtr<ResourceHandle> createResourceHandle(const KURL&, ApplicationCacheResource* newestCachedResource);
+ // For normal resource loading, WebKit client is asked about each resource individually. Since application cache does not belong to any particular document,
+ // the existing client callback cannot be used, so assume that any client that enables application cache also wants it to use credential storage.
+ virtual bool shouldUseCredentialStorage(ResourceHandle*) { return true; }
+
virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&);
virtual void didReceiveData(ResourceHandle*, const char*, int, int lengthReceived);
virtual void didFinishLoading(ResourceHandle*);
diff --git a/WebCore/loader/appcache/ApplicationCacheHost.cpp b/WebCore/loader/appcache/ApplicationCacheHost.cpp
index b0c9e74..751efc1 100644
--- a/WebCore/loader/appcache/ApplicationCacheHost.cpp
+++ b/WebCore/loader/appcache/ApplicationCacheHost.cpp
@@ -227,10 +227,13 @@ void ApplicationCacheHost::setDOMApplicationCache(DOMApplicationCache* domApplic
m_domApplicationCache = domApplicationCache;
}
-void ApplicationCacheHost::notifyEventListener(EventID id)
+void ApplicationCacheHost::notifyDOMApplicationCache(EventID id)
{
- if (m_domApplicationCache)
- m_domApplicationCache->callEventListener(id);
+ if (m_domApplicationCache) {
+ ExceptionCode ec = 0;
+ m_domApplicationCache->dispatchEvent(Event::create(DOMApplicationCache::toEventType(id), false, false), ec);
+ ASSERT(!ec);
+ }
}
void ApplicationCacheHost::setCandidateApplicationCacheGroup(ApplicationCacheGroup* group)
@@ -255,8 +258,9 @@ bool ApplicationCacheHost::shouldLoadResourceFromApplicationCache(const Resource
if (!cache || !cache->isComplete())
return false;
- // If the resource is not a HTTP/HTTPS GET, then abort
- if (!ApplicationCache::requestIsHTTPOrHTTPSGet(request))
+ // If the resource is not to be fetched using the HTTP GET mechanism or equivalent, or if its URL has a different
+ // <scheme> component than the application cache's manifest, then fetch the resource normally.
+ if (!ApplicationCache::requestIsHTTPOrHTTPSGet(request) || !equalIgnoringCase(request.url().protocol(), cache->manifestResource()->url().protocol()))
return false;
// If the resource's URL is an master entry, the manifest, an explicit entry, or a fallback entry
diff --git a/WebCore/loader/appcache/ApplicationCacheHost.h b/WebCore/loader/appcache/ApplicationCacheHost.h
index cb68862..236013d 100644
--- a/WebCore/loader/appcache/ApplicationCacheHost.h
+++ b/WebCore/loader/appcache/ApplicationCacheHost.h
@@ -108,7 +108,7 @@ namespace WebCore {
bool swapCache();
void setDOMApplicationCache(DOMApplicationCache* domApplicationCache);
- void notifyEventListener(EventID id);
+ void notifyDOMApplicationCache(EventID id);
private:
bool isApplicationCacheEnabled();
diff --git a/WebCore/loader/appcache/ApplicationCacheStorage.cpp b/WebCore/loader/appcache/ApplicationCacheStorage.cpp
index 5a2b642..d6ee723 100644
--- a/WebCore/loader/appcache/ApplicationCacheStorage.cpp
+++ b/WebCore/loader/appcache/ApplicationCacheStorage.cpp
@@ -216,7 +216,7 @@ ApplicationCacheGroup* ApplicationCacheStorage::cacheGroupForURL(const KURL& url
int result;
while ((result = statement.step()) == SQLResultRow) {
- KURL manifestURL = KURL(statement.getColumnText(1));
+ KURL manifestURL = KURL(ParsedURLString, statement.getColumnText(1));
if (m_cachesInMemory.contains(manifestURL))
continue;
@@ -284,7 +284,7 @@ ApplicationCacheGroup* ApplicationCacheStorage::fallbackCacheGroupForURL(const K
int result;
while ((result = statement.step()) == SQLResultRow) {
- KURL manifestURL = KURL(statement.getColumnText(1));
+ KURL manifestURL = KURL(ParsedURLString, statement.getColumnText(1));
if (m_cachesInMemory.contains(manifestURL))
continue;
@@ -427,7 +427,7 @@ bool ApplicationCacheStorage::executeSQLCommand(const String& sql)
return result;
}
-static const int schemaVersion = 4;
+static const int schemaVersion = 5;
void ApplicationCacheStorage::verifySchemaVersion()
{
@@ -479,6 +479,7 @@ void ApplicationCacheStorage::openDatabase(bool createIfDoesNotExist)
"manifestHostHash INTEGER NOT NULL ON CONFLICT FAIL, manifestURL TEXT UNIQUE ON CONFLICT FAIL, newestCache INTEGER)");
executeSQLCommand("CREATE TABLE IF NOT EXISTS Caches (id INTEGER PRIMARY KEY AUTOINCREMENT, cacheGroup INTEGER, size INTEGER)");
executeSQLCommand("CREATE TABLE IF NOT EXISTS CacheWhitelistURLs (url TEXT NOT NULL ON CONFLICT FAIL, cache INTEGER NOT NULL ON CONFLICT FAIL)");
+ executeSQLCommand("CREATE TABLE IF NOT EXISTS CacheAllowsAllNetworkRequests (wildcard INTEGER NOT NULL ON CONFLICT FAIL, cache INTEGER NOT NULL ON CONFLICT FAIL)");
executeSQLCommand("CREATE TABLE IF NOT EXISTS FallbackURLs (namespace TEXT NOT NULL ON CONFLICT FAIL, fallbackURL TEXT NOT NULL ON CONFLICT FAIL, "
"cache INTEGER NOT NULL ON CONFLICT FAIL)");
executeSQLCommand("CREATE TABLE IF NOT EXISTS CacheEntries (cache INTEGER NOT NULL ON CONFLICT FAIL, type INTEGER, resource INTEGER NOT NULL)");
@@ -491,6 +492,7 @@ void ApplicationCacheStorage::openDatabase(bool createIfDoesNotExist)
" FOR EACH ROW BEGIN"
" DELETE FROM CacheEntries WHERE cache = OLD.id;"
" DELETE FROM CacheWhitelistURLs WHERE cache = OLD.id;"
+ " DELETE FROM CacheAllowsAllNetworkRequests WHERE cache = OLD.id;"
" DELETE FROM FallbackURLs WHERE cache = OLD.id;"
" END");
@@ -584,6 +586,18 @@ bool ApplicationCacheStorage::store(ApplicationCache* cache, ResourceStorageIDJo
return false;
}
}
+
+ // Store online whitelist wildcard flag.
+ {
+ SQLiteStatement statement(m_database, "INSERT INTO CacheAllowsAllNetworkRequests (wildcard, cache) VALUES (?, ?)");
+ statement.prepare();
+
+ statement.bindInt64(1, cache->allowsAllNetworkRequests());
+ statement.bindInt64(2, cacheStorageID);
+
+ if (!executeStatement(statement))
+ return false;
+ }
// Store fallback URLs.
const FallbackURLVector& fallbackURLs = cache->fallbackURLs();
@@ -821,7 +835,7 @@ PassRefPtr<ApplicationCache> ApplicationCacheStorage::loadCache(unsigned storage
int result;
while ((result = cacheStatement.step()) == SQLResultRow) {
- KURL url(cacheStatement.getColumnText(0));
+ KURL url(ParsedURLString, cacheStatement.getColumnText(0));
unsigned type = static_cast<unsigned>(cacheStatement.getColumnInt64(1));
@@ -857,13 +871,28 @@ PassRefPtr<ApplicationCache> ApplicationCacheStorage::loadCache(unsigned storage
Vector<KURL> whitelist;
while ((result = whitelistStatement.step()) == SQLResultRow)
- whitelist.append(whitelistStatement.getColumnText(0));
+ whitelist.append(KURL(ParsedURLString, whitelistStatement.getColumnText(0)));
if (result != SQLResultDone)
LOG_ERROR("Could not load cache online whitelist, error \"%s\"", m_database.lastErrorMsg());
cache->setOnlineWhitelist(whitelist);
+ // Load online whitelist wildcard flag.
+ SQLiteStatement whitelistWildcardStatement(m_database, "SELECT wildcard FROM CacheAllowsAllNetworkRequests WHERE cache=?");
+ if (whitelistWildcardStatement.prepare() != SQLResultOk)
+ return 0;
+ whitelistWildcardStatement.bindInt64(1, storageID);
+
+ result = whitelistWildcardStatement.step();
+ if (result != SQLResultRow)
+ LOG_ERROR("Could not load cache online whitelist wildcard flag, error \"%s\"", m_database.lastErrorMsg());
+
+ cache->setAllowsAllNetworkRequests(whitelistWildcardStatement.getColumnInt64(0));
+
+ if (whitelistWildcardStatement.step() != SQLResultDone)
+ LOG_ERROR("Too many rows for online whitelist wildcard flag");
+
// Load fallback URLs.
SQLiteStatement fallbackStatement(m_database, "SELECT namespace, fallbackURL FROM FallbackURLs WHERE cache=?");
if (fallbackStatement.prepare() != SQLResultOk)
@@ -872,7 +901,7 @@ PassRefPtr<ApplicationCache> ApplicationCacheStorage::loadCache(unsigned storage
FallbackURLVector fallbackURLs;
while ((result = fallbackStatement.step()) == SQLResultRow)
- fallbackURLs.append(make_pair(fallbackStatement.getColumnText(0), fallbackStatement.getColumnText(1)));
+ fallbackURLs.append(make_pair(KURL(ParsedURLString, fallbackStatement.getColumnText(0)), KURL(ParsedURLString, fallbackStatement.getColumnText(1))));
if (result != SQLResultDone)
LOG_ERROR("Could not load fallback URLs, error \"%s\"", m_database.lastErrorMsg());
@@ -987,7 +1016,7 @@ bool ApplicationCacheStorage::manifestURLs(Vector<KURL>* urls)
return false;
while (selectURLs.step() == SQLResultRow)
- urls->append(selectURLs.getColumnText(0));
+ urls->append(KURL(ParsedURLString, selectURLs.getColumnText(0)));
return true;
}
diff --git a/WebCore/loader/appcache/DOMApplicationCache.cpp b/WebCore/loader/appcache/DOMApplicationCache.cpp
index ab5802f..1496b8a 100644
--- a/WebCore/loader/appcache/DOMApplicationCache.cpp
+++ b/WebCore/loader/appcache/DOMApplicationCache.cpp
@@ -42,8 +42,10 @@ namespace WebCore {
DOMApplicationCache::DOMApplicationCache(Frame* frame)
: m_frame(frame)
{
- ASSERT(applicationCacheHost());
- applicationCacheHost()->setDOMApplicationCache(this);
+ ASSERT(!m_frame || applicationCacheHost());
+ ApplicationCacheHost* cacheHost = applicationCacheHost();
+ if (cacheHost)
+ cacheHost->setDOMApplicationCache(this);
}
void DOMApplicationCache::disconnectFrame()
@@ -76,90 +78,17 @@ void DOMApplicationCache::update(ExceptionCode& ec)
ec = INVALID_STATE_ERR;
}
-bool DOMApplicationCache::swapCache()
-{
- ApplicationCacheHost* cacheHost = applicationCacheHost();
- if (!cacheHost)
- return false;
- return cacheHost->swapCache();
-}
-
void DOMApplicationCache::swapCache(ExceptionCode& ec)
{
- if (!swapCache())
+ ApplicationCacheHost* cacheHost = applicationCacheHost();
+ if (!cacheHost || !cacheHost->swapCache())
ec = INVALID_STATE_ERR;
}
ScriptExecutionContext* DOMApplicationCache::scriptExecutionContext() const
{
- return m_frame->document();
-}
-
-void DOMApplicationCache::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> eventListener, bool)
-{
- EventListenersMap::iterator iter = m_eventListeners.find(eventType);
- if (iter == m_eventListeners.end()) {
- ListenerVector listeners;
- listeners.append(eventListener);
- m_eventListeners.add(eventType, listeners);
- } else {
- ListenerVector& listeners = iter->second;
- for (ListenerVector::iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) {
- if (*listenerIter == eventListener)
- return;
- }
-
- listeners.append(eventListener);
- m_eventListeners.add(eventType, listeners);
- }
-}
-
-void DOMApplicationCache::removeEventListener(const AtomicString& eventType, EventListener* eventListener, bool)
-{
- EventListenersMap::iterator iter = m_eventListeners.find(eventType);
- if (iter == m_eventListeners.end())
- return;
-
- ListenerVector& listeners = iter->second;
- for (ListenerVector::const_iterator listenerIter = listeners.begin(); listenerIter != listeners.end(); ++listenerIter) {
- if (*listenerIter == eventListener) {
- listeners.remove(listenerIter - listeners.begin());
- return;
- }
- }
-}
-
-bool DOMApplicationCache::dispatchEvent(PassRefPtr<Event> event, ExceptionCode& ec)
-{
- if (!event || event->type().isEmpty()) {
- 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);
- event->setCurrentTarget(this);
- listenerIter->get()->handleEvent(event.get(), false);
- }
-
- return !event->defaultPrevented();
-}
-
-void DOMApplicationCache::callListener(const AtomicString& eventType, EventListener* listener)
-{
ASSERT(m_frame);
-
- RefPtr<Event> event = Event::create(eventType, false, false);
- if (listener) {
- event->setTarget(this);
- event->setCurrentTarget(this);
- listener->handleEvent(event.get(), false);
- }
-
- ExceptionCode ec = 0;
- dispatchEvent(event.release(), ec);
- ASSERT(!ec);
+ return m_frame->document();
}
const AtomicString& DOMApplicationCache::toEventType(ApplicationCacheHost::EventID id)
@@ -186,29 +115,19 @@ const AtomicString& DOMApplicationCache::toEventType(ApplicationCacheHost::Event
return eventNames().errorEvent;
}
-ApplicationCacheHost::EventID DOMApplicationCache::toEventID(const AtomicString& eventType)
+EventTargetData* DOMApplicationCache::eventTargetData()
{
- 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;
+ return &m_eventTargetData;
+}
+
+<<<<<<< HEAD:WebCore/loader/appcache/DOMApplicationCache.cpp
+=======
+EventTargetData* DOMApplicationCache::ensureEventTargetData()
+{
+ return &m_eventTargetData;
}
+>>>>>>> webkit.org at 49305:WebCore/loader/appcache/DOMApplicationCache.cpp
} // namespace WebCore
#endif // ENABLE(OFFLINE_WEB_APPLICATIONS)
diff --git a/WebCore/loader/appcache/DOMApplicationCache.h b/WebCore/loader/appcache/DOMApplicationCache.h
index 276f50e..077cae0 100644
--- a/WebCore/loader/appcache/DOMApplicationCache.h
+++ b/WebCore/loader/appcache/DOMApplicationCache.h
@@ -30,8 +30,9 @@
#include "ApplicationCacheHost.h"
#include "AtomicStringHash.h"
-#include "EventTarget.h"
#include "EventListener.h"
+#include "EventNames.h"
+#include "EventTarget.h"
#include <wtf/HashMap.h>
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
@@ -55,73 +56,39 @@ public:
void update(ExceptionCode&);
void swapCache(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; }
-
using RefCounted<DOMApplicationCache>::ref;
using RefCounted<DOMApplicationCache>::deref;
// Explicitly named attribute event listener helpers
- void setOnchecking(PassRefPtr<EventListener> listener) { setAttributeEventListener(ApplicationCacheHost::CHECKING_EVENT, listener); }
- EventListener* onchecking() const { return getAttributeEventListener(ApplicationCacheHost::CHECKING_EVENT); }
-
- void setOnerror(PassRefPtr<EventListener> listener) { setAttributeEventListener(ApplicationCacheHost::ERROR_EVENT, listener);}
- EventListener* onerror() const { return getAttributeEventListener(ApplicationCacheHost::ERROR_EVENT); }
-
- 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> listener) { setAttributeEventListener(ApplicationCacheHost::UPDATEREADY_EVENT, listener); }
- EventListener* onupdateready() const { return getAttributeEventListener(ApplicationCacheHost::UPDATEREADY_EVENT); }
-
- void setOncached(PassRefPtr<EventListener> listener) { setAttributeEventListener(ApplicationCacheHost::CACHED_EVENT, listener); }
- EventListener* oncached() const { return getAttributeEventListener(ApplicationCacheHost::CACHED_EVENT); }
-
- void setOnobsolete(PassRefPtr<EventListener> listener) { setAttributeEventListener(ApplicationCacheHost::OBSOLETE_EVENT, listener); }
- EventListener* onobsolete() const { return getAttributeEventListener(ApplicationCacheHost::OBSOLETE_EVENT); }
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(checking);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(error);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(noupdate);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(downloading);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(progress);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(updateready);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(cached);
+ DEFINE_ATTRIBUTE_EVENT_LISTENER(obsolete);
virtual ScriptExecutionContext* scriptExecutionContext() const;
DOMApplicationCache* toDOMApplicationCache() { return this; }
static const AtomicString& toEventType(ApplicationCacheHost::EventID id);
- static ApplicationCacheHost::EventID toEventID(const AtomicString& eventType);
private:
DOMApplicationCache(Frame*);
- void callListener(const AtomicString& eventType, EventListener*);
-
virtual void refEventTarget() { ref(); }
virtual void derefEventTarget() { deref(); }
+ virtual EventTargetData* eventTargetData();
+ virtual EventTargetData* ensureEventTargetData();
ApplicationCacheHost* applicationCacheHost() const;
- bool swapCache();
-
- RefPtr<EventListener> m_attributeEventListeners[ApplicationCacheHost::OBSOLETE_EVENT + 1];
-
- EventListenersMap m_eventListeners;
Frame* m_frame;
+ EventTargetData m_eventTargetData;
};
} // namespace WebCore
diff --git a/WebCore/loader/appcache/DOMApplicationCache.idl b/WebCore/loader/appcache/DOMApplicationCache.idl
index ebc1d19..dd5468a 100644
--- a/WebCore/loader/appcache/DOMApplicationCache.idl
+++ b/WebCore/loader/appcache/DOMApplicationCache.idl
@@ -27,7 +27,7 @@ module offline {
interface [
Conditional=OFFLINE_WEB_APPLICATIONS,
- CustomMarkFunction
+ EventTarget
] DOMApplicationCache {
// update status
const unsigned short UNCACHED = 0;
diff --git a/WebCore/loader/appcache/ManifestParser.cpp b/WebCore/loader/appcache/ManifestParser.cpp
index a2df825..b001bff 100644
--- a/WebCore/loader/appcache/ManifestParser.cpp
+++ b/WebCore/loader/appcache/ManifestParser.cpp
@@ -43,7 +43,8 @@ bool parseManifest(const KURL& manifestURL, const char* data, int length, Manife
ASSERT(manifest.explicitURLs.isEmpty());
ASSERT(manifest.onlineWhitelistedURLs.isEmpty());
ASSERT(manifest.fallbackURLs.isEmpty());
-
+ manifest.allowAllNetworkRequests = false;
+
Mode mode = Explicit;
RefPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("text/cache-manifest", "UTF-8");
@@ -109,6 +110,12 @@ bool parseManifest(const KURL& manifestURL, const char* data, int length, Manife
while (p < lineEnd && *p != '\t' && *p != ' ')
p++;
+ if (mode == OnlineWhitelist && p - line.characters() == 1 && *line.characters() == '*') {
+ // Wildcard was found.
+ manifest.allowAllNetworkRequests = true;
+ continue;
+ }
+
KURL url(manifestURL, String(line.characters(), p - line.characters()));
if (!url.isValid())
diff --git a/WebCore/loader/appcache/ManifestParser.h b/WebCore/loader/appcache/ManifestParser.h
index c03cf27..f0369ee 100644
--- a/WebCore/loader/appcache/ManifestParser.h
+++ b/WebCore/loader/appcache/ManifestParser.h
@@ -38,6 +38,7 @@ namespace WebCore {
Vector<KURL> onlineWhitelistedURLs;
HashSet<String> explicitURLs;
FallbackURLVector fallbackURLs;
+ bool allowAllNetworkRequests; // Wildcard found in NETWORK section.
};
bool parseManifest(const KURL& manifestURL, const char* data, int length, Manifest&);
diff --git a/WebCore/loader/archive/cf/LegacyWebArchive.cpp b/WebCore/loader/archive/cf/LegacyWebArchive.cpp
index d1269cc..3141e98 100644
--- a/WebCore/loader/archive/cf/LegacyWebArchive.cpp
+++ b/WebCore/loader/archive/cf/LegacyWebArchive.cpp
@@ -233,7 +233,7 @@ PassRefPtr<ArchiveResource> LegacyWebArchive::createResource(CFDictionaryRef dic
response = createResourceResponseFromPropertyListData(resourceResponseData, resourceResponseVersion);
}
- return ArchiveResource::create(SharedBuffer::create(CFDataGetBytePtr(resourceData), CFDataGetLength(resourceData)), KURL(url), mimeType, textEncoding, frameName, response);
+ return ArchiveResource::create(SharedBuffer::create(CFDataGetBytePtr(resourceData), CFDataGetLength(resourceData)), KURL(ParsedURLString, url), mimeType, textEncoding, frameName, response);
}
PassRefPtr<LegacyWebArchive> LegacyWebArchive::create()
@@ -489,7 +489,7 @@ PassRefPtr<LegacyWebArchive> LegacyWebArchive::create(const String& markupString
// it's possible to have a response without a URL here
// <rdar://problem/5454935>
if (responseURL.isNull())
- responseURL = KURL("");
+ responseURL = KURL(ParsedURLString, "");
PassRefPtr<ArchiveResource> mainResource = ArchiveResource::create(utf8Buffer(markupString), responseURL, response.mimeType(), "UTF-8", frame->tree()->name());
@@ -548,7 +548,7 @@ PassRefPtr<LegacyWebArchive> LegacyWebArchive::create(const String& markupString
const String& iconURL = iconDatabase()->iconURLForPageURL(responseURL);
if (!iconURL.isEmpty() && iconDatabase()->iconDataKnownForIconURL(iconURL)) {
if (Image* iconImage = iconDatabase()->iconForPageURL(responseURL, IntSize(16, 16))) {
- if (RefPtr<ArchiveResource> resource = ArchiveResource::create(iconImage->data(), KURL(iconURL), "image/x-icon", "", ""))
+ if (RefPtr<ArchiveResource> resource = ArchiveResource::create(iconImage->data(), KURL(ParsedURLString, iconURL), "image/x-icon", "", ""))
subresources.append(resource.release());
}
}
diff --git a/WebCore/loader/icon/IconDatabase.cpp b/WebCore/loader/icon/IconDatabase.cpp
index c0af78f..8982cda 100644
--- a/WebCore/loader/icon/IconDatabase.cpp
+++ b/WebCore/loader/icon/IconDatabase.cpp
@@ -137,7 +137,7 @@ bool IconDatabase::open(const String& databasePath)
return false;
}
- m_databaseDirectory = databasePath.copy();
+ m_databaseDirectory = databasePath.crossThreadString();
// Formulate the full path for the database file
m_completeDatabasePath = pathByAppendingComponent(m_databaseDirectory, defaultDatabaseFilename());
@@ -241,7 +241,7 @@ Image* IconDatabase::iconForPageURL(const String& pageURLOriginal, const IntSize
PageURLRecord* pageRecord = m_pageURLToRecordMap.get(pageURLOriginal);
if (!pageRecord) {
- pageURLCopy = pageURLOriginal.copy();
+ pageURLCopy = pageURLOriginal.crossThreadString();
pageRecord = getOrCreatePageURLRecord(pageURLCopy);
}
@@ -277,7 +277,7 @@ Image* IconDatabase::iconForPageURL(const String& pageURLOriginal, const IntSize
// mark it to be read by the background thread
if (iconRecord->imageDataStatus() == ImageDataStatusUnknown) {
if (pageURLCopy.isNull())
- pageURLCopy = pageURLOriginal.copy();
+ pageURLCopy = pageURLOriginal.crossThreadString();
MutexLocker locker(m_pendingReadingLock);
m_pageURLsInterestedInIcons.add(pageURLCopy);
@@ -326,7 +326,7 @@ String IconDatabase::iconURLForPageURL(const String& pageURLOriginal)
PageURLRecord* pageRecord = m_pageURLToRecordMap.get(pageURLOriginal);
if (!pageRecord)
- pageRecord = getOrCreatePageURLRecord(pageURLOriginal.copy());
+ pageRecord = getOrCreatePageURLRecord(pageURLOriginal.crossThreadString());
// If pageRecord is NULL, one of two things is true -
// 1 - The initial url import is incomplete and this pageURL has already been marked to be notified once it is complete if an iconURL exists
@@ -335,7 +335,7 @@ String IconDatabase::iconURLForPageURL(const String& pageURLOriginal)
return String();
// Possible the pageRecord is around because it's a retained pageURL with no iconURL, so we have to check
- return pageRecord->iconRecord() ? pageRecord->iconRecord()->iconURL().copy() : String();
+ return pageRecord->iconRecord() ? pageRecord->iconRecord()->iconURL().threadsafeCopy() : String();
}
#ifdef CAN_THEME_URL_ICON
@@ -419,7 +419,7 @@ void IconDatabase::retainIconForPageURL(const String& pageURLOriginal)
String pageURL;
if (!record) {
- pageURL = pageURLOriginal.copy();
+ pageURL = pageURLOriginal.crossThreadString();
record = new PageURLRecord(pageURL);
m_pageURLToRecordMap.set(pageURL, record);
@@ -427,7 +427,7 @@ void IconDatabase::retainIconForPageURL(const String& pageURLOriginal)
if (!record->retain()) {
if (pageURL.isNull())
- pageURL = pageURLOriginal.copy();
+ pageURL = pageURLOriginal.crossThreadString();
// This page just had its retain count bumped from 0 to 1 - Record that fact
m_retainedPageURLs.add(pageURL);
@@ -502,7 +502,7 @@ void IconDatabase::releaseIconForPageURL(const String& pageURLOriginal)
// Mark stuff for deletion from the database only if we're not in private browsing
if (!m_privateBrowsingEnabled) {
MutexLocker locker(m_pendingSyncLock);
- m_pageURLsPendingSync.set(pageURLOriginal.copy(), pageRecord->snapshot(true));
+ m_pageURLsPendingSync.set(pageURLOriginal.crossThreadString(), pageRecord->snapshot(true));
// If this page is the last page to refer to a particular IconRecord, that IconRecord needs to
// be marked for deletion
@@ -526,7 +526,7 @@ void IconDatabase::setIconDataForIconURL(PassRefPtr<SharedBuffer> dataOriginal,
return;
RefPtr<SharedBuffer> data = dataOriginal ? dataOriginal->copy() : 0;
- String iconURL = iconURLOriginal.copy();
+ String iconURL = iconURLOriginal.crossThreadString();
Vector<String> pageURLs;
{
@@ -603,8 +603,8 @@ void IconDatabase::setIconURLForPageURL(const String& iconURLOriginal, const Str
if (pageRecord && pageRecord->iconRecord() && pageRecord->iconRecord()->iconURL() == iconURLOriginal)
return;
- pageURL = pageURLOriginal.copy();
- iconURL = iconURLOriginal.copy();
+ pageURL = pageURLOriginal.crossThreadString();
+ iconURL = iconURLOriginal.crossThreadString();
if (!pageRecord) {
pageRecord = new PageURLRecord(pageURL);
@@ -861,13 +861,13 @@ bool IconDatabase::isOpen() const
String IconDatabase::databasePath() const
{
MutexLocker locker(m_syncLock);
- return m_completeDatabasePath.copy();
+ return m_completeDatabasePath.threadsafeCopy();
}
String IconDatabase::defaultDatabaseFilename()
{
DEFINE_STATIC_LOCAL(String, defaultDatabaseFilename, ("WebpageIcons.db"));
- return defaultDatabaseFilename.copy();
+ return defaultDatabaseFilename.threadsafeCopy();
}
// Unlike getOrCreatePageURLRecord(), getOrCreateIconRecord() does not mark the icon as "interested in import"
diff --git a/WebCore/loader/icon/IconDatabaseNone.cpp b/WebCore/loader/icon/IconDatabaseNone.cpp
index 03a7964..7b7cc9f 100644
--- a/WebCore/loader/icon/IconDatabaseNone.cpp
+++ b/WebCore/loader/icon/IconDatabaseNone.cpp
@@ -53,7 +53,7 @@ const int updateTimerDelay = 5;
String IconDatabase::defaultDatabaseFilename()
{
DEFINE_STATIC_LOCAL(String, defaultDatabaseFilename, ("Icons.db"));
- return defaultDatabaseFilename.copy();
+ return defaultDatabaseFilename.threadsafeCopy();
}
IconDatabase* iconDatabase()
diff --git a/WebCore/loader/loader.cpp b/WebCore/loader/loader.cpp
index 65d15a5..eb606d8 100644
--- a/WebCore/loader/loader.cpp
+++ b/WebCore/loader/loader.cpp
@@ -102,7 +102,7 @@ void Loader::load(DocLoader* docLoader, CachedResource* resource, bool increment
Request* request = new Request(docLoader, resource, incremental, skipCanLoadCheck, sendResourceLoadCallbacks);
RefPtr<Host> host;
- KURL url(resource->url());
+ KURL url(ParsedURLString, resource->url());
if (url.protocolInHTTPFamily()) {
AtomicString hostName = url.host();
host = m_hosts.get(hostName.impl());
@@ -355,7 +355,7 @@ void Loader::Host::didFinishLoading(SubresourceLoader* loader)
DocLoader* docLoader = request->docLoader();
// Prevent the document from being destroyed before we are done with
// the docLoader that it will delete when the document gets deleted.
- DocPtr<Document> protector(docLoader->doc());
+ RefPtr<Document> protector(docLoader->doc());
if (!request->isMultipart())
docLoader->decrementRequestCount();
@@ -403,7 +403,7 @@ void Loader::Host::didFail(SubresourceLoader* loader, bool cancelled)
DocLoader* docLoader = request->docLoader();
// Prevent the document from being destroyed before we are done with
// the docLoader that it will delete when the document gets deleted.
- DocPtr<Document> protector(docLoader->doc());
+ RefPtr<Document> protector(docLoader->doc());
if (!request->isMultipart())
docLoader->decrementRequestCount();