summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/network
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/network')
-rw-r--r--WebCore/platform/network/FormDataBuilder.h2
-rw-r--r--WebCore/platform/network/HTTPParsers.cpp7
-rw-r--r--WebCore/platform/network/ResourceHandle.h8
-rw-r--r--WebCore/platform/network/ResourceHandleInternal.h6
-rw-r--r--WebCore/platform/network/ResourceResponseBase.cpp28
-rw-r--r--WebCore/platform/network/ResourceResponseBase.h2
-rw-r--r--WebCore/platform/network/cf/ResourceHandleCFNet.cpp22
-rw-r--r--WebCore/platform/network/curl/ResourceHandleCurl.cpp2
-rw-r--r--WebCore/platform/network/curl/ResourceHandleManager.cpp2
-rw-r--r--WebCore/platform/network/curl/ResourceHandleManager.h5
-rw-r--r--WebCore/platform/network/mac/FormDataStreamMac.mm9
-rw-r--r--WebCore/platform/network/mac/ResourceHandleMac.mm49
-rw-r--r--WebCore/platform/network/mac/ResourceResponseMac.mm16
-rw-r--r--WebCore/platform/network/mac/WebCoreURLResponse.h7
-rw-r--r--WebCore/platform/network/mac/WebCoreURLResponse.mm257
-rw-r--r--WebCore/platform/network/qt/QNetworkReplyHandler.cpp42
-rw-r--r--WebCore/platform/network/qt/QNetworkReplyHandler.h8
-rw-r--r--WebCore/platform/network/qt/ResourceHandleQt.cpp36
-rw-r--r--WebCore/platform/network/soup/ResourceHandleSoup.cpp200
19 files changed, 501 insertions, 207 deletions
diff --git a/WebCore/platform/network/FormDataBuilder.h b/WebCore/platform/network/FormDataBuilder.h
index 666f0c1..286f59f 100644
--- a/WebCore/platform/network/FormDataBuilder.h
+++ b/WebCore/platform/network/FormDataBuilder.h
@@ -30,7 +30,7 @@ class CString;
class Document;
class TextEncoding;
-class FormDataBuilder : Noncopyable {
+class FormDataBuilder : public Noncopyable {
public:
FormDataBuilder();
~FormDataBuilder();
diff --git a/WebCore/platform/network/HTTPParsers.cpp b/WebCore/platform/network/HTTPParsers.cpp
index e57401e..9202660 100644
--- a/WebCore/platform/network/HTTPParsers.cpp
+++ b/WebCore/platform/network/HTTPParsers.cpp
@@ -100,6 +100,13 @@ bool parseHTTPRefresh(const String& refresh, bool fromHttpEquivMeta, double& del
if (refresh[urlEndPos] == quotationMark)
break;
}
+
+ // https://bugs.webkit.org/show_bug.cgi?id=27868
+ // Sometimes there is no closing quote for the end of the URL even though there was an opening quote.
+ // If we looped over the entire alleged URL string back to the opening quote, just go ahead and use everything
+ // after the opening quote instead.
+ if (urlEndPos == urlStartPos)
+ urlEndPos = len;
}
url = refresh.substring(urlStartPos, urlEndPos - urlStartPos).stripWhiteSpace();
diff --git a/WebCore/platform/network/ResourceHandle.h b/WebCore/platform/network/ResourceHandle.h
index 3b27b00..e82e13b 100644
--- a/WebCore/platform/network/ResourceHandle.h
+++ b/WebCore/platform/network/ResourceHandle.h
@@ -105,7 +105,7 @@ public:
static PassRefPtr<ResourceHandle> create(const ResourceRequest&, ResourceHandleClient*, Frame*, bool defersLoading, bool shouldContentSniff, bool mightDownloadFromHandle = false);
static void loadResourceSynchronously(const ResourceRequest&, StoredCredentials, ResourceError&, ResourceResponse&, Vector<char>& data, Frame* frame);
- static bool willLoadFromCache(ResourceRequest&);
+ static bool willLoadFromCache(ResourceRequest&, Frame*);
#if PLATFORM(MAC)
static bool didSendBodyDataDelegateExists();
#endif
@@ -191,12 +191,6 @@ public:
void fireFailure(Timer<ResourceHandle>*);
private:
-#if USE(SOUP)
- bool startData(String urlString);
- bool startHttp(String urlString);
- bool startGio(KURL url);
-#endif
-
void scheduleFailure(FailureType);
bool start(Frame*);
diff --git a/WebCore/platform/network/ResourceHandleInternal.h b/WebCore/platform/network/ResourceHandleInternal.h
index b10c658..7951109 100644
--- a/WebCore/platform/network/ResourceHandleInternal.h
+++ b/WebCore/platform/network/ResourceHandleInternal.h
@@ -35,7 +35,7 @@
#include <CFNetwork/CFURLConnectionPriv.h>
#endif
-#if USE(WININET)
+#if USE(WININET) || (USE(CURL) && PLATFORM(WIN))
#include <winsock2.h>
#include <windows.h>
#endif
@@ -81,7 +81,7 @@ namespace android {
namespace WebCore {
class ResourceHandleClient;
- class ResourceHandleInternal : Noncopyable {
+ class ResourceHandleInternal : public Noncopyable {
public:
ResourceHandleInternal(ResourceHandle* loader, const ResourceRequest& request, ResourceHandleClient* c, bool defersLoading, bool shouldContentSniff, bool mightDownloadFromHandle)
: m_client(c)
@@ -117,7 +117,6 @@ namespace WebCore {
#if USE(SOUP)
, m_msg(0)
, m_cancelled(false)
- , m_reportedHeaders(false)
, m_gfile(0)
, m_inputStream(0)
, m_cancellable(0)
@@ -203,7 +202,6 @@ namespace WebCore {
SoupMessage* m_msg;
ResourceResponse m_response;
bool m_cancelled;
- bool m_reportedHeaders;
GFile* m_gfile;
GInputStream* m_inputStream;
GCancellable* m_cancellable;
diff --git a/WebCore/platform/network/ResourceResponseBase.cpp b/WebCore/platform/network/ResourceResponseBase.cpp
index 965759e..7f8a4e2 100644
--- a/WebCore/platform/network/ResourceResponseBase.cpp
+++ b/WebCore/platform/network/ResourceResponseBase.cpp
@@ -42,12 +42,21 @@ static void parseCacheHeader(const String& header, Vector<pair<String, String> >
ResourceResponseBase::ResourceResponseBase()
: m_expectedContentLength(0)
, m_httpStatusCode(0)
+ , m_lastModifiedDate(0)
, m_isNull(true)
, m_haveParsedCacheControlHeader(false)
, m_haveParsedAgeHeader(false)
, m_haveParsedDateHeader(false)
, m_haveParsedExpiresHeader(false)
, m_haveParsedLastModifiedHeader(false)
+ , m_cacheControlContainsNoCache(false)
+ , m_cacheControlContainsNoStore(false)
+ , m_cacheControlContainsMustRevalidate(false)
+ , m_cacheControlMaxAge(0.0)
+ , m_age(0.0)
+ , m_date(0.0)
+ , m_expires(0.0)
+ , m_lastModified(0.0)
{
}
@@ -58,12 +67,21 @@ ResourceResponseBase::ResourceResponseBase(const KURL& url, const String& mimeTy
, m_textEncodingName(textEncodingName)
, m_suggestedFilename(filename)
, m_httpStatusCode(0)
+ , m_lastModifiedDate(0)
, m_isNull(false)
, m_haveParsedCacheControlHeader(false)
, m_haveParsedAgeHeader(false)
, m_haveParsedDateHeader(false)
, m_haveParsedExpiresHeader(false)
, m_haveParsedLastModifiedHeader(false)
+ , m_cacheControlContainsNoCache(false)
+ , m_cacheControlContainsNoStore(false)
+ , m_cacheControlContainsMustRevalidate(false)
+ , m_cacheControlMaxAge(0.0)
+ , m_age(0.0)
+ , m_date(0.0)
+ , m_expires(0.0)
+ , m_lastModified(0.0)
{
}
@@ -266,6 +284,7 @@ void ResourceResponseBase::parseCacheControlDirectives() const
DEFINE_STATIC_LOCAL(const AtomicString, cacheControlString, ("cache-control"));
DEFINE_STATIC_LOCAL(const AtomicString, noCacheDirective, ("no-cache"));
+ DEFINE_STATIC_LOCAL(const AtomicString, noStoreDirective, ("no-store"));
DEFINE_STATIC_LOCAL(const AtomicString, mustRevalidateDirective, ("must-revalidate"));
DEFINE_STATIC_LOCAL(const AtomicString, maxAgeDirective, ("max-age"));
@@ -280,6 +299,8 @@ void ResourceResponseBase::parseCacheControlDirectives() const
// It should be ignored by a browser level cache.
if (equalIgnoringCase(directives[i].first, noCacheDirective) && directives[i].second.isEmpty())
m_cacheControlContainsNoCache = true;
+ else if (equalIgnoringCase(directives[i].first, noStoreDirective))
+ m_cacheControlContainsNoStore = true;
else if (equalIgnoringCase(directives[i].first, mustRevalidateDirective))
m_cacheControlContainsMustRevalidate = true;
else if (equalIgnoringCase(directives[i].first, maxAgeDirective)) {
@@ -308,6 +329,13 @@ bool ResourceResponseBase::cacheControlContainsNoCache() const
return m_cacheControlContainsNoCache;
}
+bool ResourceResponseBase::cacheControlContainsNoStore() const
+{
+ if (!m_haveParsedCacheControlHeader)
+ parseCacheControlDirectives();
+ return m_cacheControlContainsNoStore;
+}
+
bool ResourceResponseBase::cacheControlContainsMustRevalidate() const
{
if (!m_haveParsedCacheControlHeader)
diff --git a/WebCore/platform/network/ResourceResponseBase.h b/WebCore/platform/network/ResourceResponseBase.h
index 7138908..7594c09 100644
--- a/WebCore/platform/network/ResourceResponseBase.h
+++ b/WebCore/platform/network/ResourceResponseBase.h
@@ -86,6 +86,7 @@ public:
// These functions return parsed values of the corresponding response headers.
// NaN means that the header was not present or had invalid value.
bool cacheControlContainsNoCache() const;
+ bool cacheControlContainsNoStore() const;
bool cacheControlContainsMustRevalidate() const;
double cacheControlMaxAge() const;
double date() const;
@@ -136,6 +137,7 @@ private:
mutable bool m_haveParsedLastModifiedHeader : 1;
mutable bool m_cacheControlContainsNoCache : 1;
+ mutable bool m_cacheControlContainsNoStore : 1;
mutable bool m_cacheControlContainsMustRevalidate : 1;
mutable double m_cacheControlMaxAge;
diff --git a/WebCore/platform/network/cf/ResourceHandleCFNet.cpp b/WebCore/platform/network/cf/ResourceHandleCFNet.cpp
index 1d5bf9f..e348f83 100644
--- a/WebCore/platform/network/cf/ResourceHandleCFNet.cpp
+++ b/WebCore/platform/network/cf/ResourceHandleCFNet.cpp
@@ -116,9 +116,27 @@ CFURLRequestRef willSendRequest(CFURLConnectionRef conn, CFURLRequestRef cfReque
LOG(Network, "CFNet - willSendRequest(conn=%p, handle=%p) (%s)", conn, handle, handle->request().url().string().utf8().data());
- ResourceRequest request(cfRequest);
+ ResourceRequest request;
+ if (cfRedirectResponse) {
+ CFHTTPMessageRef httpMessage = CFURLResponseGetHTTPResponse(cfRedirectResponse);
+ if (httpMessage && CFHTTPMessageGetResponseStatusCode(httpMessage) == 307) {
+ RetainPtr<CFStringRef> originalMethod(AdoptCF, handle->request().httpMethod().createCFString());
+ RetainPtr<CFStringRef> newMethod(AdoptCF, CFURLRequestCopyHTTPRequestMethod(cfRequest));
+ if (CFStringCompareWithOptions(originalMethod.get(), newMethod.get(), CFRangeMake(0, CFStringGetLength(originalMethod.get())), kCFCompareCaseInsensitive)) {
+ RetainPtr<CFMutableURLRequestRef> mutableRequest(AdoptCF, CFURLRequestCreateMutableCopy(0, cfRequest));
+ CFURLRequestSetHTTPRequestMethod(mutableRequest.get(), originalMethod.get());
+ request = mutableRequest.get();
+ }
+ }
+ }
+ if (request.isNull())
+ request = cfRequest;
+
handle->willSendRequest(request, cfRedirectResponse);
+ if (request.isNull())
+ return 0;
+
cfRequest = request.cfURLRequest();
CFRetain(cfRequest);
@@ -554,7 +572,7 @@ bool ResourceHandle::loadsBlocked()
return false;
}
-bool ResourceHandle::willLoadFromCache(ResourceRequest& request)
+bool ResourceHandle::willLoadFromCache(ResourceRequest& request, Frame* frame)
{
request.setCachePolicy(ReturnCacheDataDontLoad);
diff --git a/WebCore/platform/network/curl/ResourceHandleCurl.cpp b/WebCore/platform/network/curl/ResourceHandleCurl.cpp
index a2e692c..a6f5dca 100644
--- a/WebCore/platform/network/curl/ResourceHandleCurl.cpp
+++ b/WebCore/platform/network/curl/ResourceHandleCurl.cpp
@@ -179,7 +179,7 @@ void ResourceHandle::setDefersLoading(bool defers)
#endif
}
-bool ResourceHandle::willLoadFromCache(ResourceRequest&)
+bool ResourceHandle::willLoadFromCache(ResourceRequest&, Frame*)
{
notImplemented();
return false;
diff --git a/WebCore/platform/network/curl/ResourceHandleManager.cpp b/WebCore/platform/network/curl/ResourceHandleManager.cpp
index c61ad4f..2aa286a 100644
--- a/WebCore/platform/network/curl/ResourceHandleManager.cpp
+++ b/WebCore/platform/network/curl/ResourceHandleManager.cpp
@@ -582,7 +582,7 @@ void ResourceHandleManager::initializeHandle(ResourceHandle* job)
KURL kurl = job->request().url();
// Remove any fragment part, otherwise curl will send it as part of the request.
- kurl.removeRef();
+ kurl.removeFragmentIdentifier();
ResourceHandleInternal* d = job->getInternal();
String url = kurl.string();
diff --git a/WebCore/platform/network/curl/ResourceHandleManager.h b/WebCore/platform/network/curl/ResourceHandleManager.h
index f3ad234..d38e577 100644
--- a/WebCore/platform/network/curl/ResourceHandleManager.h
+++ b/WebCore/platform/network/curl/ResourceHandleManager.h
@@ -32,6 +32,11 @@
#include "Timer.h"
#include "ResourceHandleClient.h"
+#if PLATFORM(WIN)
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
#include <curl/curl.h>
#include <wtf/Vector.h>
diff --git a/WebCore/platform/network/mac/FormDataStreamMac.mm b/WebCore/platform/network/mac/FormDataStreamMac.mm
index 94fdb25..a8d6887 100644
--- a/WebCore/platform/network/mac/FormDataStreamMac.mm
+++ b/WebCore/platform/network/mac/FormDataStreamMac.mm
@@ -32,6 +32,7 @@
#import "FormDataStreamMac.h"
#import "CString.h"
+#import "FileSystem.h"
#import "FormData.h"
#import "ResourceHandle.h"
#import "ResourceHandleClient.h"
@@ -360,11 +361,9 @@ void setHTTPBody(NSMutableURLRequest *request, PassRefPtr<FormData> formData)
if (element.m_type == FormDataElement::data)
length += element.m_data.size();
else {
- const String& filename = element.m_shouldGenerateFile ? element.m_generatedFilename : element.m_filename;
- struct stat sb;
- int statResult = stat(filename.utf8().data(), &sb);
- if (statResult == 0 && (sb.st_mode & S_IFMT) == S_IFREG)
- length += sb.st_size;
+ long long fileSize;
+ if (getFileSize(element.m_shouldGenerateFile ? element.m_generatedFilename : element.m_filename, fileSize))
+ length += fileSize;
}
}
diff --git a/WebCore/platform/network/mac/ResourceHandleMac.mm b/WebCore/platform/network/mac/ResourceHandleMac.mm
index 3af1b97..db76d1a 100644
--- a/WebCore/platform/network/mac/ResourceHandleMac.mm
+++ b/WebCore/platform/network/mac/ResourceHandleMac.mm
@@ -46,10 +46,6 @@
#import "WebCoreURLResponse.h"
#import <wtf/UnusedParam.h>
-#ifndef BUILDING_ON_TIGER
-#import <objc/objc-class.h>
-#endif
-
#ifdef BUILDING_ON_TIGER
typedef int NSInteger;
#endif
@@ -93,9 +89,6 @@ using namespace WebCore;
static NSString *WebCoreSynchronousLoaderRunLoopMode = @"WebCoreSynchronousLoaderRunLoopMode";
-static IMP oldNSURLResponseMIMETypeIMP = 0;
-static NSString *webNSURLResponseMIMEType(id, SEL);
-
#endif
namespace WebCore {
@@ -182,11 +175,18 @@ bool ResourceHandle::start(Frame* frame)
if (!ResourceHandle::didSendBodyDataDelegateExists())
associateStreamWithResourceHandle([d->m_request.nsURLRequest() HTTPBodyStream], this);
+#ifdef BUILDING_ON_TIGER
+ // A conditional request sent by WebCore (e.g. to update appcache) can be for a resource that is not cacheable by NSURLConnection,
+ // which can get confused and fail to load it in this case.
+ if (d->m_request.isConditional())
+ d->m_request.setCachePolicy(ReloadIgnoringCacheData);
+#endif
+
d->m_needsSiteSpecificQuirks = frame->settings() && frame->settings()->needsSiteSpecificQuirks();
NSURLConnection *connection;
- if (d->m_shouldContentSniff)
+ if (d->m_shouldContentSniff || frame->settings()->localFileContentSniffingEnabled())
#ifdef BUILDING_ON_TIGER
connection = [[NSURLConnection alloc] initWithRequest:d->m_request.nsURLRequest() delegate:delegate];
#else
@@ -348,7 +348,7 @@ bool ResourceHandle::loadsBlocked()
#endif
}
-bool ResourceHandle::willLoadFromCache(ResourceRequest& request)
+bool ResourceHandle::willLoadFromCache(ResourceRequest& request, Frame*)
{
#ifndef BUILDING_ON_TIGER
request.setCachePolicy(ReturnCacheDataDontLoad);
@@ -567,6 +567,15 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
LOG(Network, "Handle %p delegate connection:%p willSendRequest:%@ redirectResponse:%p", m_handle, connection, [newRequest description], redirectResponse);
+ if (redirectResponse && [redirectResponse isKindOfClass:[NSHTTPURLResponse class]] && [(NSHTTPURLResponse *)redirectResponse statusCode] == 307) {
+ String originalMethod = m_handle->request().httpMethod();
+ if (!equalIgnoringCase(originalMethod, String([newRequest HTTPMethod]))) {
+ NSMutableURLRequest *mutableRequest = [newRequest mutableCopy];
+ [mutableRequest setHTTPMethod:originalMethod];
+ newRequest = [mutableRequest autorelease];
+ }
+ }
+
CallbackGuard guard;
ResourceRequest request = newRequest;
m_handle->willSendRequest(request, redirectResponse);
@@ -626,19 +635,13 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
{
UNUSED_PARAM(connection);
- LOG(Network, "Handle %p delegate connection:%p didReceiveResponse:%p (HTTP status %d)", m_handle, connection, r, [r respondsToSelector:@selector(statusCode)] ? [(id)r statusCode] : 0);
+ LOG(Network, "Handle %p delegate connection:%p didReceiveResponse:%p (HTTP status %d, MIMEType '%s', reported MIMEType '%s')", m_handle, connection, r, [r respondsToSelector:@selector(statusCode)] ? [(id)r statusCode] : 0, [[r MIMEType] UTF8String], [[r _webcore_reportedMIMEType] UTF8String]);
if (!m_handle || !m_handle->client())
return;
CallbackGuard guard;
-#ifndef BUILDING_ON_TIGER
- if (!oldNSURLResponseMIMETypeIMP) {
- Method nsURLResponseMIMETypeMethod = class_getInstanceMethod(objc_getClass("NSURLResponse"), @selector(MIMEType));
- ASSERT(nsURLResponseMIMETypeMethod);
- oldNSURLResponseMIMETypeIMP = method_setImplementation(nsURLResponseMIMETypeMethod, (IMP)webNSURLResponseMIMEType);
- }
-#endif
+ swizzleMIMETypeMethodIfNecessary();
if ([m_handle->request().nsURLRequest() _propertyForKey:@"ForceHTMLMIMEType"])
[r _setMIMEType:@"text/html"];
@@ -653,7 +656,7 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
DEFINE_STATIC_LOCAL(const String, wmlExt, (".wml"));
if (path.endsWith(wmlExt, false)) {
static NSString* defaultMIMETypeString = [(NSString*) defaultMIMEType() retain];
- if ([[r _webcore_MIMEType] isEqualToString:defaultMIMETypeString])
+ if ([[r MIMEType] isEqualToString:defaultMIMETypeString])
[r _setMIMEType:@"text/vnd.wap.wml"];
}
}
@@ -1008,14 +1011,4 @@ void ResourceHandle::receivedCancellation(const AuthenticationChallenge& challen
@end
-static NSString *webNSURLResponseMIMEType(id self, SEL _cmd)
-{
- ASSERT(oldNSURLResponseMIMETypeIMP);
- if (NSString *result = oldNSURLResponseMIMETypeIMP(self, _cmd))
- return result;
-
- static NSString *defaultMIMETypeString = [(NSString *)defaultMIMEType() retain];
- return defaultMIMETypeString;
-}
-
#endif
diff --git a/WebCore/platform/network/mac/ResourceResponseMac.mm b/WebCore/platform/network/mac/ResourceResponseMac.mm
index 60a4dc6..9b507e6 100644
--- a/WebCore/platform/network/mac/ResourceResponseMac.mm
+++ b/WebCore/platform/network/mac/ResourceResponseMac.mm
@@ -69,7 +69,7 @@ void ResourceResponse::platformLazyInit()
}
m_url = [m_nsResponse.get() URL];
- m_mimeType = [m_nsResponse.get() _webcore_MIMEType];
+ m_mimeType = [m_nsResponse.get() MIMEType];
m_expectedContentLength = [m_nsResponse.get() expectedContentLength];
m_textEncodingName = [m_nsResponse.get() textEncodingName];
m_suggestedFilename = [m_nsResponse.get() suggestedFilename];
@@ -86,20 +86,8 @@ void ResourceResponse::platformLazyInit()
NSEnumerator *e = [headers keyEnumerator];
while (NSString *name = [e nextObject])
m_httpHeaderFields.set(name, [headers objectForKey:name]);
- } else {
+ } else
m_httpStatusCode = 0;
-
-#ifndef BUILDING_ON_TIGER
- // FIXME: This is a work around for <rdar://problem/5230154> (-[NSURLConnection initWithRequest:delegate:]
- // is returning incorrect MIME type for local .xhtml files) which is only required in Leopard.
- if (m_url.isLocalFile() && m_mimeType == "text/html") {
- const String& path = m_url.path();
- DEFINE_STATIC_LOCAL(const String, xhtmlExt, (".xhtml"));
- if (path.endsWith(xhtmlExt, false))
- m_mimeType = "application/xhtml+xml";
- }
-#endif
- }
}
bool ResourceResponse::platformCompare(const ResourceResponse& a, const ResourceResponse& b)
diff --git a/WebCore/platform/network/mac/WebCoreURLResponse.h b/WebCore/platform/network/mac/WebCoreURLResponse.h
index a06ab70..0a9a7c4 100644
--- a/WebCore/platform/network/mac/WebCoreURLResponse.h
+++ b/WebCore/platform/network/mac/WebCoreURLResponse.h
@@ -26,9 +26,8 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-// FIXME: This is a workaround for <rdar://problem/5321972> REGRESSION: Plain text document from HTTP server detected
-// as application/octet-stream
-
@interface NSURLResponse (WebCoreURLResponse)
-- (NSString *)_webcore_MIMEType;
+-(NSString *)_webcore_reportedMIMEType;
@end
+
+void swizzleMIMETypeMethodIfNecessary();
diff --git a/WebCore/platform/network/mac/WebCoreURLResponse.mm b/WebCore/platform/network/mac/WebCoreURLResponse.mm
index b8843af..f025769 100644
--- a/WebCore/platform/network/mac/WebCoreURLResponse.mm
+++ b/WebCore/platform/network/mac/WebCoreURLResponse.mm
@@ -27,10 +27,20 @@
*/
#import "config.h"
-
#import "WebCoreURLResponse.h"
+#import "FoundationExtras.h"
+#import "MIMETypeRegistry.h"
+#import <objc/objc-class.h>
+#import <wtf/Assertions.h>
+#import <wtf/RetainPtr.h>
+
#ifndef BUILDING_ON_TIGER
+// <rdar://problem/5321972> Plain text document from HTTP server detected as application/octet-stream
+// When we sniff a resource as application/octet-stream but the http response headers had "text/plain",
+// we have a hard decision to make about which of the two generic MIME types to go with.
+// When the URL's extension is a known binary type, we'll go with application/octet-stream.
+// Otherwise, we'll trust the server.
static NSSet *createBinaryExtensionsSet()
{
return [[NSSet alloc] initWithObjects:
@@ -88,6 +98,7 @@ static NSSet *createBinaryExtensionsSet()
@"jpgv",
@"jpm",
@"kar",
+ @"kmz",
@"lha",
@"lrm",
@"lzh",
@@ -189,33 +200,247 @@ static NSSet *createBinaryExtensionsSet()
}
#endif
-@implementation NSURLResponse (WebCoreURLResponse)
+// <rdar://problem/7007389> CoreTypes UTI map is missing 100+ file extensions that GateKeeper knew about
+// When we disabled content sniffing for file URLs we caused problems with these 100+ extensions that CoreTypes
+// doesn't know about.
+// If CoreTypes is ever brought up to speed we can remove this table and associated code.
+static NSDictionary *createExtensionToMIMETypeMap()
+{
+ return [[NSDictionary alloc] initWithObjectsAndKeys:
+ @"application/postscript", @"ai",
+ @"text/plain", @"asc",
+ @"application/x-bcpio", @"bcpio",
+ @"image/bmp", @"bmp",
+ @"application/x-netcdf", @"cdf",
+ @"application/octet-stream", @"class",
+ @"application/x-gzip", @"cpgz",
+ @"application/x-cpio", @"cpio",
+ @"application/mac-compactpro", @"cpt",
+ @"application/x-csh", @"csh",
+ @"text/css", @"css",
+ @"application/x-director", @"dcr",
+ @"application/x-director", @"dir",
+ @"application/x-diskcopy", @"dmg",
+ @"application/octet-stream", @"dms",
+ @"application/x-dvi", @"dvi",
+ @"application/x-director", @"dxr",
+ @"application/postscript", @"eps",
+ @"text/x-setext", @"etx",
+ @"application/andrew-inset", @"ez",
+ @"application/vnd.fdf", @"fdf",
+ @"application/octet-stream", @"fla",
+ @"application/x-filemaker", @"fp",
+ @"application/x-filemaker", @"fp2",
+ @"application/x-filemaker", @"fp3",
+ @"application/x-filemaker", @"fp4",
+ @"application/x-filemaker", @"fp5",
+ @"application/x-filemaker", @"fp6",
+ @"application/x-hdf", @"hdf",
+ @"x-conference/x-cooltalk", @"ice",
+ @"image/x-icon", @"ico",
+ @"text/calendar", @"ics",
+ @"image/ief", @"ief",
+ @"model/iges", @"iges",
+ @"model/iges", @"igs",
+ @"application/octet-stream", @"iso",
+ @"text/html", @"jhtml",
+ @"application/x-latex", @"latex",
+ @"application/octet-stream", @"lha",
+ @"application/octet-stream", @"lzh",
+ @"audio/x-mpegurl", @"m3u",
+ @"audio/x-m4p", @"m4p",
+ @"image/x-macpaint", @"mac",
+ @"application/x-troff-man", @"man",
+ @"application/x-troff-me", @"me",
+ @"model/mesh", @"mesh",
+ @"application/vnd.mif", @"mif",
+ @"video/x-sgi-movie", @"movie",
+ @"audio/mpeg", @"mp2",
+ @"audio/mpeg", @"mpga",
+ @"application/x-troff-ms", @"ms",
+ @"model/mesh", @"msh",
+ @"video/vnd.mpegurl", @"mxu",
+ @"application/x-netcdf", @"nc",
+ @"application/oda", @"oda",
+ @"image/x-portable-bitmap", @"pbm",
+ @"image/x-pcx", @"pcx",
+ @"chemical/x-pdb", @"pdb",
+ @"image/x-portable-graymap", @"pgm",
+ @"application/x-chess-pgn", @"pgn",
+ @"audio/scpls", @"pls",
+ @"image/x-portable-anymap", @"pnm",
+ @"image/x-macpaint", @"pnt",
+ @"image/x-macpaint", @"pntg",
+ @"image/x-portable-pixmap", @"ppm",
+ @"image/x-cmu-raster", @"ras",
+ @"image/x-rgb", @"rgb",
+ @"application/x-troff", @"roff",
+ @"audio/x-pn-realaudio-plugin", @"rpm",
+ @"text/richtext", @"rtx",
+ @"text/sgml", @"sgm",
+ @"text/sgml", @"sgml",
+ @"application/x-sh", @"sh",
+ @"application/x-shar", @"shar",
+ @"model/mesh", @"silo",
+ @"application/x-koan", @"skd",
+ @"application/x-koan", @"skm",
+ @"application/x-koan", @"skp",
+ @"application/x-koan", @"skt",
+ @"application/x-diskcopy", @"smi",
+ @"application/octet-stream", @"so",
+ @"application/x-futuresplash", @"spl",
+ @"application/x-wais-source", @"src",
+ @"application/x-sv4cpio", @"sv4cpio",
+ @"application/x-sv4crc", @"sv4crc",
+ @"application/x-shockwave-flash", @"swf",
+ @"application/x-troff", @"t",
+ @"image/x-targa", @"targa",
+ @"application/x-tcl", @"tcl",
+ @"application/x-tex", @"tex",
+ @"application/x-texinfo", @"texi",
+ @"application/x-texinfo", @"texinfo",
+ @"application/x-gzip", @"tgz",
+ @"application/x-bittorrent", @"torrent",
+ @"application/x-troff", @"tr",
+ @"text/tab-separated-values", @"tsv",
+ @"application/x-ustar", @"ustar",
+ @"application/x-cdlink", @"vcd",
+ @"model/vrml", @"vrml",
+ @"image/vnd.wap.wbmp", @"wbmp",
+ @"application/vnd.wap.wbxml", @"wbxml",
+ @"application/x-webarchive", @"webarchive",
+ @"application/x-ms-wmd", @"wmd",
+ @"text/vnd.wap.wml", @"wml",
+ @"application/vnd.wap.wmlc", @"wmlc",
+ @"text/vnd.wap.wmlscript", @"wmls",
+ @"application/vnd.wap.wmlscriptc", @"wmlsc",
+ @"model/vrml", @"wrl",
+ @"application/vnd.adobe.xdp+xml", @"xdp",
+ @"application/vnd.adobe.xfd+xml", @"xfd",
+ @"application/vnd.adobe.xfdf", @"xfdf",
+ @"image/x-xpixmap", @"xpm",
+ @"text/xml", @"xsl",
+ @"image/x-xwindowdump", @"xwd",
+ @"chemical/x-xyz", @"xyz",
+ @"application/x-compress", @"z",
+ nil
+ ];
+}
-- (NSString *)_webcore_MIMEType
+static IMP oldNSURLResponseMIMETypeIMP = 0;
+static NSString *webNSURLResponseMIMEType(id, SEL);
+
+void swizzleMIMETypeMethodIfNecessary()
{
- NSString *MIMEType = [self MIMEType];
-#ifdef BUILDING_ON_LEOPARD
- // Workaround for <rdar://problem/5539824>
- if ([MIMEType isEqualToString:@"text/xml"])
- return @"application/xml";
+ if (!oldNSURLResponseMIMETypeIMP) {
+ Method nsURLResponseMIMETypeMethod = class_getInstanceMethod([NSURLResponse class], @selector(MIMEType));
+ ASSERT(nsURLResponseMIMETypeMethod);
+#ifdef BUILDING_ON_TIGER
+ oldNSURLResponseMIMETypeIMP = nsURLResponseMIMETypeMethod->method_imp;
+ nsURLResponseMIMETypeMethod->method_imp = (IMP)webNSURLResponseMIMEType;
+#else
+ oldNSURLResponseMIMETypeIMP = method_setImplementation(nsURLResponseMIMETypeMethod, (IMP)webNSURLResponseMIMEType);
#endif
- return MIMEType;
+ }
}
-@end
+static NSString *mimeTypeFromUTITree(CFStringRef uti)
+{
+ // Check if this UTI has a MIME type.
+ RetainPtr<CFStringRef> mimeType(AdoptCF, UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType));
+ if (mimeType)
+ return (NSString *)HardAutorelease(mimeType.releaseRef());
+
+ // If not, walk the ancestory of this UTI via its "ConformsTo" tags and return the first MIME type we find.
+ RetainPtr<CFDictionaryRef> decl(AdoptCF, UTTypeCopyDeclaration(uti));
+ if (!decl)
+ return nil;
+ CFTypeRef value = CFDictionaryGetValue(decl.get(), kUTTypeConformsToKey);
+ if (!value)
+ return nil;
+ CFTypeID typeID = CFGetTypeID(value);
+
+ if (typeID == CFStringGetTypeID())
+ return mimeTypeFromUTITree((CFStringRef)value);
-@implementation NSHTTPURLResponse (WebCoreURLResponse)
+ if (typeID == CFArrayGetTypeID()) {
+ CFArrayRef newTypes = (CFArrayRef)value;
+ CFIndex count = CFArrayGetCount(newTypes);
+ for (CFIndex i = 0; i < count; ++i) {
+ CFTypeRef object = CFArrayGetValueAtIndex(newTypes, i);
+ if (CFGetTypeID(object) != CFStringGetTypeID())
+ continue;
-- (NSString *)_webcore_MIMEType
+ if (NSString *mimeType = mimeTypeFromUTITree((CFStringRef)object))
+ return mimeType;
+ }
+ }
+
+ return nil;
+}
+
+static NSString *webNSURLResponseMIMEType(id self, SEL _cmd)
{
- NSString *MIMEType = [self MIMEType];
+ ASSERT(oldNSURLResponseMIMETypeIMP);
+ NSString *result = oldNSURLResponseMIMETypeIMP(self, _cmd);
+
+#ifdef BUILDING_ON_TIGER
+ // When content sniffing is disabled, Tiger's CFNetwork automatically returns application/octet-stream for certain
+ // extensions even when scouring the UTI maps would end up with a better result, so we'll give a chance for that to happen.
+ if ([[self URL] isFileURL] && [result caseInsensitiveCompare:@"application/octet-stream"] == NSOrderedSame)
+ result = nil;
+#endif
+
+ if (!result) {
+ NSURL *url = [self URL];
+ if ([url isFileURL]) {
+ if (NSString *extension = [[url path] pathExtension]) {
+ // <rdar://problem/7007389> CoreTypes UTI map is missing 100+ file extensions that GateKeeper knew about
+ // When this radar is resolved, we can remove this file:// url specific code.
+ static NSDictionary *extensionMap = createExtensionToMIMETypeMap();
+ result = [extensionMap objectForKey:[extension lowercaseString]];
+
+ if (!result) {
+ // If the Gatekeeper-based map doesn't have a MIME type, we'll try to figure out what it should be by
+ // looking up the file extension in the UTI maps.
+ RetainPtr<CFStringRef> uti(AdoptCF, UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (CFStringRef)extension, 0));
+ result = mimeTypeFromUTITree(uti.get());
+ }
+ }
+ }
+ }
+
+ if (!result) {
+ static NSString *defaultMIMETypeString = [(NSString *)WebCore::defaultMIMEType() retain];
+ result = defaultMIMETypeString;
+ }
+
#ifndef BUILDING_ON_TIGER
- if ([MIMEType isEqualToString:@"application/octet-stream"] && [[[self allHeaderFields] objectForKey:@"Content-Type"] hasPrefix:@"text/plain"]) {
+ // <rdar://problem/5321972> Plain text document from HTTP server detected as application/octet-stream
+ // Make the best guess when deciding between "generic binary" and "generic text" using a table of known binary MIME types.
+ if ([result isEqualToString:@"application/octet-stream"] && [self respondsToSelector:@selector(allHeaderFields)] && [[[self allHeaderFields] objectForKey:@"Content-Type"] hasPrefix:@"text/plain"]) {
static NSSet *binaryExtensions = createBinaryExtensionsSet();
- return [binaryExtensions containsObject:[[[self suggestedFilename] pathExtension] lowercaseString]] ? MIMEType : @"text/plain";
+ if (![binaryExtensions containsObject:[[[self suggestedFilename] pathExtension] lowercaseString]])
+ result = @"text/plain";
}
+
+#endif
+
+#ifdef BUILDING_ON_LEOPARD
+ // Workaround for <rdar://problem/5539824>
+ if ([result isEqualToString:@"text/xml"])
+ result = @"application/xml";
#endif
- return MIMEType;
+
+ return result;
+}
+
+@implementation NSURLResponse (WebCoreURLResponse)
+
+-(NSString *)_webcore_reportedMIMEType
+{
+ swizzleMIMETypeMethodIfNecessary();
+ return oldNSURLResponseMIMETypeIMP(self, @selector(_webcore_realMIMEType));
}
@end
diff --git a/WebCore/platform/network/qt/QNetworkReplyHandler.cpp b/WebCore/platform/network/qt/QNetworkReplyHandler.cpp
index 06b60bf..898e5f4 100644
--- a/WebCore/platform/network/qt/QNetworkReplyHandler.cpp
+++ b/WebCore/platform/network/qt/QNetworkReplyHandler.cpp
@@ -162,9 +162,21 @@ QNetworkReplyHandler::QNetworkReplyHandler(ResourceHandle* handle, LoadMode load
void QNetworkReplyHandler::setLoadMode(LoadMode mode)
{
- m_loadMode = mode;
- if (m_loadMode == LoadNormal)
- sendQueuedItems();
+ // https://bugs.webkit.org/show_bug.cgi?id=26556
+ // We cannot call sendQueuedItems() from here, because the signal that
+ // caused us to get into deferred mode, might not be processed yet.
+ switch (mode) {
+ case LoadNormal:
+ m_loadMode = LoadResuming;
+ emit processQueuedItems();
+ break;
+ case LoadDeferred:
+ m_loadMode = LoadDeferred;
+ break;
+ case LoadResuming:
+ Q_ASSERT(0); // should never happen
+ break;
+ };
}
void QNetworkReplyHandler::abort()
@@ -194,8 +206,8 @@ QNetworkReply* QNetworkReplyHandler::release()
void QNetworkReplyHandler::finish()
{
- m_shouldFinish = (m_loadMode == LoadDeferred);
- if (m_loadMode == LoadDeferred)
+ m_shouldFinish = (m_loadMode != LoadNormal);
+ if (m_shouldFinish)
return;
sendResponseIfNeeded();
@@ -213,9 +225,11 @@ void QNetworkReplyHandler::finish()
resetState();
start();
} else if (m_reply->error() != QNetworkReply::NoError
- // a web page that returns 403/404 can still have content
+ // a web page that returns 401/403/404 can still have content
&& m_reply->error() != QNetworkReply::ContentOperationNotPermittedError
- && m_reply->error() != QNetworkReply::ContentNotFoundError) {
+ && m_reply->error() != QNetworkReply::ContentNotFoundError
+ && m_reply->error() != QNetworkReply::AuthenticationRequiredError
+ && m_reply->error() != QNetworkReply::ProxyAuthenticationRequiredError) {
QUrl url = m_reply->url();
ResourceError error(url.host(), m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(),
url.toString(), m_reply->errorString());
@@ -230,8 +244,8 @@ void QNetworkReplyHandler::finish()
void QNetworkReplyHandler::sendResponseIfNeeded()
{
- m_shouldSendResponse = (m_loadMode == LoadDeferred);
- if (m_loadMode == LoadDeferred)
+ m_shouldSendResponse = (m_loadMode != LoadNormal);
+ if (m_shouldSendResponse)
return;
if (m_responseSent || !m_resourceHandle)
@@ -314,8 +328,8 @@ void QNetworkReplyHandler::sendResponseIfNeeded()
void QNetworkReplyHandler::forwardData()
{
- m_shouldForwardData = (m_loadMode == LoadDeferred);
- if (m_loadMode == LoadDeferred)
+ m_shouldForwardData = (m_loadMode != LoadNormal);
+ if (m_shouldForwardData)
return;
sendResponseIfNeeded();
@@ -399,6 +413,8 @@ void QNetworkReplyHandler::start()
connect(m_reply, SIGNAL(readyRead()),
this, SLOT(forwardData()), Qt::QueuedConnection);
+ connect(this, SIGNAL(processQueuedItems()),
+ this, SLOT(sendQueuedItems()), Qt::QueuedConnection);
}
void QNetworkReplyHandler::resetState()
@@ -413,7 +429,9 @@ void QNetworkReplyHandler::resetState()
void QNetworkReplyHandler::sendQueuedItems()
{
- Q_ASSERT(m_loadMode == LoadNormal);
+ if (m_loadMode != LoadResuming)
+ return;
+ m_loadMode = LoadNormal;
if (m_shouldStart)
start();
diff --git a/WebCore/platform/network/qt/QNetworkReplyHandler.h b/WebCore/platform/network/qt/QNetworkReplyHandler.h
index 3de6d88..f88ce8a 100644
--- a/WebCore/platform/network/qt/QNetworkReplyHandler.h
+++ b/WebCore/platform/network/qt/QNetworkReplyHandler.h
@@ -43,7 +43,8 @@ class QNetworkReplyHandler : public QObject
public:
enum LoadMode {
LoadNormal,
- LoadDeferred
+ LoadDeferred,
+ LoadResuming
};
QNetworkReplyHandler(ResourceHandle *handle, LoadMode);
@@ -55,15 +56,18 @@ public:
QNetworkReply* release();
+signals:
+ void processQueuedItems();
+
private slots:
void finish();
void sendResponseIfNeeded();
void forwardData();
+ void sendQueuedItems();
private:
void start();
void resetState();
- void sendQueuedItems();
QNetworkReply* m_reply;
ResourceHandle* m_resourceHandle;
diff --git a/WebCore/platform/network/qt/ResourceHandleQt.cpp b/WebCore/platform/network/qt/ResourceHandleQt.cpp
index c5816a4..f4c30c9 100644
--- a/WebCore/platform/network/qt/ResourceHandleQt.cpp
+++ b/WebCore/platform/network/qt/ResourceHandleQt.cpp
@@ -35,6 +35,7 @@
#include "ResourceHandleClient.h"
#include "ResourceHandleInternal.h"
#include "qwebpage_p.h"
+#include "qwebframe_p.h"
#include "ChromeClientQt.h"
#include "FrameLoaderClientQt.h"
#include "Page.h"
@@ -42,6 +43,9 @@
#include "NotImplemented.h"
+#if QT_VERSION >= 0x040500
+#include <QAbstractNetworkCache>
+#endif
#include <QCoreApplication>
#include <QUrl>
#if QT_VERSION >= 0x040400
@@ -73,11 +77,10 @@ private:
ResourceResponse m_response;
ResourceError m_error;
Vector<char> m_data;
- bool m_finished;
+ QEventLoop m_eventLoop;
};
WebCoreSynchronousLoader::WebCoreSynchronousLoader()
- : m_finished(false)
{
}
@@ -93,19 +96,18 @@ void WebCoreSynchronousLoader::didReceiveData(ResourceHandle*, const char* data,
void WebCoreSynchronousLoader::didFinishLoading(ResourceHandle*)
{
- m_finished = true;
+ m_eventLoop.exit();
}
void WebCoreSynchronousLoader::didFail(ResourceHandle*, const ResourceError& error)
{
m_error = error;
- m_finished = true;
+ m_eventLoop.exit();
}
void WebCoreSynchronousLoader::waitForCompletion()
{
- while (!m_finished)
- QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
+ m_eventLoop.exec(QEventLoop::ExcludeUserInputEvents);
}
ResourceHandleInternal::~ResourceHandleInternal()
@@ -154,10 +156,28 @@ bool ResourceHandle::loadsBlocked()
return false;
}
-bool ResourceHandle::willLoadFromCache(ResourceRequest& request)
+bool ResourceHandle::willLoadFromCache(ResourceRequest& request, Frame* frame)
{
- notImplemented();
+ if (!frame)
+ return false;
+
+#if QT_VERSION >= 0x040500
+ QNetworkAccessManager* manager = QWebFramePrivate::kit(frame)->page()->networkAccessManager();
+ QAbstractNetworkCache* cache = manager->cache();
+
+ if (!cache)
+ return false;
+
+ QNetworkCacheMetaData data = cache->metaData(request.url());
+ if (data.isValid()) {
+ request.setCachePolicy(ReturnCacheDataDontLoad);
+ return true;
+ }
+
return false;
+#else
+ return false;
+#endif
}
bool ResourceHandle::supportsBufferedData()
diff --git a/WebCore/platform/network/soup/ResourceHandleSoup.cpp b/WebCore/platform/network/soup/ResourceHandleSoup.cpp
index 6be13e2..4a22d8a 100644
--- a/WebCore/platform/network/soup/ResourceHandleSoup.cpp
+++ b/WebCore/platform/network/soup/ResourceHandleSoup.cpp
@@ -6,6 +6,7 @@
* Copyright (C) 2009 Gustavo Noronha Silva <gns@gnome.org>
* Copyright (C) 2009 Christian Dywan <christian@imendio.com>
* Copyright (C) 2009 Igalia S.L.
+ * Copyright (C) 2009 John Kjellberg <john.kjellberg@power.alstom.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -55,7 +56,7 @@
namespace WebCore {
-class WebCoreSynchronousLoader : public ResourceHandleClient, Noncopyable {
+class WebCoreSynchronousLoader : public ResourceHandleClient, public Noncopyable {
public:
WebCoreSynchronousLoader(ResourceError&, ResourceResponse &, Vector<char>&);
~WebCoreSynchronousLoader();
@@ -118,6 +119,8 @@ void WebCoreSynchronousLoader::run()
}
static void cleanupGioOperation(ResourceHandleInternal* handle);
+static bool startData(ResourceHandle* handle, String urlString);
+static bool startGio(ResourceHandle* handle, KURL url);
ResourceHandleInternal::~ResourceHandleInternal()
{
@@ -150,39 +153,7 @@ static void fillResponseFromMessage(SoupMessage* msg, ResourceResponse* response
while (soup_message_headers_iter_next(&iter, &name, &value))
response->setHTTPHeaderField(name, value);
- GHashTable* contentTypeParameters = 0;
- String contentType = soup_message_headers_get_content_type(msg->response_headers, &contentTypeParameters);
-
- // When the server sends multiple Content-Type headers, soup will
- // give us their values concatenated with commas as a separator;
- // we need to handle this and use only one value. We use the first
- // value, and add all the parameters, afterwards, if any.
- Vector<String> contentTypes;
- contentType.split(',', true, contentTypes);
- contentType = contentTypes[0];
-
- if (contentTypeParameters) {
- GString* parametersString = g_string_new(0);
- GHashTableIter hashTableIter;
- const char* hashKey;
- const char* hashValue;
-
- g_hash_table_iter_init(&hashTableIter, contentTypeParameters);
- while (g_hash_table_iter_next(&hashTableIter, reinterpret_cast<void**>(const_cast<char**>(&hashKey)), reinterpret_cast<void**>(const_cast<char**>(&hashValue)))) {
- // Work-around bug in soup which causes a crash;
- // See http://bugzilla.gnome.org/show_bug.cgi?id=577728
- if (!hashValue)
- hashValue = "";
-
- g_string_append(parametersString, "; ");
- soup_header_g_string_append_param(parametersString, hashKey, hashValue);
- }
- contentType += String(parametersString->str);
-
- g_string_free(parametersString, true);
- g_hash_table_destroy(contentTypeParameters);
- }
-
+ String contentType = soup_message_headers_get_one(msg->response_headers, "Content-Type");
response->setMimeType(extractMIMETypeFromMediaType(contentType));
char* uri = soup_uri_to_string(soup_message_get_uri(msg), false);
@@ -211,15 +182,6 @@ static void restartedCallback(SoupMessage* msg, gpointer data)
g_free(uri);
KURL newURL = KURL(handle->request().url(), location);
- // FIXME: This is needed because some servers use broken URIs in
- // their Location header, when redirecting, such as URIs with
- // white spaces instead of %20; this should be fixed in soup, in
- // the future, and this work-around removed.
- // See http://bugzilla.gnome.org/show_bug.cgi?id=575378.
- SoupURI* soup_uri = soup_uri_new(newURL.string().utf8().data());
- soup_message_set_uri(msg, soup_uri);
- soup_uri_free(soup_uri);
-
ResourceRequest request = handle->request();
ResourceResponse response;
request.setURL(newURL);
@@ -242,21 +204,38 @@ static void gotHeadersCallback(SoupMessage* msg, gpointer data)
// we got, when we finish downloading.
soup_message_body_set_accumulate(msg->response_body, FALSE);
+ if (msg->status_code == SOUP_STATUS_NOT_MODIFIED) {
+ RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(data);
+ if (!handle)
+ return;
+ ResourceHandleInternal* d = handle->getInternal();
+ if (d->m_cancelled)
+ return;
+ ResourceHandleClient* client = handle->client();
+ if (!client)
+ return;
+
+ fillResponseFromMessage(msg, &d->m_response);
+ client->didReceiveResponse(handle.get(), d->m_response);
+ }
+}
+
+static void contentSniffedCallback(SoupMessage* msg, const char* sniffedType, GHashTable *params, gpointer data)
+{
+ if (sniffedType) {
+ const char* officialType = soup_message_headers_get_one(msg->response_headers, "Content-Type");
+
+ if (!officialType || strcmp(officialType, sniffedType))
+ soup_message_headers_set_content_type(msg->response_headers, sniffedType, params);
+ }
+
// The 304 status code (SOUP_STATUS_NOT_MODIFIED) needs to be fed
// into WebCore, as opposed to other kinds of redirections, which
// are handled by soup directly, so we special-case it here and in
// gotChunk.
if (SOUP_STATUS_IS_TRANSPORT_ERROR(msg->status_code)
- || (SOUP_STATUS_IS_REDIRECTION(msg->status_code) && (msg->status_code != SOUP_STATUS_NOT_MODIFIED)))
- return;
-
- // We still don't know anything about Content-Type, so we will try
- // sniffing the contents of the file, and then report that we got
- // headers; we will not do content sniffing for 304 responses,
- // though, since they do not have a body.
- const char* contentType = soup_message_headers_get_content_type(msg->response_headers, NULL);
- if ((msg->status_code != SOUP_STATUS_NOT_MODIFIED)
- && (!contentType || !g_ascii_strcasecmp(contentType, "text/plain")))
+ || (SOUP_STATUS_IS_REDIRECTION(msg->status_code) && (msg->status_code != SOUP_STATUS_NOT_MODIFIED))
+ || (msg->status_code == SOUP_STATUS_UNAUTHORIZED))
return;
RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(data);
@@ -270,7 +249,6 @@ static void gotHeadersCallback(SoupMessage* msg, gpointer data)
return;
fillResponseFromMessage(msg, &d->m_response);
- d->m_reportedHeaders = true;
client->didReceiveResponse(handle.get(), d->m_response);
}
@@ -291,21 +269,6 @@ static void gotChunkCallback(SoupMessage* msg, SoupBuffer* chunk, gpointer data)
if (!client)
return;
- if (!d->m_reportedHeaders) {
- gboolean uncertain;
- char* contentType = g_content_type_guess(d->m_request.url().lastPathComponent().utf8().data(), reinterpret_cast<const guchar*>(chunk->data), chunk->length, &uncertain);
- soup_message_headers_set_content_type(msg->response_headers, contentType, NULL);
- g_free(contentType);
-
- fillResponseFromMessage(msg, &d->m_response);
- client->didReceiveResponse(handle.get(), d->m_response);
- d->m_reportedHeaders = true;
-
- // the didReceiveResponse call above may have cancelled the request
- if (d->m_cancelled)
- return;
- }
-
client->didReceiveData(handle.get(), chunk->data, chunk->length, false);
}
@@ -328,10 +291,12 @@ static void finishedCallback(SoupSession *session, SoupMessage* msg, gpointer da
return;
if (SOUP_STATUS_IS_TRANSPORT_ERROR(msg->status_code)) {
+ char* uri = soup_uri_to_string(soup_message_get_uri(msg), false);
ResourceError error(g_quark_to_string(SOUP_HTTP_ERROR),
msg->status_code,
- soup_uri_to_string(soup_message_get_uri(msg), false),
+ uri,
String::fromUTF8(msg->reason_phrase));
+ g_free(uri);
client->didFail(handle.get(), error);
return;
}
@@ -428,13 +393,15 @@ static gboolean parseDataUrl(gpointer callback_data)
return false;
}
-bool ResourceHandle::startData(String urlString)
+static bool startData(ResourceHandle* handle, String urlString)
{
- ResourceHandleInternal* d = this->getInternal();
+ ASSERT(handle);
+
+ ResourceHandleInternal* d = handle->getInternal();
// If parseDataUrl is called synchronously the job is not yet effectively started
// and webkit won't never know that the data has been parsed even didFinishLoading is called.
- d->m_idleHandler = g_idle_add(parseDataUrl, this);
+ d->m_idleHandler = g_idle_add(parseDataUrl, handle);
return true;
}
@@ -463,17 +430,31 @@ static void ensureSessionIsInitialized(SoupSession* session)
g_object_set_data(G_OBJECT(session), "webkit-init", reinterpret_cast<void*>(0xdeadbeef));
}
-bool ResourceHandle::startHttp(String urlString)
+static bool startHttp(ResourceHandle* handle, String urlString)
{
- SoupSession* session = defaultSession();
+ ASSERT(handle);
+
+ SoupSession* session = handle->defaultSession();
ensureSessionIsInitialized(session);
- d->m_msg = request().toSoupMessage();
- g_signal_connect(d->m_msg, "restarted", G_CALLBACK(restartedCallback), this);
- g_signal_connect(d->m_msg, "got-headers", G_CALLBACK(gotHeadersCallback), this);
- g_signal_connect(d->m_msg, "got-chunk", G_CALLBACK(gotChunkCallback), this);
+ ResourceHandleInternal* d = handle->getInternal();
+
+ d->m_msg = handle->request().toSoupMessage();
+ if (!d->m_msg) {
+ ResourceError resourceError(g_quark_to_string(SOUP_HTTP_ERROR),
+ SOUP_STATUS_MALFORMED,
+ urlString,
+ handle->request().httpMethod());
+ d->client()->didFail(handle, resourceError);
+ return false;
+ }
+
+ g_signal_connect(d->m_msg, "restarted", G_CALLBACK(restartedCallback), handle);
+ g_signal_connect(d->m_msg, "got-headers", G_CALLBACK(gotHeadersCallback), handle);
+ g_signal_connect(d->m_msg, "content-sniffed", G_CALLBACK(contentSniffedCallback), handle);
+ g_signal_connect(d->m_msg, "got-chunk", G_CALLBACK(gotChunkCallback), handle);
- g_object_set_data(G_OBJECT(d->m_msg), "resourceHandle", reinterpret_cast<void*>(this));
+ g_object_set_data(G_OBJECT(d->m_msg), "resourceHandle", reinterpret_cast<void*>(handle));
FormData* httpBody = d->m_request.httpBody();
if (httpBody && !httpBody->isEmpty()) {
@@ -516,10 +497,10 @@ bool ResourceHandle::startHttp(String urlString)
String::fromUTF8(error->message));
g_error_free(error);
- d->client()->didFail(this, resourceError);
+ d->client()->didFail(handle, resourceError);
g_signal_handlers_disconnect_matched(d->m_msg, G_SIGNAL_MATCH_DATA,
- 0, 0, 0, 0, this);
+ 0, 0, 0, 0, handle);
g_object_unref(d->m_msg);
d->m_msg = 0;
@@ -528,7 +509,12 @@ bool ResourceHandle::startHttp(String urlString)
SoupBuffer* soupBuffer = soup_buffer_new_with_owner(g_mapped_file_get_contents(fileMapping),
g_mapped_file_get_length(fileMapping),
- fileMapping, reinterpret_cast<GDestroyNotify>(g_mapped_file_free));
+ fileMapping,
+#if GLIB_CHECK_VERSION(2, 21, 3)
+ reinterpret_cast<GDestroyNotify>(g_mapped_file_unref));
+#else
+ reinterpret_cast<GDestroyNotify>(g_mapped_file_free));
+#endif
soup_message_body_append_buffer(d->m_msg->request_body, soupBuffer);
soup_buffer_free(soupBuffer);
}
@@ -537,7 +523,7 @@ bool ResourceHandle::startHttp(String urlString)
}
// balanced by a deref() in finishedCallback, which should always run
- ref();
+ handle->ref();
// FIXME: For now, we cannot accept content encoded in anything
// other than identity, so force servers to do it our way. When
@@ -549,7 +535,7 @@ bool ResourceHandle::startHttp(String urlString)
// keep our own ref, because after queueing the message, the
// session owns the initial reference.
g_object_ref(d->m_msg);
- soup_session_queue_message(session, d->m_msg, finishedCallback, this);
+ soup_session_queue_message(session, d->m_msg, finishedCallback, handle);
return true;
}
@@ -574,14 +560,14 @@ bool ResourceHandle::start(Frame* frame)
d->m_frame = frame;
if (equalIgnoringCase(protocol, "data"))
- return startData(urlString);
+ return startData(this, urlString);
- if ((equalIgnoringCase(protocol, "http") || equalIgnoringCase(protocol, "https")) && SOUP_URI_VALID_FOR_HTTP(soup_uri_new(urlString.utf8().data())))
- return startHttp(urlString);
+ if (equalIgnoringCase(protocol, "http") || equalIgnoringCase(protocol, "https"))
+ return startHttp(this, urlString);
if (equalIgnoringCase(protocol, "file") || equalIgnoringCase(protocol, "ftp") || equalIgnoringCase(protocol, "ftps"))
// FIXME: should we be doing any other protocols here?
- return startGio(url);
+ return startGio(this, url);
// Error must not be reported immediately
this->scheduleFailure(InvalidURLFailure);
@@ -620,7 +606,7 @@ bool ResourceHandle::loadsBlocked()
return false;
}
-bool ResourceHandle::willLoadFromCache(ResourceRequest&)
+bool ResourceHandle::willLoadFromCache(ResourceRequest&, Frame*)
{
// Not having this function means that we'll ask the user about re-posting a form
// even when we go back to a page that's still in the cache.
@@ -697,10 +683,12 @@ static void readCallback(GObject* source, GAsyncResult* res, gpointer)
gssize bytesRead = g_input_stream_read_finish(d->m_inputStream, res, &error);
if (error) {
+ char* uri = g_file_get_uri(d->m_gfile);
ResourceError resourceError(g_quark_to_string(G_IO_ERROR),
error->code,
- g_file_get_uri(d->m_gfile),
+ uri,
error ? String::fromUTF8(error->message) : String());
+ g_free(uri);
g_error_free(error);
cleanupGioOperation(d);
client->didFail(handle.get(), resourceError);
@@ -743,11 +731,12 @@ static void openCallback(GObject* source, GAsyncResult* res, gpointer)
GError *error = 0;
GFileInputStream* in = g_file_read_finish(G_FILE(source), res, &error);
if (error) {
+ char* uri = g_file_get_uri(d->m_gfile);
ResourceError resourceError(g_quark_to_string(G_IO_ERROR),
error->code,
- g_file_get_uri(d->m_gfile),
+ uri,
error ? String::fromUTF8(error->message) : String());
-
+ g_free(uri);
g_error_free(error);
cleanupGioOperation(d);
client->didFail(handle, resourceError);
@@ -794,10 +783,12 @@ static void queryInfoCallback(GObject* source, GAsyncResult* res, gpointer)
// server (and then keep track of the fact that we mounted it,
// and set a timeout to unmount it later after it's been idle
// for a while).
+ char* uri = g_file_get_uri(d->m_gfile);
ResourceError resourceError(g_quark_to_string(G_IO_ERROR),
error->code,
- g_file_get_uri(d->m_gfile),
+ uri,
error ? String::fromUTF8(error->message) : String());
+ g_free(uri);
g_error_free(error);
cleanupGioOperation(d);
client->didFail(handle, resourceError);
@@ -807,10 +798,12 @@ static void queryInfoCallback(GObject* source, GAsyncResult* res, gpointer)
if (g_file_info_get_file_type(info) != G_FILE_TYPE_REGULAR) {
// FIXME: what if the URI points to a directory? Should we
// generate a listing? How? What do other backends do here?
+ char* uri = g_file_get_uri(d->m_gfile);
ResourceError resourceError(g_quark_to_string(G_IO_ERROR),
G_IO_ERROR_FAILED,
- g_file_get_uri(d->m_gfile),
+ uri,
String());
+ g_free(uri);
cleanupGioOperation(d);
client->didFail(handle, resourceError);
return;
@@ -828,21 +821,24 @@ static void queryInfoCallback(GObject* source, GAsyncResult* res, gpointer)
g_file_read_async(d->m_gfile, G_PRIORITY_DEFAULT, d->m_cancellable,
openCallback, 0);
}
-
-bool ResourceHandle::startGio(KURL url)
+static bool startGio(ResourceHandle* handle, KURL url)
{
- if (request().httpMethod() != "GET" && request().httpMethod() != "POST") {
+ ASSERT(handle);
+
+ ResourceHandleInternal* d = handle->getInternal();
+
+ if (handle->request().httpMethod() != "GET" && handle->request().httpMethod() != "POST") {
ResourceError error(g_quark_to_string(SOUP_HTTP_ERROR),
SOUP_STATUS_METHOD_NOT_ALLOWED,
- url.string(), request().httpMethod());
- d->client()->didFail(this, error);
+ url.string(), handle->request().httpMethod());
+ d->client()->didFail(handle, error);
return false;
}
// GIO doesn't know how to handle refs and queries, so remove them
// TODO: use KURL.fileSystemPath after KURLGtk and FileSystemGtk are
// using GIO internally, and providing URIs instead of file paths
- url.removeRef();
+ url.removeFragmentIdentifier();
url.setQuery(String());
url.setPort(0);
@@ -855,7 +851,7 @@ bool ResourceHandle::startGio(KURL url)
else
#endif
d->m_gfile = g_file_new_for_uri(url.string().utf8().data());
- g_object_set_data(G_OBJECT(d->m_gfile), "webkit-resource", this);
+ g_object_set_data(G_OBJECT(d->m_gfile), "webkit-resource", handle);
d->m_cancellable = g_cancellable_new();
g_file_query_info_async(d->m_gfile,
G_FILE_ATTRIBUTE_STANDARD_TYPE ","