summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/network
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/network')
-rw-r--r--WebCore/platform/network/FormData.cpp6
-rw-r--r--WebCore/platform/network/FormData.h8
-rw-r--r--WebCore/platform/network/HTTPHeaderMap.cpp2
-rw-r--r--WebCore/platform/network/HTTPParsers.cpp9
-rw-r--r--WebCore/platform/network/ResourceErrorBase.cpp17
-rw-r--r--WebCore/platform/network/ResourceErrorBase.h7
-rw-r--r--WebCore/platform/network/ResourceHandle.h12
-rw-r--r--WebCore/platform/network/ResourceHandleClient.h6
-rw-r--r--WebCore/platform/network/ResourceHandleInternal.h13
-rw-r--r--WebCore/platform/network/ResourceRequestBase.cpp23
-rw-r--r--WebCore/platform/network/ResourceRequestBase.h12
-rw-r--r--WebCore/platform/network/ResourceResponseBase.cpp4
-rw-r--r--WebCore/platform/network/ResourceResponseBase.h9
-rw-r--r--WebCore/platform/network/cf/FormDataStreamCFNet.cpp88
-rw-r--r--WebCore/platform/network/cf/ResourceHandleCFNet.cpp93
-rw-r--r--WebCore/platform/network/cf/ResourceRequestCFNet.h2
-rw-r--r--WebCore/platform/network/cf/ResourceResponse.h12
-rw-r--r--WebCore/platform/network/chromium/ResourceRequest.h53
-rw-r--r--WebCore/platform/network/curl/ResourceHandleManager.cpp4
-rw-r--r--WebCore/platform/network/mac/FormDataStreamMac.mm2
-rw-r--r--WebCore/platform/network/mac/ResourceErrorMac.mm7
-rw-r--r--WebCore/platform/network/mac/ResourceRequestMac.mm4
-rw-r--r--WebCore/platform/network/mac/ResourceResponse.h12
-rw-r--r--WebCore/platform/network/qt/QNetworkReplyHandler.cpp4
-rw-r--r--WebCore/platform/network/soup/CookieJarSoup.cpp33
-rw-r--r--WebCore/platform/network/soup/CookieJarSoup.h3
-rw-r--r--WebCore/platform/network/soup/ResourceHandleSoup.cpp497
-rw-r--r--WebCore/platform/network/win/CookieJarCFNetWin.cpp24
28 files changed, 618 insertions, 348 deletions
diff --git a/WebCore/platform/network/FormData.cpp b/WebCore/platform/network/FormData.cpp
index 3cac168..af3b7f0 100644
--- a/WebCore/platform/network/FormData.cpp
+++ b/WebCore/platform/network/FormData.cpp
@@ -29,7 +29,8 @@
namespace WebCore {
inline FormData::FormData()
- : m_hasGeneratedFiles(false)
+ : m_identifier(0)
+ , m_hasGeneratedFiles(false)
, m_alwaysStream(false)
{
}
@@ -37,6 +38,7 @@ inline FormData::FormData()
inline FormData::FormData(const FormData& data)
: RefCounted<FormData>()
, m_elements(data.m_elements)
+ , m_identifier(data.m_identifier)
, m_hasGeneratedFiles(false)
, m_alwaysStream(false)
{
@@ -98,7 +100,7 @@ PassRefPtr<FormData> FormData::deepCopy() const
formData->m_alwaysStream = m_alwaysStream;
size_t n = m_elements.size();
- formData->m_elements.reserveCapacity(n);
+ formData->m_elements.reserveInitialCapacity(n);
for (size_t i = 0; i < n; ++i) {
const FormDataElement& e = m_elements[i];
switch (e.m_type) {
diff --git a/WebCore/platform/network/FormData.h b/WebCore/platform/network/FormData.h
index 5998b1b..7278f2e 100644
--- a/WebCore/platform/network/FormData.h
+++ b/WebCore/platform/network/FormData.h
@@ -86,11 +86,17 @@ public:
bool alwaysStream() const { return m_alwaysStream; }
void setAlwaysStream(bool alwaysStream) { m_alwaysStream = alwaysStream; }
+ // Identifies a particular form submission instance. A value of 0 is used
+ // to indicate an unspecified identifier.
+ void setIdentifier(int64_t identifier) { m_identifier = identifier; }
+ int64_t identifier() const { return m_identifier; }
+
private:
FormData();
FormData(const FormData&);
-
+
Vector<FormDataElement> m_elements;
+ int64_t m_identifier;
bool m_hasGeneratedFiles;
bool m_alwaysStream;
};
diff --git a/WebCore/platform/network/HTTPHeaderMap.cpp b/WebCore/platform/network/HTTPHeaderMap.cpp
index aa9c5fa..ff470a0 100644
--- a/WebCore/platform/network/HTTPHeaderMap.cpp
+++ b/WebCore/platform/network/HTTPHeaderMap.cpp
@@ -41,7 +41,7 @@ namespace WebCore {
auto_ptr<CrossThreadHTTPHeaderMapData> HTTPHeaderMap::copyData() const
{
auto_ptr<CrossThreadHTTPHeaderMapData> data(new CrossThreadHTTPHeaderMapData());
- data->reserveCapacity(size());
+ data->reserveInitialCapacity(size());
HTTPHeaderMap::const_iterator end_it = end();
for (HTTPHeaderMap::const_iterator it = begin(); it != end_it; ++it) {
diff --git a/WebCore/platform/network/HTTPParsers.cpp b/WebCore/platform/network/HTTPParsers.cpp
index 0858fc9..f36e9fb 100644
--- a/WebCore/platform/network/HTTPParsers.cpp
+++ b/WebCore/platform/network/HTTPParsers.cpp
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
* Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -131,18 +132,18 @@ String filenameFromHTTPContentDisposition(const String& value)
String extractMIMETypeFromMediaType(const String& mediaType)
{
- String mimeType;
+ Vector<UChar, 64> mimeType;
unsigned length = mediaType.length();
+ mimeType.reserveCapacity(length);
for (unsigned offset = 0; offset < length; offset++) {
UChar c = mediaType[offset];
if (c == ';')
break;
else if (isSpaceOrNewline(c)) // FIXME: This seems wrong, " " is an invalid MIME type character according to RFC 2045. bug 8644
continue;
- // FIXME: This is a very slow way to build a string, given WebCore::String's implementation.
- mimeType += String(&c, 1);
+ mimeType.append(c);
}
- return mimeType;
+ return String(mimeType.data(), mimeType.size());
}
String extractCharsetFromMediaType(const String& mediaType)
diff --git a/WebCore/platform/network/ResourceErrorBase.cpp b/WebCore/platform/network/ResourceErrorBase.cpp
index 1ea35b0..370650f 100644
--- a/WebCore/platform/network/ResourceErrorBase.cpp
+++ b/WebCore/platform/network/ResourceErrorBase.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
+ * Copyright (C) 2009 Google Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,6 +29,20 @@
namespace WebCore {
+ResourceError ResourceErrorBase::copy() const
+{
+ lazyInit();
+
+ ResourceError errorCopy;
+ errorCopy.m_domain = m_domain.copy();
+ errorCopy.m_errorCode = m_errorCode;
+ errorCopy.m_failingURL = m_failingURL.copy();
+ errorCopy.m_localizedDescription = m_localizedDescription.copy();
+ errorCopy.m_isNull = m_isNull;
+ errorCopy.m_isCancellation = m_isCancellation;
+ return errorCopy;
+}
+
void ResourceErrorBase::lazyInit() const
{
const_cast<ResourceError*>(static_cast<const ResourceError*>(this))->platformLazyInit();
@@ -59,4 +74,4 @@ bool ResourceErrorBase::compare(const ResourceError& a, const ResourceError& b)
return platformCompare(a, b);
}
-}
+} // namespace WebCore
diff --git a/WebCore/platform/network/ResourceErrorBase.h b/WebCore/platform/network/ResourceErrorBase.h
index 4631324..237db9e 100644
--- a/WebCore/platform/network/ResourceErrorBase.h
+++ b/WebCore/platform/network/ResourceErrorBase.h
@@ -34,6 +34,9 @@ class ResourceError;
class ResourceErrorBase {
public:
+ // Makes a deep copy. Useful for when you need to use a ResourceError on another thread.
+ ResourceError copy() const;
+
bool isNull() const { return m_isNull; }
const String& domain() const { lazyInit(); return m_domain; }
@@ -44,7 +47,7 @@ public:
void setIsCancellation(bool isCancellation) { m_isCancellation = isCancellation; }
bool isCancellation() const { return m_isCancellation; }
- static bool compare(const ResourceError& a, const ResourceError& b);
+ static bool compare(const ResourceError&, const ResourceError&);
protected:
ResourceErrorBase()
@@ -85,4 +88,4 @@ inline bool operator!=(const ResourceError& a, const ResourceError& b) { return
} // namespace WebCore
-#endif // ResourceErrorBase_h_
+#endif // ResourceErrorBase_h
diff --git a/WebCore/platform/network/ResourceHandle.h b/WebCore/platform/network/ResourceHandle.h
index c981483..e3038ca 100644
--- a/WebCore/platform/network/ResourceHandle.h
+++ b/WebCore/platform/network/ResourceHandle.h
@@ -30,6 +30,10 @@
#include "HTTPHeaderMap.h"
#include <wtf/OwnPtr.h>
+#if USE(SOUP)
+typedef struct _SoupSession SoupSession;
+#endif
+
#if PLATFORM(CF)
typedef const struct __CFData * CFDataRef;
#endif
@@ -79,7 +83,7 @@ class KURL;
class ResourceError;
class ResourceHandleClient;
class ResourceHandleInternal;
-class ResourceRequest;
+struct ResourceRequest;
class ResourceResponse;
class SchedulePair;
class SharedBuffer;
@@ -159,6 +163,10 @@ public:
ResourceHandleInternal* getInternal() { return d.get(); }
#endif
+#if USE(SOUP)
+ static SoupSession* defaultSession();
+#endif
+
// Used to work around the fact that you don't get any more NSURLConnection callbacks until you return from the one you're in.
static bool loadsBlocked();
@@ -179,7 +187,7 @@ private:
#if USE(SOUP)
bool startData(String urlString);
bool startHttp(String urlString);
- bool startGio(String urlString);
+ bool startGio(KURL url);
#endif
void scheduleFailure(FailureType);
diff --git a/WebCore/platform/network/ResourceHandleClient.h b/WebCore/platform/network/ResourceHandleClient.h
index 3668d88..54c27d2 100644
--- a/WebCore/platform/network/ResourceHandleClient.h
+++ b/WebCore/platform/network/ResourceHandleClient.h
@@ -32,6 +32,7 @@
#if USE(CFNETWORK)
#include <ConditionalMacros.h>
+#include <CFNetwork/CFURLCachePriv.h>
#include <CFNetwork/CFURLResponsePriv.h>
#endif
@@ -49,7 +50,7 @@ namespace WebCore {
class KURL;
class ResourceHandle;
class ResourceError;
- class ResourceRequest;
+ struct ResourceRequest;
class ResourceResponse;
enum CacheStoragePolicy {
@@ -86,6 +87,9 @@ namespace WebCore {
virtual NSCachedURLResponse* willCacheResponse(ResourceHandle*, NSCachedURLResponse* response) { return response; }
virtual void willStopBufferingData(ResourceHandle*, const char*, int) { }
#endif
+#if USE(CFNETWORK)
+ virtual bool shouldCacheResponse(ResourceHandle*, CFCachedURLResponseRef response) { return true; }
+#endif
};
}
diff --git a/WebCore/platform/network/ResourceHandleInternal.h b/WebCore/platform/network/ResourceHandleInternal.h
index cc90cc8..c592a1a 100644
--- a/WebCore/platform/network/ResourceHandleInternal.h
+++ b/WebCore/platform/network/ResourceHandleInternal.h
@@ -47,6 +47,7 @@
#if USE(SOUP)
#include <libsoup/soup.h>
+class Frame;
#endif
#if PLATFORM(QT)
@@ -116,13 +117,15 @@ namespace WebCore {
#if USE(SOUP)
, m_msg(0)
, m_cancelled(false)
+ , m_reportedHeaders(false)
, m_gfile(0)
- , m_input_stream(0)
+ , m_inputStream(0)
, m_cancellable(0)
, m_buffer(0)
- , m_bufsize(0)
+ , m_bufferSize(0)
, m_total(0)
, m_idleHandler(0)
+ , m_frame(0)
#endif
#if PLATFORM(QT)
, m_job(0)
@@ -190,12 +193,14 @@ namespace WebCore {
SoupMessage* m_msg;
ResourceResponse m_response;
bool m_cancelled;
+ bool m_reportedHeaders;
GFile* m_gfile;
- GInputStream* m_input_stream;
+ GInputStream* m_inputStream;
GCancellable* m_cancellable;
char* m_buffer;
- gsize m_bufsize, m_total;
+ gsize m_bufferSize, m_total;
guint m_idleHandler;
+ Frame* m_frame;
#endif
#if PLATFORM(QT)
#if QT_VERSION < 0x040400
diff --git a/WebCore/platform/network/ResourceRequestBase.cpp b/WebCore/platform/network/ResourceRequestBase.cpp
index 15469a0..fd27718 100644
--- a/WebCore/platform/network/ResourceRequestBase.cpp
+++ b/WebCore/platform/network/ResourceRequestBase.cpp
@@ -76,7 +76,7 @@ auto_ptr<CrossThreadResourceRequestData> ResourceRequestBase::copyData() const
data->m_httpMethod = httpMethod().copy();
data->m_httpHeaders.adopt(httpHeaderFields().copyData());
- data->m_responseContentDispositionEncodingFallbackArray.reserveCapacity(m_responseContentDispositionEncodingFallbackArray.size());
+ data->m_responseContentDispositionEncodingFallbackArray.reserveInitialCapacity(m_responseContentDispositionEncodingFallbackArray.size());
size_t encodingArraySize = m_responseContentDispositionEncodingFallbackArray.size();
for (size_t index = 0; index < encodingArraySize; ++index) {
data->m_responseContentDispositionEncodingFallbackArray.append(m_responseContentDispositionEncodingFallbackArray[index].copy());
@@ -130,7 +130,8 @@ void ResourceRequestBase::setCachePolicy(ResourceRequestCachePolicy cachePolicy)
m_cachePolicy = cachePolicy;
- m_platformRequestUpdated = false;
+ if (url().protocolInHTTPFamily())
+ m_platformRequestUpdated = false;
}
double ResourceRequestBase::timeoutInterval() const
@@ -146,7 +147,8 @@ void ResourceRequestBase::setTimeoutInterval(double timeoutInterval)
m_timeoutInterval = timeoutInterval;
- m_platformRequestUpdated = false;
+ if (url().protocolInHTTPFamily())
+ m_platformRequestUpdated = false;
}
const KURL& ResourceRequestBase::mainDocumentURL() const
@@ -178,7 +180,8 @@ void ResourceRequestBase::setHTTPMethod(const String& httpMethod)
m_httpMethod = httpMethod;
- m_platformRequestUpdated = false;
+ if (url().protocolInHTTPFamily())
+ m_platformRequestUpdated = false;
}
const HTTPHeaderMap& ResourceRequestBase::httpHeaderFields() const
@@ -201,7 +204,8 @@ void ResourceRequestBase::setHTTPHeaderField(const AtomicString& name, const Str
m_httpHeaderFields.set(name, value);
- m_platformRequestUpdated = false;
+ if (url().protocolInHTTPFamily())
+ m_platformRequestUpdated = false;
}
void ResourceRequestBase::setResponseContentDispositionEncodingFallbackArray(const String& encoding1, const String& encoding2, const String& encoding3)
@@ -216,7 +220,8 @@ void ResourceRequestBase::setResponseContentDispositionEncodingFallbackArray(con
if (!encoding3.isNull())
m_responseContentDispositionEncodingFallbackArray.append(encoding3);
- m_platformRequestUpdated = false;
+ if (url().protocolInHTTPFamily())
+ m_platformRequestUpdated = false;
}
FormData* ResourceRequestBase::httpBody() const
@@ -232,7 +237,8 @@ void ResourceRequestBase::setHTTPBody(PassRefPtr<FormData> httpBody)
m_httpBody = httpBody;
- m_platformRequestUpdated = false;
+ if (url().protocolInHTTPFamily())
+ m_platformRequestUpdated = false;
}
bool ResourceRequestBase::allowHTTPCookies() const
@@ -248,7 +254,8 @@ void ResourceRequestBase::setAllowHTTPCookies(bool allowHTTPCookies)
m_allowHTTPCookies = allowHTTPCookies;
- m_platformRequestUpdated = false;
+ if (url().protocolInHTTPFamily())
+ m_platformRequestUpdated = false;
}
void ResourceRequestBase::addHTTPHeaderField(const AtomicString& name, const String& value)
diff --git a/WebCore/platform/network/ResourceRequestBase.h b/WebCore/platform/network/ResourceRequestBase.h
index 0f6bb47..4fd57e1 100644
--- a/WebCore/platform/network/ResourceRequestBase.h
+++ b/WebCore/platform/network/ResourceRequestBase.h
@@ -46,7 +46,7 @@ namespace WebCore {
const int unspecifiedTimeoutInterval = INT_MAX;
- class ResourceRequest;
+ struct ResourceRequest;
struct CrossThreadResourceRequestData;
// Do not use this type directly. Use ResourceRequest instead.
@@ -107,12 +107,18 @@ namespace WebCore {
void setAllowHTTPCookies(bool allowHTTPCookies);
bool isConditional() const;
-
+
+ // Whether the associated ResourceHandleClient needs to be notified of
+ // upload progress made for that resource.
+ bool reportUploadProgress() const { return m_reportUploadProgress; }
+ void setReportUploadProgress(bool reportUploadProgress) { m_reportUploadProgress = reportUploadProgress; }
+
protected:
// Used when ResourceRequest is initialized from a platform representation of the request
ResourceRequestBase()
: m_resourceRequestUpdated(false)
, m_platformRequestUpdated(true)
+ , m_reportUploadProgress(false)
{
}
@@ -124,6 +130,7 @@ namespace WebCore {
, m_allowHTTPCookies(true)
, m_resourceRequestUpdated(true)
, m_platformRequestUpdated(false)
+ , m_reportUploadProgress(false)
{
}
@@ -142,6 +149,7 @@ namespace WebCore {
bool m_allowHTTPCookies;
mutable bool m_resourceRequestUpdated;
mutable bool m_platformRequestUpdated;
+ bool m_reportUploadProgress;
private:
const ResourceRequest& asResourceRequest() const;
diff --git a/WebCore/platform/network/ResourceResponseBase.cpp b/WebCore/platform/network/ResourceResponseBase.cpp
index 92ece8c..60c0097 100644
--- a/WebCore/platform/network/ResourceResponseBase.cpp
+++ b/WebCore/platform/network/ResourceResponseBase.cpp
@@ -39,7 +39,7 @@ static void parseCacheControlDirectiveValues(const String& directives, Vector<St
auto_ptr<ResourceResponse> ResourceResponseBase::adopt(auto_ptr<CrossThreadResourceResponseData> data)
{
auto_ptr<ResourceResponse> response(new ResourceResponse());
- response->setUrl(data->m_url);
+ response->setURL(data->m_url);
response->setMimeType(data->m_mimeType);
response->setExpectedContentLength(data->m_expectedContentLength);
response->setTextEncodingName(data->m_textEncodingName);
@@ -94,7 +94,7 @@ const KURL& ResourceResponseBase::url() const
return m_url;
}
-void ResourceResponseBase::setUrl(const KURL& url)
+void ResourceResponseBase::setURL(const KURL& url)
{
lazyInit();
m_isNull = false;
diff --git a/WebCore/platform/network/ResourceResponseBase.h b/WebCore/platform/network/ResourceResponseBase.h
index c06f75b..ff34a26 100644
--- a/WebCore/platform/network/ResourceResponseBase.h
+++ b/WebCore/platform/network/ResourceResponseBase.h
@@ -49,7 +49,7 @@ public:
bool isHTTP() const;
const KURL& url() const;
- void setUrl(const KURL& url);
+ void setURL(const KURL& url);
const String& mimeType() const;
void setMimeType(const String& mimeType);
@@ -97,6 +97,13 @@ public:
return m_cacheControlContainsMustRevalidate;
}
+ // The ResourceResponse subclass may "shadow" this method to provide platform-specific memory usage information
+ unsigned memoryUsage() const
+ {
+ // average size, mostly due to URL and Header Map strings
+ return 1280;
+ }
+
static bool compare(const ResourceResponse& a, const ResourceResponse& b);
protected:
diff --git a/WebCore/platform/network/cf/FormDataStreamCFNet.cpp b/WebCore/platform/network/cf/FormDataStreamCFNet.cpp
index 71fbfe7..3414d90 100644
--- a/WebCore/platform/network/cf/FormDataStreamCFNet.cpp
+++ b/WebCore/platform/network/cf/FormDataStreamCFNet.cpp
@@ -317,8 +317,7 @@ static void formEventCallback(CFReadStreamRef stream, CFStreamEventType type, vo
void setHTTPBody(CFMutableURLRequestRef request, PassRefPtr<FormData> formData)
{
if (!formData) {
- if (wkCanAccessCFURLRequestHTTPBodyParts())
- wkCFURLRequestSetHTTPRequestBodyParts(request, 0);
+ wkCFURLRequestSetHTTPRequestBodyParts(request, 0);
return;
}
@@ -338,52 +337,20 @@ void setHTTPBody(CFMutableURLRequestRef request, PassRefPtr<FormData> formData)
}
}
- if (wkCanAccessCFURLRequestHTTPBodyParts()) {
- RetainPtr<CFMutableArrayRef> array(AdoptCF, CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks));
-
- for (size_t i = 0; i < count; ++i) {
- const FormDataElement& element = formData->elements()[i];
- if (element.m_type == FormDataElement::data) {
- RetainPtr<CFDataRef> data(AdoptCF, CFDataCreate(0, reinterpret_cast<const UInt8*>(element.m_data.data()), element.m_data.size()));
- CFArrayAppendValue(array.get(), data.get());
- } else {
- RetainPtr<CFStringRef> filename(AdoptCF, element.m_filename.createCFString());
- CFArrayAppendValue(array.get(), filename.get());
- }
- }
+ RetainPtr<CFMutableArrayRef> array(AdoptCF, CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks));
- wkCFURLRequestSetHTTPRequestBodyParts(request, array.get());
- return;
- }
-
- // Precompute the content length so CFURLConnection doesn't use chunked mode.
- bool haveLength = true;
- long long length = 0;
for (size_t i = 0; i < count; ++i) {
const FormDataElement& element = formData->elements()[i];
- if (element.m_type == FormDataElement::data)
- length += element.m_data.size();
- else {
- long long size;
- if (getFileSize(element.m_filename, size))
- length += size;
- else
- haveLength = false;
+ if (element.m_type == FormDataElement::data) {
+ RetainPtr<CFDataRef> data(AdoptCF, CFDataCreate(0, reinterpret_cast<const UInt8*>(element.m_data.data()), element.m_data.size()));
+ CFArrayAppendValue(array.get(), data.get());
+ } else {
+ RetainPtr<CFStringRef> filename(AdoptCF, element.m_filename.createCFString());
+ CFArrayAppendValue(array.get(), filename.get());
}
}
- if (haveLength) {
- CFStringRef lengthStr = CFStringCreateWithFormat(0, 0, CFSTR("%lld"), length);
- CFURLRequestSetHTTPHeaderFieldValue(request, CFSTR("Content-Length"), lengthStr);
- CFRelease(lengthStr);
- }
-
- static WCReadStreamCallBacks formDataStreamCallbacks =
- { 1, formCreate, formFinalize, 0, formOpen, 0, formRead, 0, formCanRead, formClose, 0, 0, 0, formSchedule, formUnschedule };
-
- CFReadStreamRef stream = CFReadStreamCreate(0, (CFReadStreamCallBacks *)&formDataStreamCallbacks, formData.releaseRef());
- CFURLRequestSetHTTPRequestBodyStream(request, stream);
- CFRelease(stream);
+ wkCFURLRequestSetHTTPRequestBodyParts(request, array.get());
}
PassRefPtr<FormData> httpBodyFromRequest(CFURLRequestRef request)
@@ -391,28 +358,23 @@ PassRefPtr<FormData> httpBodyFromRequest(CFURLRequestRef request)
if (RetainPtr<CFDataRef> bodyData = CFURLRequestCopyHTTPRequestBody(request))
return FormData::create(CFDataGetBytePtr(bodyData.get()), CFDataGetLength(bodyData.get()));
- if (wkCanAccessCFURLRequestHTTPBodyParts()) {
- if (RetainPtr<CFArrayRef> bodyParts = wkCFURLRequestCopyHTTPRequestBodyParts(request)) {
- RefPtr<FormData> formData = FormData::create();
-
- CFIndex count = CFArrayGetCount(bodyParts.get());
- for (CFIndex i = 0; i < count; i++) {
- CFTypeRef bodyPart = CFArrayGetValueAtIndex(bodyParts.get(), i);
- CFTypeID typeID = CFGetTypeID(bodyPart);
- if (typeID == CFStringGetTypeID()) {
- String filename = (CFStringRef)bodyPart;
- formData->appendFile(filename);
- } else if (typeID == CFDataGetTypeID()) {
- CFDataRef data = (CFDataRef)bodyPart;
- formData->appendData(CFDataGetBytePtr(data), CFDataGetLength(data));
- } else
- ASSERT_NOT_REACHED();
- }
- return formData.release();
+ if (RetainPtr<CFArrayRef> bodyParts = wkCFURLRequestCopyHTTPRequestBodyParts(request)) {
+ RefPtr<FormData> formData = FormData::create();
+
+ CFIndex count = CFArrayGetCount(bodyParts.get());
+ for (CFIndex i = 0; i < count; i++) {
+ CFTypeRef bodyPart = CFArrayGetValueAtIndex(bodyParts.get(), i);
+ CFTypeID typeID = CFGetTypeID(bodyPart);
+ if (typeID == CFStringGetTypeID()) {
+ String filename = (CFStringRef)bodyPart;
+ formData->appendFile(filename);
+ } else if (typeID == CFDataGetTypeID()) {
+ CFDataRef data = (CFDataRef)bodyPart;
+ formData->appendData(CFDataGetBytePtr(data), CFDataGetLength(data));
+ } else
+ ASSERT_NOT_REACHED();
}
- } else {
- if (RetainPtr<CFReadStreamRef> bodyStream = CFURLRequestCopyHTTPRequestBodyStream(request))
- return getStreamFormDatas().get(bodyStream.get());
+ return formData.release();
}
// FIXME: what to do about arbitrary body streams?
diff --git a/WebCore/platform/network/cf/ResourceHandleCFNet.cpp b/WebCore/platform/network/cf/ResourceHandleCFNet.cpp
index a4000a3..2dcbbed 100644
--- a/WebCore/platform/network/cf/ResourceHandleCFNet.cpp
+++ b/WebCore/platform/network/cf/ResourceHandleCFNet.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2004, 2005, 2006, 2007, 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
@@ -53,51 +53,6 @@
namespace WebCore {
-static HMODULE findCFNetworkModule()
-{
- if (HMODULE module = GetModuleHandleA("CFNetwork"))
- return module;
- return GetModuleHandleA("CFNetwork_debug");
-}
-
-static DWORD cfNetworkVersion()
-{
- HMODULE cfNetworkModule = findCFNetworkModule();
- WCHAR filename[MAX_PATH];
- GetModuleFileName(cfNetworkModule, filename, MAX_PATH);
- DWORD handle;
- DWORD versionInfoSize = GetFileVersionInfoSize(filename, &handle);
- Vector<BYTE> versionInfo(versionInfoSize);
- GetFileVersionInfo(filename, handle, versionInfoSize, versionInfo.data());
- VS_FIXEDFILEINFO* fixedFileInfo;
- UINT fixedFileInfoLength;
- VerQueryValue(versionInfo.data(), TEXT("\\"), reinterpret_cast<LPVOID*>(&fixedFileInfo), &fixedFileInfoLength);
- return fixedFileInfo->dwProductVersionMS;
-}
-
-static CFIndex highestSupportedCFURLConnectionClientVersion()
-{
- const DWORD firstCFNetworkVersionWithConnectionClientV2 = 0x000101a8; // 1.424
- const DWORD firstCFNetworkVersionWithConnectionClientV3 = 0x000101ad; // 1.429
-
-#ifndef _CFURLConnectionClientV2Present
- return 1;
-#else
-
- DWORD version = cfNetworkVersion();
- if (version < firstCFNetworkVersionWithConnectionClientV2)
- return 1;
-#ifndef _CFURLConnectionClientV3Present
- return 2;
-#else
-
- if (version < firstCFNetworkVersionWithConnectionClientV3)
- return 2;
- return 3;
-#endif // _CFURLConnectionClientV3Present
-#endif // _CFURLConnectionClientV2Present
-}
-
static HashSet<String>& allowsAnyHTTPSCertificateHosts()
{
static HashSet<String> hosts;
@@ -154,7 +109,6 @@ void didReceiveData(CFURLConnectionRef conn, CFDataRef data, CFIndex originalLen
handle->client()->didReceiveData(handle, (const char*)bytes, length, originalLength);
}
-#ifdef _CFURLConnectionClientV2Present
static void didSendBodyData(CFURLConnectionRef conn, CFIndex bytesWritten, CFIndex totalBytesWritten, CFIndex totalBytesExpectedToWrite, const void *clientInfo)
{
ResourceHandle* handle = (ResourceHandle*)clientInfo;
@@ -162,9 +116,7 @@ static void didSendBodyData(CFURLConnectionRef conn, CFIndex bytesWritten, CFInd
return;
handle->client()->didSendData(handle, totalBytesWritten, totalBytesExpectedToWrite);
}
-#endif
-#ifdef _CFURLConnectionClientV3Present
static Boolean shouldUseCredentialStorageCallback(CFURLConnectionRef conn, const void* clientInfo)
{
ResourceHandle* handle = const_cast<ResourceHandle*>(static_cast<const ResourceHandle*>(clientInfo));
@@ -176,7 +128,6 @@ static Boolean shouldUseCredentialStorageCallback(CFURLConnectionRef conn, const
return handle->shouldUseCredentialStorage();
}
-#endif
void didFinishLoading(CFURLConnectionRef conn, const void* clientInfo)
{
@@ -202,6 +153,9 @@ CFCachedURLResponseRef willCacheResponse(CFURLConnectionRef conn, CFCachedURLRes
{
ResourceHandle* handle = (ResourceHandle*)clientInfo;
+ if (handle->client() && !handle->client()->shouldCacheResponse(handle, cachedResponse))
+ return 0;
+
CacheStoragePolicy policy = static_cast<CacheStoragePolicy>(CFCachedURLResponseGetStoragePolicy(cachedResponse));
if (handle->client())
@@ -297,7 +251,7 @@ void* runLoaderThread(void *unused)
CFRunLoopRef ResourceHandle::loaderRunLoop()
{
if (!loaderRL) {
- createThread(runLoaderThread, 0, "CFNetwork::Loader");
+ createThread(runLoaderThread, 0, "WebCore: CFNetwork Loader");
while (loaderRL == 0) {
// FIXME: sleep 10? that can't be right...
Sleep(10);
@@ -348,20 +302,9 @@ bool ResourceHandle::start(Frame* frame)
RetainPtr<CFURLRequestRef> request(AdoptCF, makeFinalRequest(d->m_request, d->m_shouldContentSniff));
- static CFIndex clientVersion = highestSupportedCFURLConnectionClientVersion();
- CFURLConnectionClient* client;
-#if defined(_CFURLConnectionClientV3Present)
- CFURLConnectionClient_V3 client_V3 = {clientVersion, this, 0, 0, 0, willSendRequest, didReceiveResponse, didReceiveData, NULL, didFinishLoading, didFail, willCacheResponse, didReceiveChallenge, didSendBodyData, shouldUseCredentialStorageCallback, 0};
- client = reinterpret_cast<CFURLConnectionClient*>(&client_V3);
-#elif defined(_CFURLConnectionClientV2Present)
- CFURLConnectionClient_V2 client_V2 = {clientVersion, this, 0, 0, 0, willSendRequest, didReceiveResponse, didReceiveData, NULL, didFinishLoading, didFail, willCacheResponse, didReceiveChallenge, didSendBodyData};
- client = reinterpret_cast<CFURLConnectionClient*>(&client_V2);
-#else
- CFURLConnectionClient client_V1 = {1, this, 0, 0, 0, willSendRequest, didReceiveResponse, didReceiveData, NULL, didFinishLoading, didFail, willCacheResponse, didReceiveChallenge};
- client = &client_V1;
-#endif
-
- d->m_connection.adoptCF(CFURLConnectionCreate(0, request.get(), client));
+ CFURLConnectionClient_V3 client = { 3, this, 0, 0, 0, willSendRequest, didReceiveResponse, didReceiveData, NULL, didFinishLoading, didFail, willCacheResponse, didReceiveChallenge, didSendBodyData, shouldUseCredentialStorageCallback, 0};
+
+ d->m_connection.adoptCF(CFURLConnectionCreate(0, request.get(), reinterpret_cast<CFURLConnectionClient*>(&client)));
CFURLConnectionScheduleWithCurrentMessageQueue(d->m_connection.get());
CFURLConnectionScheduleDownloadWithRunLoop(d->m_connection.get(), loaderRunLoop(), kCFRunLoopDefaultMode);
@@ -519,12 +462,22 @@ bool ResourceHandle::loadsBlocked()
return false;
}
-bool ResourceHandle::willLoadFromCache(ResourceRequest&)
+bool ResourceHandle::willLoadFromCache(ResourceRequest& request)
{
- // 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.
- notImplemented();
- return false;
+ request.setCachePolicy(ReturnCacheDataDontLoad);
+
+ CFURLResponseRef cfResponse = 0;
+ CFErrorRef cfError = 0;
+ RetainPtr<CFURLRequestRef> cfRequest(AdoptCF, makeFinalRequest(request, true));
+ RetainPtr<CFDataRef> data(AdoptCF, CFURLConnectionSendSynchronousRequest(cfRequest.get(), &cfResponse, &cfError, request.timeoutInterval()));
+ bool cached = cfResponse && !cfError;
+
+ if (cfError)
+ CFRelease(cfError);
+ if (cfResponse)
+ CFRelease(cfResponse);
+
+ return cached;
}
} // namespace WebCore
diff --git a/WebCore/platform/network/cf/ResourceRequestCFNet.h b/WebCore/platform/network/cf/ResourceRequestCFNet.h
index e9ebe76..d26072d 100644
--- a/WebCore/platform/network/cf/ResourceRequestCFNet.h
+++ b/WebCore/platform/network/cf/ResourceRequestCFNet.h
@@ -30,7 +30,7 @@ typedef const struct _CFURLRequest* CFURLRequestRef;
namespace WebCore {
- class ResourceRequest;
+ struct ResourceRequest;
void getResourceRequest(ResourceRequest&, CFURLRequestRef);
CFURLRequestRef cfURLRequest(const ResourceRequest&);
diff --git a/WebCore/platform/network/cf/ResourceResponse.h b/WebCore/platform/network/cf/ResourceResponse.h
index e14c79e..04cc82c 100644
--- a/WebCore/platform/network/cf/ResourceResponse.h
+++ b/WebCore/platform/network/cf/ResourceResponse.h
@@ -52,6 +52,18 @@ public:
{
}
+ unsigned memoryUsage() const
+ {
+ // FIXME: Find some programmatic lighweight way to calculate ResourceResponse and associated classes.
+ // This is a rough estimate of resource overhead based on stats collected from the stress test.
+ return 3072;
+ /* 1280 * 2 + // average size of ResourceResponse. Doubled to account for the WebCore copy and the CF copy.
+ // Mostly due to the size of the hash maps, the Header Map strings and the URL.
+ 256 * 2 // Overhead from ResourceRequest, doubled to account for WebCore copy and CF copy.
+ // Mostly due to the URL and Header Map.
+ */
+ }
+
CFURLResponseRef cfURLResponse() const;
private:
diff --git a/WebCore/platform/network/chromium/ResourceRequest.h b/WebCore/platform/network/chromium/ResourceRequest.h
index 76b8b99..b14dba6 100644
--- a/WebCore/platform/network/chromium/ResourceRequest.h
+++ b/WebCore/platform/network/chromium/ResourceRequest.h
@@ -35,7 +35,7 @@ namespace WebCore {
class Frame;
- class ResourceRequest : public ResourceRequestBase {
+ struct ResourceRequest : public ResourceRequestBase {
public:
enum TargetType {
TargetIsMainFrame,
@@ -47,16 +47,16 @@ namespace WebCore {
ResourceRequest(const String& url)
: ResourceRequestBase(KURL(url), UseProtocolCachePolicy)
- , m_frame(0)
- , m_originPid(0)
+ , m_requestorID(0)
+ , m_requestorProcessID(0)
, m_targetType(TargetIsSubResource)
{
}
ResourceRequest(const KURL& url, const CString& securityInfo)
: ResourceRequestBase(url, UseProtocolCachePolicy)
- , m_frame(0)
- , m_originPid(0)
+ , m_requestorID(0)
+ , m_requestorProcessID(0)
, m_targetType(TargetIsSubResource)
, m_securityInfo(securityInfo)
{
@@ -64,16 +64,16 @@ namespace WebCore {
ResourceRequest(const KURL& url)
: ResourceRequestBase(url, UseProtocolCachePolicy)
- , m_frame(0)
- , m_originPid(0)
+ , m_requestorID(0)
+ , m_requestorProcessID(0)
, m_targetType(TargetIsSubResource)
{
}
ResourceRequest(const KURL& url, const String& referrer, ResourceRequestCachePolicy policy = UseProtocolCachePolicy)
: ResourceRequestBase(url, policy)
- , m_frame(0)
- , m_originPid(0)
+ , m_requestorID(0)
+ , m_requestorProcessID(0)
, m_targetType(TargetIsSubResource)
{
setHTTPReferrer(referrer);
@@ -81,26 +81,30 @@ namespace WebCore {
ResourceRequest()
: ResourceRequestBase(KURL(), UseProtocolCachePolicy)
- , m_frame(0)
- , m_originPid(0)
+ , m_requestorID(0)
+ , m_requestorProcessID(0)
, m_targetType(TargetIsSubResource)
{
}
- // Provides context for the resource request.
- Frame* frame() const { return m_frame; }
- void setFrame(Frame* frame) { m_frame = frame; }
+ // Allows the request to be matched up with its requestor.
+ int requestorID() const { return m_requestorID; }
+ void setRequestorID(int requestorID) { m_requestorID = requestorID; }
// What this request is for.
- void setTargetType(TargetType type) { m_targetType = type; }
TargetType targetType() const { return m_targetType; }
-
- // The origin pid is the process id of the process from which this
- // request originated. In the case of out-of-process plugins, this
- // allows to link back the request to the plugin process (as it is
- // processed through a render view process).
- int originPid() const { return m_originPid; }
- void setOriginPid(int originPid) { m_originPid = originPid; }
+ void setTargetType(TargetType type) { m_targetType = type; }
+
+ // The document's policy base url.
+ KURL policyURL() const { return m_policyURL; }
+ void setPolicyURL(const KURL& policyURL) { m_policyURL = policyURL; }
+
+ // The process id of the process from which this request originated. In
+ // the case of out-of-process plugins, this allows to link back the
+ // request to the plugin process (as it is processed through a render
+ // view process).
+ int requestorProcessID() const { return m_requestorProcessID; }
+ void setRequestorProcessID(int requestorProcessID) { m_requestorProcessID = requestorProcessID; }
// Opaque buffer that describes the security state (including SSL
// connection state) for the resource that should be reported when the
@@ -117,10 +121,11 @@ namespace WebCore {
void doUpdatePlatformRequest() {}
void doUpdateResourceRequest() {}
- Frame* m_frame;
- int m_originPid;
+ int m_requestorID;
+ int m_requestorProcessID;
TargetType m_targetType;
CString m_securityInfo;
+ KURL m_policyURL;
};
} // namespace WebCore
diff --git a/WebCore/platform/network/curl/ResourceHandleManager.cpp b/WebCore/platform/network/curl/ResourceHandleManager.cpp
index 6a44233..6f009db 100644
--- a/WebCore/platform/network/curl/ResourceHandleManager.cpp
+++ b/WebCore/platform/network/curl/ResourceHandleManager.cpp
@@ -126,7 +126,7 @@ static size_t writeCallback(void* ptr, size_t size, size_t nmemb, void* data)
if (!d->m_response.responseFired()) {
const char* hdr;
err = curl_easy_getinfo(h, CURLINFO_EFFECTIVE_URL, &hdr);
- d->m_response.setUrl(KURL(hdr));
+ d->m_response.setURL(KURL(hdr));
if (d->client())
d->client()->didReceiveResponse(job, d->m_response);
d->m_response.setResponseFired(true);
@@ -180,7 +180,7 @@ static size_t headerCallback(char* ptr, size_t size, size_t nmemb, void* data)
const char* hdr;
err = curl_easy_getinfo(h, CURLINFO_EFFECTIVE_URL, &hdr);
- d->m_response.setUrl(KURL(hdr));
+ d->m_response.setURL(KURL(hdr));
long httpCode = 0;
err = curl_easy_getinfo(h, CURLINFO_RESPONSE_CODE, &httpCode);
diff --git a/WebCore/platform/network/mac/FormDataStreamMac.mm b/WebCore/platform/network/mac/FormDataStreamMac.mm
index b618949..94fdb25 100644
--- a/WebCore/platform/network/mac/FormDataStreamMac.mm
+++ b/WebCore/platform/network/mac/FormDataStreamMac.mm
@@ -204,7 +204,7 @@ static void* formCreate(CFReadStreamRef stream, void* context)
// Append in reverse order since we remove elements from the end.
size_t size = formData->elements().size();
- newInfo->remainingElements.reserveCapacity(size);
+ newInfo->remainingElements.reserveInitialCapacity(size);
for (size_t i = 0; i < size; ++i)
newInfo->remainingElements.append(formData->elements()[size - i - 1]);
diff --git a/WebCore/platform/network/mac/ResourceErrorMac.mm b/WebCore/platform/network/mac/ResourceErrorMac.mm
index e59eadd..94c2124 100644
--- a/WebCore/platform/network/mac/ResourceErrorMac.mm
+++ b/WebCore/platform/network/mac/ResourceErrorMac.mm
@@ -26,6 +26,7 @@
#import "config.h"
#import "ResourceError.h"
+#import "BlockExceptions.h"
#import "KURL.h"
#import <Foundation/Foundation.h>
@@ -46,8 +47,12 @@ void ResourceError::platformLazyInit()
NSString* failingURLString = [[m_platformError.get() userInfo] valueForKey:@"NSErrorFailingURLStringKey"];
if (!failingURLString)
failingURLString = [[[m_platformError.get() userInfo] valueForKey:@"NSErrorFailingURLKey"] absoluteString];
-
+
+ // Workaround for <rdar://problem/6554067>
+ m_localizedDescription = failingURLString;
+ BEGIN_BLOCK_OBJC_EXCEPTIONS;
m_localizedDescription = [m_platformError.get() _web_localizedDescription];
+ END_BLOCK_OBJC_EXCEPTIONS;
m_dataIsUpToDate = true;
}
diff --git a/WebCore/platform/network/mac/ResourceRequestMac.mm b/WebCore/platform/network/mac/ResourceRequestMac.mm
index a9bbd40..92c37ee 100644
--- a/WebCore/platform/network/mac/ResourceRequestMac.mm
+++ b/WebCore/platform/network/mac/ResourceRequestMac.mm
@@ -119,8 +119,8 @@ void ResourceRequest::doUpdatePlatformRequest()
for (HTTPHeaderMap::const_iterator it = httpHeaderFields().begin(); it != end; ++it)
[nsRequest setValue:it->second forHTTPHeaderField:it->first];
- // The below check can be removed once we require a version of Foundation with -[NSMutableURLRequest setContentDispositionEncodingFallbackArray] method.
- static bool supportsContentDispositionEncodingFallbackArray = [NSMutableURLRequest instancesRespondToSelector:@selector(setContentDispositionEncodingFallbackArray)];
+ // The below check can be removed once we require a version of Foundation with -[NSMutableURLRequest setContentDispositionEncodingFallbackArray:] method.
+ static bool supportsContentDispositionEncodingFallbackArray = [NSMutableURLRequest instancesRespondToSelector:@selector(setContentDispositionEncodingFallbackArray:)];
if (supportsContentDispositionEncodingFallbackArray) {
NSMutableArray *encodingFallbacks = [NSMutableArray array];
unsigned count = m_responseContentDispositionEncodingFallbackArray.size();
diff --git a/WebCore/platform/network/mac/ResourceResponse.h b/WebCore/platform/network/mac/ResourceResponse.h
index b65760c..16b0cbf 100644
--- a/WebCore/platform/network/mac/ResourceResponse.h
+++ b/WebCore/platform/network/mac/ResourceResponse.h
@@ -57,6 +57,18 @@ public:
{
}
+ unsigned memoryUsage() const
+ {
+ // FIXME: Find some programmatic lighweight way to calculate ResourceResponse and associated classes.
+ // This is a rough estimate of resource overhead based on stats collected from the stress test.
+ return 3072;
+ /* 1280 * 2 + // average size of ResourceResponse. Doubled to account for the WebCore copy and the CF copy.
+ // Mostly due to the size of the hash maps, the Header Map strings and the URL.
+ 256 * 2 // Overhead from ResourceRequest, doubled to account for WebCore copy and CF copy.
+ // Mostly due to the URL and Header Map.
+ */
+ }
+
NSURLResponse *nsURLResponse() const;
private:
diff --git a/WebCore/platform/network/qt/QNetworkReplyHandler.cpp b/WebCore/platform/network/qt/QNetworkReplyHandler.cpp
index 2de2125..2c730a6 100644
--- a/WebCore/platform/network/qt/QNetworkReplyHandler.cpp
+++ b/WebCore/platform/network/qt/QNetworkReplyHandler.cpp
@@ -269,8 +269,10 @@ void QNetworkReplyHandler::sendResponseIfNeeded()
const bool isLocalFileReply = (m_reply->url().scheme() == QLatin1String("file"));
int statusCode = m_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
- if (!isLocalFileReply)
+ if (!isLocalFileReply) {
response.setHTTPStatusCode(statusCode);
+ response.setHTTPStatusText(m_reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray().constData());
+ }
else if (m_reply->error() == QNetworkReply::ContentNotFoundError)
response.setHTTPStatusCode(404);
diff --git a/WebCore/platform/network/soup/CookieJarSoup.cpp b/WebCore/platform/network/soup/CookieJarSoup.cpp
index 88109e8..e3064e1 100644
--- a/WebCore/platform/network/soup/CookieJarSoup.cpp
+++ b/WebCore/platform/network/soup/CookieJarSoup.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 Xan Lopez <xan@gnome.org>
+ * Copyright (C) 2009 Igalia S.L.
* Copyright (C) 2008 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
@@ -25,15 +26,35 @@
namespace WebCore {
-SoupCookieJar* getCookieJar()
+static bool cookiesInitialized;
+static SoupCookieJar* cookieJar;
+
+SoupCookieJar* defaultCookieJar()
+{
+ if (!cookiesInitialized) {
+ cookiesInitialized = true;
+ setDefaultCookieJar(soup_cookie_jar_new());
+ }
+
+ return cookieJar;
+}
+
+void setDefaultCookieJar(SoupCookieJar* jar)
{
- static SoupCookieJar* jar = soup_cookie_jar_new();
- return jar;
+ cookiesInitialized = true;
+
+ if (cookieJar)
+ g_object_unref(cookieJar);
+
+ cookieJar = jar;
+
+ if (cookieJar)
+ g_object_ref(cookieJar);
}
void setCookies(Document* /*document*/, const KURL& url, const KURL& /*policyURL*/, const String& value)
{
- SoupCookieJar* jar = getCookieJar();
+ SoupCookieJar* jar = defaultCookieJar();
if (!jar)
return;
@@ -45,7 +66,7 @@ void setCookies(Document* /*document*/, const KURL& url, const KURL& /*policyURL
String cookies(const Document* /*document*/, const KURL& url)
{
- SoupCookieJar* jar = getCookieJar();
+ SoupCookieJar* jar = defaultCookieJar();
if (!jar)
return String();
@@ -61,7 +82,7 @@ String cookies(const Document* /*document*/, const KURL& url)
bool cookiesEnabled(const Document* /*document*/)
{
- return getCookieJar();
+ return defaultCookieJar();
}
}
diff --git a/WebCore/platform/network/soup/CookieJarSoup.h b/WebCore/platform/network/soup/CookieJarSoup.h
index 61179ae..ab1f95c 100644
--- a/WebCore/platform/network/soup/CookieJarSoup.h
+++ b/WebCore/platform/network/soup/CookieJarSoup.h
@@ -31,7 +31,8 @@
#include <libsoup/soup.h>
namespace WebCore {
- SoupCookieJar* getCookieJar();
+ SoupCookieJar* defaultCookieJar();
+ void setDefaultCookieJar(SoupCookieJar* jar);
}
#endif
diff --git a/WebCore/platform/network/soup/ResourceHandleSoup.cpp b/WebCore/platform/network/soup/ResourceHandleSoup.cpp
index da96873..1b91e32 100644
--- a/WebCore/platform/network/soup/ResourceHandleSoup.cpp
+++ b/WebCore/platform/network/soup/ResourceHandleSoup.cpp
@@ -3,6 +3,9 @@
* Copyright (C) 2008 Xan Lopez <xan@gnome.org>
* Copyright (C) 2008 Collabora Ltd.
* Copyright (C) 2009 Holger Hans Peter Freyther
+ * Copyright (C) 2009 Gustavo Noronha Silva <gns@gnome.org>
+ * Copyright (C) 2009 Christian Dywan <christian@imendio.com>
+ * Copyright (C) 2009 Igalia S.L.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -21,41 +24,109 @@
*/
#include "config.h"
-#include "CString.h"
#include "ResourceHandle.h"
#include "Base64.h"
#include "CookieJarSoup.h"
+#include "ChromeClient.h"
+#include "CString.h"
#include "DocLoader.h"
+#include "FileSystem.h"
#include "Frame.h"
#include "HTTPParsers.h"
+#include "Logging.h"
#include "MIMETypeRegistry.h"
#include "NotImplemented.h"
+#include "Page.h"
#include "ResourceError.h"
#include "ResourceHandleClient.h"
#include "ResourceHandleInternal.h"
#include "ResourceResponse.h"
#include "TextEncoding.h"
+#include <errno.h>
+#include <fcntl.h>
#include <gio/gio.h>
+#include <gtk/gtk.h>
#include <libsoup/soup.h>
-#include <libsoup/soup-message.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
#if PLATFORM(GTK)
- #if GLIB_CHECK_VERSION(2,12,0)
- #define USE_GLIB_BASE64
- #endif
+#define USE_GLIB_BASE64
#endif
namespace WebCore {
-static SoupSession* session = 0;
+class WebCoreSynchronousLoader : public ResourceHandleClient, Noncopyable {
+public:
+ WebCoreSynchronousLoader(ResourceError&, ResourceResponse &, Vector<char>&);
+ ~WebCoreSynchronousLoader();
+
+ virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&);
+ virtual void didReceiveData(ResourceHandle*, const char*, int, int lengthReceived);
+ virtual void didFinishLoading(ResourceHandle*);
+ virtual void didFail(ResourceHandle*, const ResourceError&);
+
+ void run();
+
+private:
+ ResourceError& m_error;
+ ResourceResponse& m_response;
+ Vector<char>& m_data;
+ bool m_finished;
+ GMainLoop* m_mainLoop;
+};
+
+WebCoreSynchronousLoader::WebCoreSynchronousLoader(ResourceError& error, ResourceResponse& response, Vector<char>& data)
+ : m_error(error)
+ , m_response(response)
+ , m_data(data)
+ , m_finished(false)
+{
+ m_mainLoop = g_main_loop_new(0, false);
+}
+
+WebCoreSynchronousLoader::~WebCoreSynchronousLoader()
+{
+ g_main_loop_unref(m_mainLoop);
+}
+
+void WebCoreSynchronousLoader::didReceiveResponse(ResourceHandle*, const ResourceResponse& response)
+{
+ m_response = response;
+}
+
+void WebCoreSynchronousLoader::didReceiveData(ResourceHandle*, const char* data, int length, int)
+{
+ m_data.append(data, length);
+}
+
+void WebCoreSynchronousLoader::didFinishLoading(ResourceHandle*)
+{
+ g_main_loop_quit(m_mainLoop);
+ m_finished = true;
+}
+
+void WebCoreSynchronousLoader::didFail(ResourceHandle* handle, const ResourceError& error)
+{
+ m_error = error;
+ didFinishLoading(handle);
+}
+
+void WebCoreSynchronousLoader::run()
+{
+ if (!m_finished)
+ g_main_loop_run(m_mainLoop);
+}
enum
{
ERROR_TRANSPORT,
ERROR_UNKNOWN_PROTOCOL,
- ERROR_BAD_NON_HTTP_METHOD
+ ERROR_BAD_NON_HTTP_METHOD,
+ ERROR_UNABLE_TO_OPEN_FILE,
};
static void cleanupGioOperation(ResourceHandleInternal* handle);
@@ -82,20 +153,47 @@ ResourceHandle::~ResourceHandle()
static void fillResponseFromMessage(SoupMessage* msg, ResourceResponse* response)
{
SoupMessageHeadersIter iter;
- const char* name = NULL;
- const char* value = NULL;
+ const char* name = 0;
+ const char* value = 0;
soup_message_headers_iter_init(&iter, msg->response_headers);
while (soup_message_headers_iter_next(&iter, &name, &value))
response->setHTTPHeaderField(name, value);
- String contentType = soup_message_headers_get(msg->response_headers, "Content-Type");
- char* uri = soup_uri_to_string(soup_message_get_uri(msg), FALSE);
- response->setUrl(KURL(uri));
- g_free(uri);
+ 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) {
+ GHashTableIter hashTableIter;
+ gpointer hashKey;
+ gpointer hashValue;
+
+ g_hash_table_iter_init(&hashTableIter, contentTypeParameters);
+ while (g_hash_table_iter_next(&hashTableIter, &hashKey, &hashValue)) {
+ contentType += String("; ");
+ contentType += String(static_cast<char*>(hashKey));
+ contentType += String("=");
+ contentType += String(static_cast<char*>(hashValue));
+ }
+ g_hash_table_destroy(contentTypeParameters);
+ }
+
response->setMimeType(extractMIMETypeFromMediaType(contentType));
+
+ char* uri = soup_uri_to_string(soup_message_get_uri(msg), false);
+ response->setURL(KURL(KURL(), uri));
+ g_free(uri);
response->setTextEncodingName(extractCharsetFromMediaType(contentType));
response->setExpectedContentLength(soup_message_headers_get_content_length(msg->response_headers));
response->setHTTPStatusCode(msg->status_code);
+ response->setHTTPStatusText(msg->reason_phrase);
response->setSuggestedFilename(filenameFromHTTPContentDisposition(response->httpHeaderField("Content-Disposition")));
}
@@ -110,11 +208,20 @@ static void restartedCallback(SoupMessage* msg, gpointer data)
if (d->m_cancelled)
return;
- char* uri = soup_uri_to_string(soup_message_get_uri(msg), FALSE);
+ char* uri = soup_uri_to_string(soup_message_get_uri(msg), false);
String location = String(uri);
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);
@@ -127,7 +234,32 @@ static void restartedCallback(SoupMessage* msg, gpointer data)
static void gotHeadersCallback(SoupMessage* msg, gpointer data)
{
- if (!SOUP_STATUS_IS_SUCCESSFUL(msg->status_code))
+ // For 401, we will accumulate the resource body, and only use it
+ // in case authentication with the soup feature doesn't happen
+ if (msg->status_code == SOUP_STATUS_UNAUTHORIZED) {
+ soup_message_body_set_accumulate(msg->response_body, TRUE);
+ return;
+ }
+
+ // For all the other responses, we handle each chunk ourselves,
+ // and we don't need msg->response_body to contain all of the data
+ // we got, when we finish downloading.
+ soup_message_body_set_accumulate(msg->response_body, FALSE);
+
+ // 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.
+ if ((msg->status_code != SOUP_STATUS_NOT_MODIFIED)
+ && !soup_message_headers_get_content_type(msg->response_headers, NULL))
return;
ResourceHandle* handle = static_cast<ResourceHandle*>(data);
@@ -142,12 +274,14 @@ static void gotHeadersCallback(SoupMessage* msg, gpointer data)
fillResponseFromMessage(msg, &d->m_response);
client->didReceiveResponse(handle, d->m_response);
- soup_message_set_flags(msg, SOUP_MESSAGE_OVERWRITE_CHUNKS);
+ d->m_reportedHeaders = true;
}
static void gotChunkCallback(SoupMessage* msg, SoupBuffer* chunk, gpointer data)
{
- if (!SOUP_STATUS_IS_SUCCESSFUL(msg->status_code))
+ if (SOUP_STATUS_IS_TRANSPORT_ERROR(msg->status_code)
+ || (SOUP_STATUS_IS_REDIRECTION(msg->status_code) && (msg->status_code != SOUP_STATUS_NOT_MODIFIED))
+ || (msg->status_code == SOUP_STATUS_UNAUTHORIZED))
return;
ResourceHandle* handle = static_cast<ResourceHandle*>(data);
@@ -160,6 +294,17 @@ 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, d->m_response);
+ d->m_reportedHeaders = true;
+ }
+
client->didReceiveData(handle, chunk->data, chunk->length, false);
}
@@ -167,7 +312,7 @@ static void gotChunkCallback(SoupMessage* msg, SoupBuffer* chunk, gpointer data)
// Doesn't get called for redirects.
static void finishedCallback(SoupSession *session, SoupMessage* msg, gpointer data)
{
- ResourceHandle* handle = static_cast<ResourceHandle*>(data);
+ RefPtr<ResourceHandle>handle = adoptRef(static_cast<ResourceHandle*>(data));
// TODO: maybe we should run this code even if there's no client?
if (!handle)
return;
@@ -182,24 +327,26 @@ 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);
+ char* uri = soup_uri_to_string(soup_message_get_uri(msg), false);
ResourceError error("webkit-network-error", ERROR_TRANSPORT, uri, String::fromUTF8(msg->reason_phrase));
g_free(uri);
- client->didFail(handle, error);
+ client->didFail(handle.get(), error);
return;
- } else if (!SOUP_STATUS_IS_SUCCESSFUL(msg->status_code)) {
+ }
+
+ if (msg->status_code == SOUP_STATUS_UNAUTHORIZED) {
fillResponseFromMessage(msg, &d->m_response);
- client->didReceiveResponse(handle, d->m_response);
+ client->didReceiveResponse(handle.get(), d->m_response);
// WebCore might have cancelled the job in the while
if (d->m_cancelled)
return;
if (msg->response_body->data)
- client->didReceiveData(handle, msg->response_body->data, msg->response_body->length, true);
+ client->didReceiveData(handle.get(), msg->response_body->data, msg->response_body->length, true);
}
- client->didFinishLoading(handle);
+ client->didFinishLoading(handle.get());
}
// parseDataUrl() is taken from the CURL http backend.
@@ -212,7 +359,7 @@ static gboolean parseDataUrl(gpointer callback_data)
ASSERT(client);
if (!client)
- return FALSE;
+ return false;
String url = handle->request().url().string();
ASSERT(url.startsWith("data:", false));
@@ -220,14 +367,14 @@ static gboolean parseDataUrl(gpointer callback_data)
int index = url.find(',');
if (index == -1) {
client->cannotShowURL(handle);
- return FALSE;
+ return false;
}
String mediaType = url.substring(5, index - 5);
String data = url.substring(index + 1);
- bool base64 = mediaType.endsWith(";base64", false);
- if (base64)
+ bool isBase64 = mediaType.endsWith(";base64", false);
+ if (isBase64)
mediaType = mediaType.left(mediaType.length() - 7);
if (mediaType.isEmpty())
@@ -239,7 +386,7 @@ static gboolean parseDataUrl(gpointer callback_data)
ResourceResponse response;
response.setMimeType(mimeType);
- if (base64) {
+ if (isBase64) {
data = decodeURLEscapeSequences(data);
response.setTextEncodingName(charset);
client->didReceiveResponse(handle, response);
@@ -269,7 +416,7 @@ static gboolean parseDataUrl(gpointer callback_data)
client->didFinishLoading(handle);
- return FALSE;
+ return false;
}
bool ResourceHandle::startData(String urlString)
@@ -282,30 +429,44 @@ bool ResourceHandle::startData(String urlString)
return true;
}
-bool ResourceHandle::startHttp(String urlString)
+static SoupSession* createSoupSession()
{
- if (!session) {
- session = soup_session_async_new();
+ return soup_session_async_new();
+}
- soup_session_add_feature(session, SOUP_SESSION_FEATURE(getCookieJar()));
+static void ensureSessionIsInitialized(SoupSession* session)
+{
+ if (g_object_get_data(G_OBJECT(session), "webkit-init"))
+ return;
- const char* soup_debug = g_getenv("WEBKIT_SOUP_LOGGING");
- if (soup_debug) {
- int soup_debug_level = atoi(soup_debug);
+ SoupCookieJar* jar = reinterpret_cast<SoupCookieJar*>(soup_session_get_feature(session, SOUP_TYPE_COOKIE_JAR));
+ if (!jar)
+ soup_session_add_feature(session, SOUP_SESSION_FEATURE(defaultCookieJar()));
+ else
+ setDefaultCookieJar(jar);
- SoupLogger* logger = soup_logger_new(static_cast<SoupLoggerLogLevel>(soup_debug_level), -1);
- soup_logger_attach(logger, session);
- g_object_unref(logger);
- }
+ if (!soup_session_get_feature(session, SOUP_TYPE_LOGGER) && LogNetwork.state == WTFLogChannelOn) {
+ SoupLogger* logger = soup_logger_new(static_cast<SoupLoggerLogLevel>(SOUP_LOGGER_LOG_BODY), -1);
+ soup_logger_attach(logger, session);
+ g_object_unref(logger);
}
+ g_object_set_data(G_OBJECT(session), "webkit-init", reinterpret_cast<void*>(0xdeadbeef));
+}
+
+bool ResourceHandle::startHttp(String urlString)
+{
+ SoupSession* session = defaultSession();
+ ensureSessionIsInitialized(session);
+
SoupMessage* msg;
msg = soup_message_new(request().httpMethod().utf8().data(), urlString.utf8().data());
g_signal_connect(msg, "restarted", G_CALLBACK(restartedCallback), this);
-
g_signal_connect(msg, "got-headers", G_CALLBACK(gotHeadersCallback), this);
g_signal_connect(msg, "got-chunk", G_CALLBACK(gotChunkCallback), this);
+ g_object_set_data(G_OBJECT(msg), "resourceHandle", reinterpret_cast<void*>(this));
+
HTTPHeaderMap customHeaders = d->m_request.httpHeaderFields();
if (!customHeaders.isEmpty()) {
HTTPHeaderMap::const_iterator end = customHeaders.end();
@@ -315,68 +476,130 @@ bool ResourceHandle::startHttp(String urlString)
FormData* httpBody = d->m_request.httpBody();
if (httpBody && !httpBody->isEmpty()) {
- // Making a copy of the request body isn't the most efficient way to
- // serialize it, but by far the most simple. Dealing with individual
- // FormData elements and shared buffers should be more memory
- // efficient.
- //
- // This possibly isn't handling file uploads/attachments, for which
- // shared buffers or streaming should definitely be used.
- Vector<char> body;
- httpBody->flatten(body);
- soup_message_set_request(msg, d->m_request.httpContentType().utf8().data(),
- SOUP_MEMORY_COPY, body.data(), body.size());
+ size_t numElements = httpBody->elements().size();
+
+ // handle the most common case (i.e. no file upload)
+ if (numElements < 2) {
+ Vector<char> body;
+ httpBody->flatten(body);
+ soup_message_set_request(msg, d->m_request.httpContentType().utf8().data(),
+ SOUP_MEMORY_COPY, body.data(), body.size());
+ } else {
+ /*
+ * we have more than one element to upload, and some may
+ * be (big) files, which we will want to mmap instead of
+ * copying into memory; TODO: support upload of non-local
+ * (think sftp://) files by using GIO?
+ */
+ soup_message_body_set_accumulate(msg->request_body, FALSE);
+ for (size_t i = 0; i < numElements; i++) {
+ const FormDataElement& element = httpBody->elements()[i];
+
+ if (element.m_type == FormDataElement::data)
+ soup_message_body_append(msg->request_body, SOUP_MEMORY_TEMPORARY, element.m_data.data(), element.m_data.size());
+ else {
+ /*
+ * mapping for uploaded files code inspired by technique used in
+ * libsoup's simple-httpd test
+ */
+ GError* error = 0;
+ gchar* fileName = filenameFromString(element.m_filename);
+ GMappedFile* fileMapping = g_mapped_file_new(fileName, false, &error);
+
+ g_free(fileName);
+
+ if (error) {
+ ResourceError resourceError("webkit-network-error", ERROR_UNABLE_TO_OPEN_FILE, urlString, error->message);
+ g_error_free(error);
+
+ d->client()->didFail(this, resourceError);
+
+ g_object_unref(msg);
+ return false;
+ }
+
+ 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));
+ soup_message_body_append_buffer(msg->request_body, soupBuffer);
+ soup_buffer_free(soupBuffer);
+ }
+ }
+ }
}
d->m_msg = static_cast<SoupMessage*>(g_object_ref(msg));
+ // balanced by a deref() in finishedCallback, which should always run
+ ref();
+
soup_session_queue_message(session, d->m_msg, finishedCallback, this);
return true;
}
+static gboolean reportUnknownProtocolError(gpointer callback_data)
+{
+ ResourceHandle* handle = static_cast<ResourceHandle*>(callback_data);
+ ResourceHandleInternal* d = handle->getInternal();
+ ResourceHandleClient* client = handle->client();
+
+ if (d->m_cancelled || !client) {
+ handle->deref();
+ return false;
+ }
+
+ KURL url = handle->request().url();
+ ResourceError error("webkit-network-error", ERROR_UNKNOWN_PROTOCOL, url.string(), url.protocol());
+ client->didFail(handle, error);
+
+ handle->deref();
+ return false;
+}
+
bool ResourceHandle::start(Frame* frame)
{
ASSERT(!d->m_msg);
- // If we are no longer attached to a Page, this must be an attempted load from an
- // onUnload handler, so let's just block it.
- if (!frame->page())
+
+ // The frame could be null if the ResourceHandle is not associated to any
+ // Frame, e.g. if we are downloading a file.
+ // If the frame is not null but the page is null this must be an attempted
+ // load from an onUnload handler, so let's just block it.
+ if (frame && !frame->page())
return false;
KURL url = request().url();
String urlString = url.string();
String protocol = url.protocol();
+ // Used to set the authentication dialog toplevel; may be NULL
+ d->m_frame = frame;
+
if (equalIgnoringCase(protocol, "data"))
return startData(urlString);
- else if ((equalIgnoringCase(protocol, "http") || equalIgnoringCase(protocol, "https")) && SOUP_URI_VALID_FOR_HTTP(soup_uri_new(urlString.utf8().data())))
+
+ if ((equalIgnoringCase(protocol, "http") || equalIgnoringCase(protocol, "https")) && SOUP_URI_VALID_FOR_HTTP(soup_uri_new(urlString.utf8().data())))
return startHttp(urlString);
- else if (equalIgnoringCase(protocol, "file") || equalIgnoringCase(protocol, "ftp") || equalIgnoringCase(protocol, "ftps"))
+
+ if (equalIgnoringCase(protocol, "file") || equalIgnoringCase(protocol, "ftp") || equalIgnoringCase(protocol, "ftps"))
// FIXME: should we be doing any other protocols here?
- return startGio(urlString);
- else {
- // If we don't call didFail the job is not complete for webkit even false is returned.
- if (d->client()) {
- ResourceError error("webkit-network-error", ERROR_UNKNOWN_PROTOCOL, urlString, protocol);
- d->client()->didFail(this, error);
- }
- return false;
- }
+ return startGio(url);
+
+ // Error must not be reported immediately, but through an idle function.
+ // Despite error, we should return true so a proper handle is created,
+ // to which this failure can be reported.
+ ref();
+ d->m_idleHandler = g_idle_add(reportUnknownProtocolError, this);
+ return true;
}
void ResourceHandle::cancel()
{
d->m_cancelled = true;
- if (d->m_msg) {
- soup_session_cancel_message(session, d->m_msg, SOUP_STATUS_CANCELLED);
- // For re-entrancy troubles we call didFinishLoading when the message hasn't been handled yet.
- if (client())
- client()->didFinishLoading(this);
- } else if (d->m_cancellable) {
+ if (d->m_msg)
+ soup_session_cancel_message(defaultSession(), d->m_msg, SOUP_STATUS_CANCELLED);
+ else if (d->m_cancellable)
g_cancellable_cancel(d->m_cancellable);
- if (client())
- client()->didFinishLoading(this);
- }
}
PassRefPtr<SharedBuffer> ResourceHandle::bufferedData()
@@ -409,9 +632,13 @@ bool ResourceHandle::willLoadFromCache(ResourceRequest&)
return false;
}
-void ResourceHandle::loadResourceSynchronously(const ResourceRequest&, ResourceError&, ResourceResponse&, Vector<char>&, Frame*)
+void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data, Frame* frame)
{
- notImplemented();
+ WebCoreSynchronousLoader syncLoader(error, response, data);
+ ResourceHandle handle(request, &syncLoader, true, false, true);
+
+ handle.start(frame);
+ syncLoader.run();
}
// GIO-based loader
@@ -420,7 +647,7 @@ static inline ResourceError networkErrorForFile(GFile* file, GError* error)
{
// FIXME: Map gio errors to a more detailed error code when we have it in WebKit.
gchar* uri = g_file_get_uri(file);
- ResourceError resourceError("webkit-network-error", ERROR_TRANSPORT, uri, String::fromUTF8(error->message));
+ ResourceError resourceError("webkit-network-error", ERROR_TRANSPORT, uri, error ? String::fromUTF8(error->message) : String());
g_free(uri);
return resourceError;
}
@@ -430,20 +657,23 @@ static void cleanupGioOperation(ResourceHandleInternal* d)
if (d->m_gfile) {
g_object_set_data(G_OBJECT(d->m_gfile), "webkit-resource", 0);
g_object_unref(d->m_gfile);
- d->m_gfile = NULL;
+ d->m_gfile = 0;
}
+
if (d->m_cancellable) {
g_object_unref(d->m_cancellable);
- d->m_cancellable = NULL;
+ d->m_cancellable = 0;
}
- if (d->m_input_stream) {
- g_object_set_data(G_OBJECT(d->m_input_stream), "webkit-resource", 0);
- g_object_unref(d->m_input_stream);
- d->m_input_stream = NULL;
+
+ if (d->m_inputStream) {
+ g_object_set_data(G_OBJECT(d->m_inputStream), "webkit-resource", 0);
+ g_object_unref(d->m_inputStream);
+ d->m_inputStream = 0;
}
+
if (d->m_buffer) {
g_free(d->m_buffer);
- d->m_buffer = NULL;
+ d->m_buffer = 0;
}
}
@@ -456,14 +686,15 @@ static void closeCallback(GObject* source, GAsyncResult* res, gpointer)
ResourceHandleInternal* d = handle->getInternal();
ResourceHandleClient* client = handle->client();
- g_input_stream_close_finish(d->m_input_stream, res, NULL);
+ g_input_stream_close_finish(d->m_inputStream, res, 0);
cleanupGioOperation(d);
client->didFinishLoading(handle);
}
static void readCallback(GObject* source, GAsyncResult* res, gpointer)
{
- ResourceHandle* handle = static_cast<ResourceHandle*>(g_object_get_data(source, "webkit-resource"));
+ // didReceiveData may cancel the load, which may release the last reference.
+ RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(g_object_get_data(source, "webkit-resource"));
if (!handle)
return;
@@ -475,27 +706,34 @@ static void readCallback(GObject* source, GAsyncResult* res, gpointer)
return;
}
- gssize nread;
GError *error = 0;
- nread = g_input_stream_read_finish(d->m_input_stream, res, &error);
+ gssize bytesRead = g_input_stream_read_finish(d->m_inputStream, res, &error);
if (error) {
ResourceError resourceError = networkErrorForFile(d->m_gfile, error);
+ g_error_free(error);
cleanupGioOperation(d);
- client->didFail(handle, resourceError);
+ client->didFail(handle.get(), resourceError);
return;
- } else if (!nread) {
- g_input_stream_close_async(d->m_input_stream, G_PRIORITY_DEFAULT,
- NULL, closeCallback, NULL);
+ }
+
+ if (!bytesRead) {
+ g_input_stream_close_async(d->m_inputStream, G_PRIORITY_DEFAULT,
+ 0, closeCallback, 0);
return;
}
- d->m_total += nread;
- client->didReceiveData(handle, d->m_buffer, nread, d->m_total);
+ d->m_total += bytesRead;
+ client->didReceiveData(handle.get(), d->m_buffer, bytesRead, d->m_total);
- g_input_stream_read_async(d->m_input_stream, d->m_buffer, d->m_bufsize,
+ if (d->m_cancelled) {
+ cleanupGioOperation(d);
+ return;
+ }
+
+ g_input_stream_read_async(d->m_inputStream, d->m_buffer, d->m_bufferSize,
G_PRIORITY_DEFAULT, d->m_cancellable,
- readCallback, NULL);
+ readCallback, 0);
}
static void openCallback(GObject* source, GAsyncResult* res, gpointer)
@@ -512,24 +750,24 @@ static void openCallback(GObject* source, GAsyncResult* res, gpointer)
return;
}
- GFileInputStream* in;
- GError *error = NULL;
- in = g_file_read_finish(G_FILE(source), res, &error);
+ GError *error = 0;
+ GFileInputStream* in = g_file_read_finish(G_FILE(source), res, &error);
if (error) {
ResourceError resourceError = networkErrorForFile(d->m_gfile, error);
+ g_error_free(error);
cleanupGioOperation(d);
client->didFail(handle, resourceError);
return;
}
- d->m_input_stream = G_INPUT_STREAM(in);
- d->m_bufsize = 8192;
- d->m_buffer = static_cast<char*>(g_malloc(d->m_bufsize));
+ d->m_inputStream = G_INPUT_STREAM(in);
+ d->m_bufferSize = 8192;
+ d->m_buffer = static_cast<char*>(g_malloc(d->m_bufferSize));
d->m_total = 0;
- g_object_set_data(G_OBJECT(d->m_input_stream), "webkit-resource", handle);
- g_input_stream_read_async(d->m_input_stream, d->m_buffer, d->m_bufsize,
+ g_object_set_data(G_OBJECT(d->m_inputStream), "webkit-resource", handle);
+ g_input_stream_read_async(d->m_inputStream, d->m_buffer, d->m_bufferSize,
G_PRIORITY_DEFAULT, d->m_cancellable,
- readCallback, NULL);
+ readCallback, 0);
}
static void queryInfoCallback(GObject* source, GAsyncResult* res, gpointer)
@@ -549,10 +787,10 @@ static void queryInfoCallback(GObject* source, GAsyncResult* res, gpointer)
ResourceResponse response;
char* uri = g_file_get_uri(d->m_gfile);
- response.setUrl(KURL(uri));
+ response.setURL(KURL(KURL(), uri));
g_free(uri);
- GError *error = NULL;
+ GError *error = 0;
GFileInfo* info = g_file_query_info_finish(d->m_gfile, res, &error);
if (error) {
@@ -564,6 +802,7 @@ static void queryInfoCallback(GObject* source, GAsyncResult* res, gpointer)
// for a while).
ResourceError resourceError = networkErrorForFile(d->m_gfile, error);
+ g_error_free(error);
cleanupGioOperation(d);
client->didFail(handle, resourceError);
return;
@@ -573,7 +812,7 @@ static void queryInfoCallback(GObject* source, GAsyncResult* res, gpointer)
// FIXME: what if the URI points to a directory? Should we
// generate a listing? How? What do other backends do here?
- ResourceError resourceError = networkErrorForFile(d->m_gfile, error);
+ ResourceError resourceError = networkErrorForFile(d->m_gfile, 0);
cleanupGioOperation(d);
client->didFail(handle, resourceError);
return;
@@ -581,7 +820,6 @@ static void queryInfoCallback(GObject* source, GAsyncResult* res, gpointer)
response.setMimeType(g_file_info_get_content_type(info));
response.setExpectedContentLength(g_file_info_get_size(info));
- response.setHTTPStatusCode(SOUP_STATUS_OK);
GTimeVal tv;
g_file_info_get_modification_time(info, &tv);
@@ -590,23 +828,31 @@ static void queryInfoCallback(GObject* source, GAsyncResult* res, gpointer)
client->didReceiveResponse(handle, response);
g_file_read_async(d->m_gfile, G_PRIORITY_DEFAULT, d->m_cancellable,
- openCallback, NULL);
+ openCallback, 0);
}
-bool ResourceHandle::startGio(String urlString)
+bool ResourceHandle::startGio(KURL url)
{
- if (request().httpMethod() != "GET") {
- ResourceError error("webkit-network-error", ERROR_BAD_NON_HTTP_METHOD, urlString, request().httpMethod());
+ if (request().httpMethod() != "GET" && request().httpMethod() != "POST") {
+ ResourceError error("webkit-network-error", ERROR_BAD_NON_HTTP_METHOD, url.string(), request().httpMethod());
d->client()->didFail(this, error);
return false;
}
- // Remove the fragment part of the URL since the file backend doesn't deal with it
- int fragPos;
- if ((fragPos = urlString.find("#")) != -1)
- urlString = urlString.left(fragPos);
-
- d->m_gfile = g_file_new_for_uri(urlString.utf8().data());
+ // 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.setQuery(String());
+ url.setPort(0);
+
+ // we avoid the escaping for local files, because
+ // g_filename_from_uri (used internally by GFile) has problems
+ // decoding strings with arbitrary percent signs
+ if (url.isLocalFile())
+ d->m_gfile = g_file_new_for_path(url.prettyURL().utf8().data() + sizeof("file://") - 1);
+ else
+ d->m_gfile = g_file_new_for_uri(url.string().utf8().data());
g_object_set_data(G_OBJECT(d->m_gfile), "webkit-resource", this);
d->m_cancellable = g_cancellable_new();
g_file_query_info_async(d->m_gfile,
@@ -615,9 +861,16 @@ bool ResourceHandle::startGio(String urlString)
G_FILE_ATTRIBUTE_STANDARD_SIZE,
G_FILE_QUERY_INFO_NONE,
G_PRIORITY_DEFAULT, d->m_cancellable,
- queryInfoCallback, NULL);
+ queryInfoCallback, 0);
return true;
}
+SoupSession* ResourceHandle::defaultSession()
+{
+ static SoupSession* session = createSoupSession();;
+
+ return session;
+}
+
}
diff --git a/WebCore/platform/network/win/CookieJarCFNetWin.cpp b/WebCore/platform/network/win/CookieJarCFNetWin.cpp
index 56d7265..7e64813 100644
--- a/WebCore/platform/network/win/CookieJarCFNetWin.cpp
+++ b/WebCore/platform/network/win/CookieJarCFNetWin.cpp
@@ -41,28 +41,6 @@ namespace WebCore {
static const CFStringRef s_setCookieKeyCF = CFSTR("Set-Cookie");
static const CFStringRef s_cookieCF = CFSTR("Cookie");
-typedef Boolean (*IsHTTPOnlyFunction)(CFHTTPCookieRef);
-
-static HMODULE findCFNetworkModule()
-{
- if (HMODULE module = GetModuleHandleA("CFNetwork"))
- return module;
- return GetModuleHandleA("CFNetwork_debug");
-}
-
-static IsHTTPOnlyFunction findIsHTTPOnlyFunction()
-{
- return reinterpret_cast<IsHTTPOnlyFunction>(GetProcAddress(findCFNetworkModule(), "CFHTTPCookieIsHTTPOnly"));
-}
-
-static bool isHTTPOnly(CFHTTPCookieRef cookie)
-{
- // Once we require a newer version of CFNetwork with the CFHTTPCookieIsHTTPOnly function,
- // we can change this to be a normal function call and eliminate findIsHTTPOnlyFunction.
- static IsHTTPOnlyFunction function = findIsHTTPOnlyFunction();
- return function && function(cookie);
-}
-
static RetainPtr<CFArrayRef> filterCookies(CFArrayRef unfilteredCookies)
{
CFIndex count = CFArrayGetCount(unfilteredCookies);
@@ -77,7 +55,7 @@ static RetainPtr<CFArrayRef> filterCookies(CFArrayRef unfilteredCookies)
if (!CFStringGetLength(CFHTTPCookieGetName(cookie)))
continue;
- if (isHTTPOnly(cookie))
+ if (CFHTTPCookieIsHTTPOnly(cookie))
continue;
CFArrayAppendValue(filteredCookies.get(), cookie);