summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/network
diff options
context:
space:
mode:
authorSteve Block <steveblock@google.com>2011-05-18 13:36:51 +0100
committerSteve Block <steveblock@google.com>2011-05-24 15:38:28 +0100
commit2fc2651226baac27029e38c9d6ef883fa32084db (patch)
treee396d4bf89dcce6ed02071be66212495b1df1dec /Source/WebCore/platform/network
parentb3725cedeb43722b3b175aaeff70552e562d2c94 (diff)
downloadexternal_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.zip
external_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.tar.gz
external_webkit-2fc2651226baac27029e38c9d6ef883fa32084db.tar.bz2
Merge WebKit at r78450: Initial merge by git.
Change-Id: I6d3e5f1f868ec266a0aafdef66182ddc3f265dc1
Diffstat (limited to 'Source/WebCore/platform/network')
-rw-r--r--Source/WebCore/platform/network/BlobRegistryImpl.cpp4
-rw-r--r--Source/WebCore/platform/network/BlobResourceHandle.cpp50
-rw-r--r--Source/WebCore/platform/network/BlobResourceHandle.h3
-rw-r--r--Source/WebCore/platform/network/FormData.cpp22
-rw-r--r--Source/WebCore/platform/network/FormDataBuilder.cpp5
-rw-r--r--Source/WebCore/platform/network/ProtectionSpaceHash.h6
-rw-r--r--Source/WebCore/platform/network/ResourceHandle.h4
-rw-r--r--Source/WebCore/platform/network/ResourceHandleInternal.h13
-rw-r--r--Source/WebCore/platform/network/ResourceRequestBase.cpp22
-rw-r--r--Source/WebCore/platform/network/ResourceRequestBase.h18
-rw-r--r--Source/WebCore/platform/network/cf/DNSCFNet.cpp1
-rw-r--r--Source/WebCore/platform/network/cf/DownloadBundle.h43
-rw-r--r--Source/WebCore/platform/network/cf/FormDataStreamCFNet.cpp13
-rw-r--r--Source/WebCore/platform/network/cf/LoaderRunLoopCF.cpp1
-rw-r--r--Source/WebCore/platform/network/cf/LoaderRunLoopCF.h2
-rw-r--r--Source/WebCore/platform/network/cf/ProxyServerCFNet.cpp4
-rw-r--r--Source/WebCore/platform/network/cf/ResourceHandleCFNet.cpp7
-rw-r--r--Source/WebCore/platform/network/cf/ResourceRequestCFNet.cpp49
-rw-r--r--Source/WebCore/platform/network/cf/ResourceRequestCFNet.h47
-rw-r--r--Source/WebCore/platform/network/cf/SocketStreamHandle.h1
-rw-r--r--Source/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp1
-rw-r--r--Source/WebCore/platform/network/chromium/ResourceRequest.cpp2
-rw-r--r--Source/WebCore/platform/network/chromium/ResourceRequest.h10
-rw-r--r--Source/WebCore/platform/network/chromium/ResourceResponse.cpp4
-rw-r--r--Source/WebCore/platform/network/chromium/ResourceResponse.h15
-rw-r--r--Source/WebCore/platform/network/mac/AuthenticationMac.mm15
-rw-r--r--Source/WebCore/platform/network/mac/FormDataStreamMac.mm4
-rw-r--r--Source/WebCore/platform/network/mac/ResourceHandleMac.mm7
-rw-r--r--Source/WebCore/platform/network/mac/ResourceRequestMac.mm22
-rw-r--r--Source/WebCore/platform/network/qt/QtNAMThreadSafeProxy.cpp20
-rw-r--r--Source/WebCore/platform/network/qt/QtNAMThreadSafeProxy.h4
-rw-r--r--Source/WebCore/platform/network/soup/CookieJarSoup.cpp8
-rw-r--r--Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp375
-rw-r--r--Source/WebCore/platform/network/soup/ResourceRequestSoup.cpp6
-rw-r--r--Source/WebCore/platform/network/soup/SocketStreamHandle.h2
-rw-r--r--Source/WebCore/platform/network/soup/SocketStreamHandleSoup.cpp35
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-directory-input-stream.c200
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-directory-input-stream.h62
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-http-input-stream.c922
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-http-input-stream.h77
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-request-data.c170
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-request-data.h52
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-request-file.c331
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-request-file.h54
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-request-http.c356
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-request-http.h54
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-request.c312
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-request.h100
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-requester.c188
-rw-r--r--Source/WebCore/platform/network/soup/cache/soup-requester.h81
-rw-r--r--Source/WebCore/platform/network/soup/cache/webkit/soup-cache-private.h42
-rw-r--r--Source/WebCore/platform/network/soup/cache/webkit/soup-cache.c1677
-rw-r--r--Source/WebCore/platform/network/soup/cache/webkit/soup-cache.h106
-rw-r--r--Source/WebCore/platform/network/win/DownloadBundleWin.cpp196
54 files changed, 692 insertions, 5133 deletions
diff --git a/Source/WebCore/platform/network/BlobRegistryImpl.cpp b/Source/WebCore/platform/network/BlobRegistryImpl.cpp
index 2c4e8fa..83517f1 100644
--- a/Source/WebCore/platform/network/BlobRegistryImpl.cpp
+++ b/Source/WebCore/platform/network/BlobRegistryImpl.cpp
@@ -68,7 +68,9 @@ PassRefPtr<ResourceHandle> BlobRegistryImpl::createResourceHandle(const Resource
if (!shouldLoadResource(request))
return 0;
- return BlobResourceHandle::create(m_blobs.get(request.url().string()), request, client);
+ RefPtr<BlobResourceHandle> handle = BlobResourceHandle::create(m_blobs.get(request.url().string()), request, client);
+ handle->start();
+ return handle.release();
}
bool BlobRegistryImpl::loadResourceSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, Vector<char>& data)
diff --git a/Source/WebCore/platform/network/BlobResourceHandle.cpp b/Source/WebCore/platform/network/BlobResourceHandle.cpp
index 753052a..24c9088 100644
--- a/Source/WebCore/platform/network/BlobResourceHandle.cpp
+++ b/Source/WebCore/platform/network/BlobResourceHandle.cpp
@@ -138,11 +138,6 @@ void BlobResourceHandle::loadResourceSynchronously(PassRefPtr<BlobStorageData> b
handle->start();
}
-static void delayedStart(void* context)
-{
- static_cast<BlobResourceHandle*>(context)->start();
-}
-
BlobResourceHandle::BlobResourceHandle(PassRefPtr<BlobStorageData> blobData, const ResourceRequest& request, ResourceHandleClient* client, bool async)
: ResourceHandle(request, client, false, false)
, m_blobData(blobData)
@@ -158,11 +153,9 @@ BlobResourceHandle::BlobResourceHandle(PassRefPtr<BlobStorageData> blobData, con
, m_readItemCount(0)
, m_fileOpened(false)
{
- if (m_async) {
- // We need to take a ref.
+ if (m_async)
m_asyncStream = client->createAsyncFileStream(this);
- callOnMainThread(delayedStart, this);
- } else
+ else
m_stream = FileStream::create();
}
@@ -187,10 +180,32 @@ void BlobResourceHandle::cancel()
}
m_aborted = true;
+
+ ResourceHandle::cancel();
+}
+
+void delayedStartBlobResourceHandle(void* context)
+{
+ RefPtr<BlobResourceHandle> handle = adoptRef(static_cast<BlobResourceHandle*>(context));
+ handle->doStart();
}
void BlobResourceHandle::start()
{
+ if (m_async) {
+ // Keep BlobResourceHandle alive until delayedStartBlobResourceHandle runs.
+ ref();
+
+ // Finish this async call quickly and return.
+ callOnMainThread(delayedStartBlobResourceHandle, this);
+ return;
+ }
+
+ doStart();
+}
+
+void BlobResourceHandle::doStart()
+{
// Do not continue if the request is aborted or an error occurs.
if (m_aborted || m_errorCode)
return;
@@ -578,10 +593,23 @@ void BlobResourceHandle::notifyFail(int errorCode)
client()->didFail(this, ResourceError(String(), errorCode, firstRequest().url(), String()));
}
+static void doNotifyFinish(void* context)
+{
+ BlobResourceHandle* handle = static_cast<BlobResourceHandle*>(context);
+ if (handle->client())
+ handle->client()->didFinishLoading(handle, 0);
+}
+
void BlobResourceHandle::notifyFinish()
{
- if (client())
- client()->didFinishLoading(this, 0);
+ if (m_async) {
+ // Schedule to notify the client from a standalone function because the client might dispose the handle immediately from the callback function
+ // while we still have BlobResourceHandle calls in the stack.
+ callOnMainThread(doNotifyFinish, this);
+ return;
+ }
+
+ doNotifyFinish(this);
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/network/BlobResourceHandle.h b/Source/WebCore/platform/network/BlobResourceHandle.h
index 63e8578..1e9e94a 100644
--- a/Source/WebCore/platform/network/BlobResourceHandle.h
+++ b/Source/WebCore/platform/network/BlobResourceHandle.h
@@ -69,9 +69,12 @@ public:
int readSync(char*, int);
private:
+ friend void delayedStartBlobResourceHandle(void*);
+
BlobResourceHandle(PassRefPtr<BlobStorageData>, const ResourceRequest&, ResourceHandleClient*, bool async);
virtual ~BlobResourceHandle();
+ void doStart();
void getSizeForNext();
void seek();
void consumeData(const char* data, int bytesRead);
diff --git a/Source/WebCore/platform/network/FormData.cpp b/Source/WebCore/platform/network/FormData.cpp
index 16f98ad..9784b7f 100644
--- a/Source/WebCore/platform/network/FormData.cpp
+++ b/Source/WebCore/platform/network/FormData.cpp
@@ -209,14 +209,16 @@ void FormData::appendKeyValuePairItems(const FormDataList& list, const TextEncod
name = file->webkitRelativePath().isEmpty() ? file->name() : file->webkitRelativePath();
#else
name = file->name();
-#endif
-
+#endif
// Let the application specify a filename if it's going to generate a replacement file for the upload.
- if (Page* page = document->page()) {
- String generatedFileName;
- shouldGenerateFile = page->chrome()->client()->shouldReplaceWithGeneratedFileForUpload(file->path(), generatedFileName);
- if (shouldGenerateFile)
- name = generatedFileName;
+ const String& path = file->path();
+ if (!path.isEmpty()) {
+ if (Page* page = document->page()) {
+ String generatedFileName;
+ shouldGenerateFile = page->chrome()->client()->shouldReplaceWithGeneratedFileForUpload(path, generatedFileName);
+ if (shouldGenerateFile)
+ name = generatedFileName;
+ }
}
} else {
// For non-file blob, use the identifier part of the URL as the name.
@@ -364,7 +366,9 @@ static void encode(Encoder& encoder, const FormDataElement& element)
static bool decode(Decoder& decoder, FormDataElement& element)
{
- uint32_t type = element.m_type;
+ uint32_t type;
+ if (!decoder.decodeUInt32(type))
+ return false;
switch (type) {
case FormDataElement::data: {
@@ -432,7 +436,7 @@ void FormData::encodeForBackForward(Encoder& encoder) const
encoder.encodeBool(m_hasGeneratedFiles);
- encoder.encodeBool(m_identifier);
+ encoder.encodeInt64(m_identifier);
}
PassRefPtr<FormData> FormData::decodeForBackForward(Decoder& decoder)
diff --git a/Source/WebCore/platform/network/FormDataBuilder.cpp b/Source/WebCore/platform/network/FormDataBuilder.cpp
index da28fc2..e973f99 100644
--- a/Source/WebCore/platform/network/FormDataBuilder.cpp
+++ b/Source/WebCore/platform/network/FormDataBuilder.cpp
@@ -94,10 +94,7 @@ TextEncoding FormDataBuilder::encodingFromAcceptCharset(const String& acceptChar
return encoding;
}
- if (Frame* frame = document->frame())
- return frame->loader()->writer()->encoding();
-
- return Latin1Encoding();
+ return document->inputEncoding();
}
Vector<char> FormDataBuilder::generateUniqueBoundaryString()
diff --git a/Source/WebCore/platform/network/ProtectionSpaceHash.h b/Source/WebCore/platform/network/ProtectionSpaceHash.h
index 08716b5..9934321 100644
--- a/Source/WebCore/platform/network/ProtectionSpaceHash.h
+++ b/Source/WebCore/platform/network/ProtectionSpaceHash.h
@@ -42,11 +42,11 @@ struct ProtectionSpaceHash {
protectionSpace.realm().impl() ? protectionSpace.realm().impl()->hash() : 0
};
- unsigned codeCount = sizeof(hashCodes) / sizeof(UChar);
+ unsigned codeCount = sizeof(hashCodes);
// Ignore realm for proxies.
if (protectionSpace.isProxy())
- codeCount -= sizeof(hashCodes[0]) / sizeof(UChar);
- return StringImpl::computeHash(reinterpret_cast<UChar*>(hashCodes), codeCount);
+ codeCount -= sizeof(hashCodes[0]);
+ return WTF::StringHasher::createBlobHash(hashCodes, codeCount);
}
static bool equal(const ProtectionSpace& a, const ProtectionSpace& b) { return a == b; }
diff --git a/Source/WebCore/platform/network/ResourceHandle.h b/Source/WebCore/platform/network/ResourceHandle.h
index bb94b59..c2a0b8e 100644
--- a/Source/WebCore/platform/network/ResourceHandle.h
+++ b/Source/WebCore/platform/network/ResourceHandle.h
@@ -41,7 +41,7 @@ typedef struct _SoupSession SoupSession;
typedef const struct __CFData * CFDataRef;
#endif
-#if PLATFORM(WIN)
+#if USE(WININET)
typedef unsigned long DWORD;
typedef unsigned long DWORD_PTR;
typedef void* LPVOID;
@@ -173,7 +173,7 @@ public:
bool hasAuthenticationChallenge() const;
void clearAuthentication();
- void cancel();
+ virtual void cancel();
// The client may be 0, in which case no callbacks will be made.
ResourceHandleClient* client() const;
diff --git a/Source/WebCore/platform/network/ResourceHandleInternal.h b/Source/WebCore/platform/network/ResourceHandleInternal.h
index ed66944..5512062 100644
--- a/Source/WebCore/platform/network/ResourceHandleInternal.h
+++ b/Source/WebCore/platform/network/ResourceHandleInternal.h
@@ -46,8 +46,9 @@
#endif
#if USE(SOUP)
-#include "soup-requester.h"
#include <GRefPtr.h>
+#define LIBSOUP_USE_UNSTABLE_REQUEST_API
+#include <libsoup/soup-request.h>
#include <libsoup/soup.h>
class Frame;
#endif
@@ -114,6 +115,8 @@ namespace WebCore {
, m_cancelled(false)
, m_buffer(0)
, m_total(0)
+ , m_bodySize(0)
+ , m_bodyDataSent(0)
, m_idleHandler(0)
, m_gotChunkHandler(0)
#endif
@@ -132,9 +135,6 @@ namespace WebCore {
m_user = url.user();
m_pass = url.pass();
m_firstRequest.removeCredentials();
-#if USE(SOUP)
- m_requester = adoptGRef(webkit_soup_requester_new());
-#endif
}
~ResourceHandleInternal();
@@ -190,12 +190,13 @@ namespace WebCore {
GRefPtr<SoupMessage> m_soupMessage;
ResourceResponse m_response;
bool m_cancelled;
- GRefPtr<WebKitSoupRequest> m_soupRequest;
- GRefPtr<WebKitSoupRequester> m_requester;
+ GRefPtr<SoupRequest> m_soupRequest;
GRefPtr<GInputStream> m_inputStream;
GRefPtr<GCancellable> m_cancellable;
char* m_buffer;
gsize m_total;
+ unsigned long m_bodySize;
+ unsigned long m_bodyDataSent;
guint m_idleHandler;
RefPtr<NetworkingContext> m_context;
gulong m_gotChunkHandler;
diff --git a/Source/WebCore/platform/network/ResourceRequestBase.cpp b/Source/WebCore/platform/network/ResourceRequestBase.cpp
index ae8316a..ba58461 100644
--- a/Source/WebCore/platform/network/ResourceRequestBase.cpp
+++ b/Source/WebCore/platform/network/ResourceRequestBase.cpp
@@ -45,6 +45,7 @@ PassOwnPtr<ResourceRequest> ResourceRequestBase::adopt(PassOwnPtr<CrossThreadRes
request->setTimeoutInterval(data->m_timeoutInterval);
request->setFirstPartyForCookies(data->m_firstPartyForCookies);
request->setHTTPMethod(data->m_httpMethod);
+ request->setPriority(data->m_priority);
request->setTargetType(data->m_targetType);
request->updateResourceRequest();
@@ -78,6 +79,7 @@ PassOwnPtr<CrossThreadResourceRequestData> ResourceRequestBase::copyData() const
data->m_firstPartyForCookies = firstPartyForCookies().copy();
data->m_httpMethod = httpMethod().crossThreadString();
data->m_httpHeaders = httpHeaderFields().copyData();
+ data->m_priority = priority();
data->m_targetType = m_targetType;
data->m_responseContentDispositionEncodingFallbackArray.reserveInitialCapacity(m_responseContentDispositionEncodingFallbackArray.size());
@@ -314,6 +316,23 @@ void ResourceRequestBase::setAllowCookies(bool allowCookies)
m_platformRequestUpdated = false;
}
+ResourceLoadPriority ResourceRequestBase::priority() const
+{
+ updateResourceRequest();
+
+ return m_priority;
+}
+
+void ResourceRequestBase::setPriority(ResourceLoadPriority priority)
+{
+ updateResourceRequest();
+
+ m_priority = priority;
+
+ if (url().protocolInHTTPFamily())
+ m_platformRequestUpdated = false;
+}
+
void ResourceRequestBase::addHTTPHeaderField(const AtomicString& name, const String& value)
{
updateResourceRequest();
@@ -352,6 +371,9 @@ bool equalIgnoringHeaderFields(const ResourceRequestBase& a, const ResourceReque
if (a.allowCookies() != b.allowCookies())
return false;
+ if (a.priority() != b.priority())
+ return false;
+
FormData* formDataA = a.httpBody();
FormData* formDataB = b.httpBody();
diff --git a/Source/WebCore/platform/network/ResourceRequestBase.h b/Source/WebCore/platform/network/ResourceRequestBase.h
index dce33db..9cc9148 100644
--- a/Source/WebCore/platform/network/ResourceRequestBase.h
+++ b/Source/WebCore/platform/network/ResourceRequestBase.h
@@ -29,8 +29,9 @@
#define ResourceRequestBase_h
#include "FormData.h"
-#include "KURL.h"
#include "HTTPHeaderMap.h"
+#include "KURL.h"
+#include "ResourceLoadPriority.h"
#include <wtf/OwnPtr.h>
@@ -128,6 +129,9 @@ namespace WebCore {
bool allowCookies() const;
void setAllowCookies(bool allowCookies);
+ ResourceLoadPriority priority() const;
+ void setPriority(ResourceLoadPriority);
+
bool isConditional() const;
// Whether the associated ResourceHandleClient needs to be notified of
@@ -157,6 +161,7 @@ namespace WebCore {
, m_reportUploadProgress(false)
, m_reportLoadTiming(false)
, m_reportRawHeaders(false)
+ , m_priority(ResourceLoadPriorityLow)
, m_targetType(TargetIsSubresource)
{
}
@@ -172,6 +177,7 @@ namespace WebCore {
, m_reportUploadProgress(false)
, m_reportLoadTiming(false)
, m_reportRawHeaders(false)
+ , m_priority(ResourceLoadPriorityLow)
, m_targetType(TargetIsSubresource)
{
}
@@ -197,6 +203,7 @@ namespace WebCore {
bool m_reportUploadProgress;
bool m_reportLoadTiming;
bool m_reportRawHeaders;
+ ResourceLoadPriority m_priority;
TargetType m_targetType;
private:
@@ -223,11 +230,20 @@ namespace WebCore {
Vector<String> m_responseContentDispositionEncodingFallbackArray;
RefPtr<FormData> m_httpBody;
bool m_allowCookies;
+ ResourceLoadPriority m_priority;
ResourceRequestBase::TargetType m_targetType;
};
unsigned initializeMaximumHTTPConnectionCountPerHost();
+#if PLATFORM(CF)
+ bool isHTTPPipeliningEnabled();
+ bool shouldForceHTTPPipeliningPriorityHigh();
+#else
+ inline bool isHTTPPipeliningEnabled() { return false; }
+ inline bool shouldForceHTTPPipeliningPriorityHigh() { return false; }
+#endif
+
} // namespace WebCore
#endif // ResourceRequestBase_h
diff --git a/Source/WebCore/platform/network/cf/DNSCFNet.cpp b/Source/WebCore/platform/network/cf/DNSCFNet.cpp
index 166abbf..b6f9922 100644
--- a/Source/WebCore/platform/network/cf/DNSCFNet.cpp
+++ b/Source/WebCore/platform/network/cf/DNSCFNet.cpp
@@ -36,6 +36,7 @@
#if PLATFORM(WIN)
#include "LoaderRunLoopCF.h"
+#include <CFNetwork/CFNetwork.h>
#endif
#if defined(BUILDING_ON_LEOPARD)
diff --git a/Source/WebCore/platform/network/cf/DownloadBundle.h b/Source/WebCore/platform/network/cf/DownloadBundle.h
new file mode 100644
index 0000000..cf90908
--- /dev/null
+++ b/Source/WebCore/platform/network/cf/DownloadBundle.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DownloadBundle_h
+#define DownloadBundle_h
+
+#include <wtf/Forward.h>
+
+typedef const struct __CFData* CFDataRef;
+
+namespace WebCore {
+namespace DownloadBundle {
+
+bool appendResumeData(CFDataRef resumeData, const String& bundlePath);
+CFDataRef extractResumeData(const String& bundlePath);
+const String& fileExtension();
+
+} // namespace DownloadBundle
+} // namespace WebCore
+
+#endif // DownloadBundle_h
diff --git a/Source/WebCore/platform/network/cf/FormDataStreamCFNet.cpp b/Source/WebCore/platform/network/cf/FormDataStreamCFNet.cpp
index eb0ec3a..8bc8f08 100644
--- a/Source/WebCore/platform/network/cf/FormDataStreamCFNet.cpp
+++ b/Source/WebCore/platform/network/cf/FormDataStreamCFNet.cpp
@@ -145,17 +145,8 @@ static void advanceCurrentStream(FormStreamFields *form)
char* data = nextInput.m_data.releaseBuffer();
form->currentStream = CFReadStreamCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(data), size, kCFAllocatorNull);
form->currentData = data;
- } else {
- CFStringRef filename = nextInput.m_filename.createCFString();
-#if PLATFORM(WIN)
- CFURLRef fileURL = CFURLCreateWithFileSystemPath(0, filename, kCFURLWindowsPathStyle, FALSE);
-#else
- CFURLRef fileURL = CFURLCreateWithFileSystemPath(0, filename, kCFURLPOSIXPathStyle, FALSE);
-#endif
- CFRelease(filename);
- form->currentStream = CFReadStreamCreateWithFile(0, fileURL);
- CFRelease(fileURL);
- }
+ } else
+ form->currentStream = CFReadStreamCreateWithFile(0, pathAsURL(nextInput.m_filename).get());
form->remainingElements.removeLast();
// Set up the callback.
diff --git a/Source/WebCore/platform/network/cf/LoaderRunLoopCF.cpp b/Source/WebCore/platform/network/cf/LoaderRunLoopCF.cpp
index 249fe43..a7cc639 100644
--- a/Source/WebCore/platform/network/cf/LoaderRunLoopCF.cpp
+++ b/Source/WebCore/platform/network/cf/LoaderRunLoopCF.cpp
@@ -28,6 +28,7 @@
#if USE(CFNETWORK)
+#include <CoreFoundation/CoreFoundation.h>
#include <wtf/Threading.h>
namespace WebCore {
diff --git a/Source/WebCore/platform/network/cf/LoaderRunLoopCF.h b/Source/WebCore/platform/network/cf/LoaderRunLoopCF.h
index f66128c..e0d3ba4 100644
--- a/Source/WebCore/platform/network/cf/LoaderRunLoopCF.h
+++ b/Source/WebCore/platform/network/cf/LoaderRunLoopCF.h
@@ -32,6 +32,8 @@
#error This code is not needed on platforms other than Windows, because main thread's CFRunLoop can be used.
#endif
+typedef struct __CFRunLoop* CFRunLoopRef;
+
namespace WebCore {
CFRunLoopRef loaderRunLoop();
diff --git a/Source/WebCore/platform/network/cf/ProxyServerCFNet.cpp b/Source/WebCore/platform/network/cf/ProxyServerCFNet.cpp
index 3bef808..57d714b 100644
--- a/Source/WebCore/platform/network/cf/ProxyServerCFNet.cpp
+++ b/Source/WebCore/platform/network/cf/ProxyServerCFNet.cpp
@@ -29,6 +29,10 @@
#include "KURL.h"
#include <wtf/RetainPtr.h>
+#if PLATFORM(WIN)
+#include <CFNetwork/CFNetwork.h>
+#endif
+
namespace WebCore {
#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD)
diff --git a/Source/WebCore/platform/network/cf/ResourceHandleCFNet.cpp b/Source/WebCore/platform/network/cf/ResourceHandleCFNet.cpp
index 66ae5a0..52b100f 100644
--- a/Source/WebCore/platform/network/cf/ResourceHandleCFNet.cpp
+++ b/Source/WebCore/platform/network/cf/ResourceHandleCFNet.cpp
@@ -126,12 +126,7 @@ static void setDefaultMIMEType(CFURLResponseRef response)
static String encodeBasicAuthorization(const String& user, const String& password)
{
- CString unencodedString = (user + ":" + password).utf8();
- Vector<char> unencoded(unencodedString.length());
- std::copy(unencodedString.data(), unencodedString.data() + unencodedString.length(), unencoded.begin());
- Vector<char> encoded;
- base64Encode(unencoded, encoded);
- return String(encoded.data(), encoded.size());
+ return base64Encode((user + ":" + password).utf8());
}
CFURLRequestRef willSendRequest(CFURLConnectionRef conn, CFURLRequestRef cfRequest, CFURLResponseRef cfRedirectResponse, const void* clientInfo)
diff --git a/Source/WebCore/platform/network/cf/ResourceRequestCFNet.cpp b/Source/WebCore/platform/network/cf/ResourceRequestCFNet.cpp
index 410a649..7a1dfd5 100644
--- a/Source/WebCore/platform/network/cf/ResourceRequestCFNet.cpp
+++ b/Source/WebCore/platform/network/cf/ResourceRequestCFNet.cpp
@@ -26,16 +26,22 @@
#include "config.h"
#include "ResourceRequestCFNet.h"
-#if USE(CFNETWORK)
-
-#include "FormDataStreamCFNet.h"
#include "ResourceRequest.h"
+#if PLATFORM(MAC)
+#include "WebCoreSystemInterface.h"
+#endif
+
+#if USE(CFNETWORK)
+#include "FormDataStreamCFNet.h"
#include <CFNetwork/CFURLRequestPriv.h>
#include <WebKitSystemInterface/WebKitSystemInterface.h>
+#endif
namespace WebCore {
+#if USE(CFNETWORK)
+
typedef void (*CFURLRequestSetContentDispositionEncodingFallbackArrayFunction)(CFMutableURLRequestRef, CFArrayRef);
typedef CFArrayRef (*CFURLRequestCopyContentDispositionEncodingFallbackArrayFunction)(CFURLRequestRef);
@@ -189,12 +195,43 @@ void ResourceRequest::doUpdateResourceRequest()
m_httpBody = httpBodyFromRequest(m_cfRequest.get());
}
+#endif // USE(CFNETWORK)
+
unsigned initializeMaximumHTTPConnectionCountPerHost()
{
static const unsigned preferredConnectionCount = 6;
- return wkInitializeMaximumHTTPConnectionCountPerHost(preferredConnectionCount);
+ static const unsigned unlimitedConnectionCount = 10000;
+
+ // Always set the connection count per host, even when pipelining.
+ unsigned maximumHTTPConnectionCountPerHost = wkInitializeMaximumHTTPConnectionCountPerHost(preferredConnectionCount);
+
+#if PLATFORM(MAC)
+ if (isHTTPPipeliningEnabled()) {
+ // When pipelining do not rate-limit requests sent from WebCore since CFNetwork handles that.
+ return unlimitedConnectionCount;
+ }
+#endif
+
+ return maximumHTTPConnectionCountPerHost;
}
-} // namespace WebCore
+static inline bool readBooleanPreference(CFStringRef key)
+{
+ Boolean keyExistsAndHasValidFormat;
+ Boolean result = CFPreferencesGetAppBooleanValue(key, kCFPreferencesCurrentApplication, &keyExistsAndHasValidFormat);
+ return keyExistsAndHasValidFormat ? result : false;
+}
-#endif // USE(CFNETWORK)
+bool isHTTPPipeliningEnabled()
+{
+ static bool isEnabled = readBooleanPreference(CFSTR("WebKitEnableHTTPPipelining"));
+ return isEnabled;
+}
+
+bool shouldForceHTTPPipeliningPriorityHigh()
+{
+ static bool shouldForcePriorityHigh = readBooleanPreference(CFSTR("WebKitForceHTTPPipeliningPriorityHigh"));
+ return shouldForcePriorityHigh;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/platform/network/cf/ResourceRequestCFNet.h b/Source/WebCore/platform/network/cf/ResourceRequestCFNet.h
index 39587a4..09f4cea 100644
--- a/Source/WebCore/platform/network/cf/ResourceRequestCFNet.h
+++ b/Source/WebCore/platform/network/cf/ResourceRequestCFNet.h
@@ -26,18 +26,55 @@
#ifndef ResourceRequestCFNet_h
#define ResourceRequestCFNet_h
-#if USE(CFNETWORK)
+#include "ResourceLoadPriority.h"
+#if USE(CFNETWORK)
typedef const struct _CFURLRequest* CFURLRequestRef;
+#endif
namespace WebCore {
- class ResourceRequest;
+class ResourceRequest;
+
+#if USE(CFNETWORK)
+void getResourceRequest(ResourceRequest&, CFURLRequestRef);
+CFURLRequestRef cfURLRequest(const ResourceRequest&);
+#endif
+
+inline ResourceLoadPriority mapHTTPPipeliningPriorityToResourceLoadPriority(int priority)
+{
+ switch (priority) {
+ case 0:
+ return ResourceLoadPriorityLow;
+ case 1:
+ return ResourceLoadPriorityMedium;
+ case 2:
+ return ResourceLoadPriorityHigh;
+ default:
+ ASSERT_NOT_REACHED();
+ return ResourceLoadPriorityLowest;
+ }
+}
+
+inline int mapResourceLoadPriorityToHTTPPipeliningPriority(ResourceLoadPriority priority)
+{
+ switch (priority) {
+ case ResourceLoadPriorityVeryLow:
+ case ResourceLoadPriorityLow:
+ return 0;
+ case ResourceLoadPriorityMedium:
+ return 1;
+ case ResourceLoadPriorityHigh:
+ return 2;
+ case ResourceLoadPriorityUnresolved:
+ ASSERT_NOT_REACHED();
+ return 0;
+ }
- void getResourceRequest(ResourceRequest&, CFURLRequestRef);
- CFURLRequestRef cfURLRequest(const ResourceRequest&);
+ ASSERT_NOT_REACHED();
+ return 0;
}
-#endif // USE(CFNETWORK)
+} // namespace WebCore
#endif // ResourceRequestCFNet_h
diff --git a/Source/WebCore/platform/network/cf/SocketStreamHandle.h b/Source/WebCore/platform/network/cf/SocketStreamHandle.h
index df1d4a3..fbda3bc 100644
--- a/Source/WebCore/platform/network/cf/SocketStreamHandle.h
+++ b/Source/WebCore/platform/network/cf/SocketStreamHandle.h
@@ -36,6 +36,7 @@
#include "SocketStreamHandleBase.h"
#include <wtf/RetainPtr.h>
+typedef struct __CFHTTPMessage* CFHTTPMessageRef;
namespace WebCore {
diff --git a/Source/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp b/Source/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp
index 821b1ca..06454a7 100644
--- a/Source/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp
+++ b/Source/WebCore/platform/network/cf/SocketStreamHandleCFNet.cpp
@@ -47,6 +47,7 @@
#if PLATFORM(WIN)
#include "LoaderRunLoopCF.h"
+#include <CFNetwork/CFNetwork.h>
#include <WebKitSystemInterface/WebKitSystemInterface.h>
#else
#include "WebCoreSystemInterface.h"
diff --git a/Source/WebCore/platform/network/chromium/ResourceRequest.cpp b/Source/WebCore/platform/network/chromium/ResourceRequest.cpp
index 69591c1..519c63f 100644
--- a/Source/WebCore/platform/network/chromium/ResourceRequest.cpp
+++ b/Source/WebCore/platform/network/chromium/ResourceRequest.cpp
@@ -43,6 +43,7 @@ PassOwnPtr<CrossThreadResourceRequestData> ResourceRequest::doPlatformCopyData(P
data->m_requestorProcessID = m_requestorProcessID;
data->m_appCacheHostID = m_appCacheHostID;
data->m_hasUserGesture = m_hasUserGesture;
+ data->m_downloadToFile = m_downloadToFile;
return data;
}
@@ -52,6 +53,7 @@ void ResourceRequest::doPlatformAdopt(PassOwnPtr<CrossThreadResourceRequestData>
m_requestorProcessID = data->m_requestorProcessID;
m_appCacheHostID = data->m_appCacheHostID;
m_hasUserGesture = data->m_hasUserGesture;
+ m_downloadToFile = data->m_downloadToFile;
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/network/chromium/ResourceRequest.h b/Source/WebCore/platform/network/chromium/ResourceRequest.h
index 41ad6e0..07b31eb 100644
--- a/Source/WebCore/platform/network/chromium/ResourceRequest.h
+++ b/Source/WebCore/platform/network/chromium/ResourceRequest.h
@@ -42,6 +42,7 @@ namespace WebCore {
, m_requestorProcessID(0)
, m_appCacheHostID(0)
, m_hasUserGesture(false)
+ , m_downloadToFile(false)
{
}
@@ -51,6 +52,7 @@ namespace WebCore {
, m_requestorProcessID(0)
, m_appCacheHostID(0)
, m_hasUserGesture(false)
+ , m_downloadToFile(false)
{
}
@@ -60,6 +62,7 @@ namespace WebCore {
, m_requestorProcessID(0)
, m_appCacheHostID(0)
, m_hasUserGesture(false)
+ , m_downloadToFile(false)
{
setHTTPReferrer(referrer);
}
@@ -70,6 +73,7 @@ namespace WebCore {
, m_requestorProcessID(0)
, m_appCacheHostID(0)
, m_hasUserGesture(false)
+ , m_downloadToFile(false)
{
}
@@ -92,6 +96,10 @@ namespace WebCore {
bool hasUserGesture() const { return m_hasUserGesture; }
void setHasUserGesture(bool hasUserGesture) { m_hasUserGesture = hasUserGesture; }
+ // True if request should be downloaded to file.
+ bool downloadToFile() const { return m_downloadToFile; }
+ void setDownloadToFile(bool downloadToFile) { m_downloadToFile = downloadToFile; }
+
private:
friend class ResourceRequestBase;
@@ -105,6 +113,7 @@ namespace WebCore {
int m_requestorProcessID;
int m_appCacheHostID;
bool m_hasUserGesture;
+ bool m_downloadToFile;
};
struct CrossThreadResourceRequestData : public CrossThreadResourceRequestDataBase {
@@ -112,6 +121,7 @@ namespace WebCore {
int m_requestorProcessID;
int m_appCacheHostID;
bool m_hasUserGesture;
+ bool m_downloadToFile;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/network/chromium/ResourceResponse.cpp b/Source/WebCore/platform/network/chromium/ResourceResponse.cpp
index acd44d3..fc8ac62 100644
--- a/Source/WebCore/platform/network/chromium/ResourceResponse.cpp
+++ b/Source/WebCore/platform/network/chromium/ResourceResponse.cpp
@@ -39,6 +39,8 @@ PassOwnPtr<CrossThreadResourceResponseData> ResourceResponse::doPlatformCopyData
data->m_wasAlternateProtocolAvailable = m_wasAlternateProtocolAvailable;
data->m_wasFetchedViaProxy = m_wasFetchedViaProxy;
data->m_responseTime = m_responseTime;
+ data->m_socketAddress = m_socketAddress;
+ data->m_downloadFilePath = m_downloadFilePath;
return data;
}
@@ -53,6 +55,8 @@ void ResourceResponse::doPlatformAdopt(PassOwnPtr<CrossThreadResourceResponseDat
m_wasAlternateProtocolAvailable = data->m_wasAlternateProtocolAvailable;
m_wasFetchedViaProxy = data->m_wasFetchedViaProxy;
m_responseTime = data->m_responseTime;
+ m_socketAddress = data->m_socketAddress;
+ m_downloadFilePath = data->m_downloadFilePath;
}
} // namespace WebCore
diff --git a/Source/WebCore/platform/network/chromium/ResourceResponse.h b/Source/WebCore/platform/network/chromium/ResourceResponse.h
index 5e99994..35f13d1 100644
--- a/Source/WebCore/platform/network/chromium/ResourceResponse.h
+++ b/Source/WebCore/platform/network/chromium/ResourceResponse.h
@@ -96,6 +96,12 @@ namespace WebCore {
double responseTime() const { return m_responseTime; }
void setResponseTime(double responseTime) { m_responseTime = responseTime; }
+ const String& socketAddress() const { return m_socketAddress; }
+ void setSocketAddress(const String& value) { m_socketAddress = value; }
+
+ const String& downloadFilePath() const { return m_downloadFilePath; }
+ void setDownloadFilePath(const String& downloadFilePath) { m_downloadFilePath = downloadFilePath; }
+
private:
friend class ResourceResponseBase;
@@ -143,6 +149,13 @@ namespace WebCore {
// The time at which the response headers were received. For cached
// responses, this time could be "far" in the past.
double m_responseTime;
+
+ // Remote address of the socket which fetched this resource, for presenting
+ // to inquisitive users. Can be "ipv4:port", "[ipv6]:port", or empty.
+ String m_socketAddress;
+
+ // The path to the downloaded file.
+ String m_downloadFilePath;
};
struct CrossThreadResourceResponseData : public CrossThreadResourceResponseDataBase {
@@ -155,6 +168,8 @@ namespace WebCore {
bool m_wasAlternateProtocolAvailable;
bool m_wasFetchedViaProxy;
double m_responseTime;
+ String m_socketAddress;
+ String m_downloadFilePath;
};
} // namespace WebCore
diff --git a/Source/WebCore/platform/network/mac/AuthenticationMac.mm b/Source/WebCore/platform/network/mac/AuthenticationMac.mm
index efa42d9..a187187 100644
--- a/Source/WebCore/platform/network/mac/AuthenticationMac.mm
+++ b/Source/WebCore/platform/network/mac/AuthenticationMac.mm
@@ -31,6 +31,7 @@
#import "AuthenticationClient.h"
#import "Credential.h"
#import "ProtectionSpace.h"
+#import <wtf/UnusedParam.h>
#import <Foundation/NSURLAuthenticationChallenge.h>
#import <Foundation/NSURLCredential.h>
@@ -86,6 +87,20 @@ using namespace WebCore;
m_client->receivedCancellation(core(challenge));
}
+- (void)performDefaultHandlingForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
+{
+ // FIXME: <rdar://problem/8995483> Determine what, if anything, we should do here.
+ ASSERT_NOT_REACHED();
+ UNUSED_PARAM(challenge);
+}
+
+- (void)rejectProtectionSpaceAndContinueWithChallenge:(NSURLAuthenticationChallenge *)challenge
+{
+ // FIXME: <rdar://problem/8995483> Determine what, if anything, we should do here.
+ ASSERT_NOT_REACHED();
+ UNUSED_PARAM(challenge);
+}
+
@end
namespace WebCore {
diff --git a/Source/WebCore/platform/network/mac/FormDataStreamMac.mm b/Source/WebCore/platform/network/mac/FormDataStreamMac.mm
index 03f4579..eb6f601 100644
--- a/Source/WebCore/platform/network/mac/FormDataStreamMac.mm
+++ b/Source/WebCore/platform/network/mac/FormDataStreamMac.mm
@@ -185,9 +185,7 @@ static bool advanceCurrentStream(FormStreamFields* form)
}
#endif
const String& path = nextInput.m_shouldGenerateFile ? nextInput.m_generatedFilename : nextInput.m_filename;
- RetainPtr<CFStringRef> filename(AdoptCF, path.createCFString());
- RetainPtr<CFURLRef> fileURL(AdoptCF, CFURLCreateWithFileSystemPath(0, filename.get(), kCFURLPOSIXPathStyle, FALSE));
- form->currentStream = CFReadStreamCreateWithFile(0, fileURL.get());
+ form->currentStream = CFReadStreamCreateWithFile(0, pathAsURL(path).get());
if (!form->currentStream) {
// The file must have been removed or become unreadable.
return false;
diff --git a/Source/WebCore/platform/network/mac/ResourceHandleMac.mm b/Source/WebCore/platform/network/mac/ResourceHandleMac.mm
index 84b656c..2d687c0 100644
--- a/Source/WebCore/platform/network/mac/ResourceHandleMac.mm
+++ b/Source/WebCore/platform/network/mac/ResourceHandleMac.mm
@@ -164,12 +164,7 @@ public:
#ifndef BUILDING_ON_TIGER
static String encodeBasicAuthorization(const String& user, const String& password)
{
- CString unencodedString = (user + ":" + password).utf8();
- Vector<char> unencoded(unencodedString.length());
- std::copy(unencodedString.data(), unencodedString.data() + unencodedString.length(), unencoded.begin());
- Vector<char> encoded;
- base64Encode(unencoded, encoded);
- return String(encoded.data(), encoded.size());
+ return base64Encode((user + ":" + password).utf8());
}
#endif
diff --git a/Source/WebCore/platform/network/mac/ResourceRequestMac.mm b/Source/WebCore/platform/network/mac/ResourceRequestMac.mm
index f0357e5..640d237 100644
--- a/Source/WebCore/platform/network/mac/ResourceRequestMac.mm
+++ b/Source/WebCore/platform/network/mac/ResourceRequestMac.mm
@@ -31,6 +31,8 @@
#import "WebCoreSystemInterface.h"
#import "FormDataStreamMac.h"
+#import "ResourceRequestCFNet.h"
+#import "WebCoreSystemInterface.h"
#import <Foundation/Foundation.h>
@@ -65,7 +67,12 @@ void ResourceRequest::doUpdateResourceRequest()
if (NSString* method = [m_nsRequest.get() HTTPMethod])
m_httpMethod = method;
m_allowCookies = [m_nsRequest.get() HTTPShouldHandleCookies];
-
+
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+ if (isHTTPPipeliningEnabled() && !shouldForceHTTPPipeliningPriorityHigh())
+ m_priority = mapHTTPPipeliningPriorityToResourceLoadPriority(wkGetHTTPPipeliningPriority(m_nsRequest.get()));
+#endif
+
NSDictionary *headers = [m_nsRequest.get() allHTTPHeaderFields];
NSEnumerator *e = [headers keyEnumerator];
NSString *name;
@@ -111,6 +118,13 @@ void ResourceRequest::doUpdatePlatformRequest()
wkSupportsMultipartXMixedReplace(nsRequest);
#endif
+#if !defined(BUILDING_ON_TIGER) && !defined(BUILDING_ON_LEOPARD) && !defined(BUILDING_ON_SNOW_LEOPARD)
+ if (isHTTPPipeliningEnabled()) {
+ int priority = mapResourceLoadPriorityToHTTPPipeliningPriority(m_priority);
+ wkSetHTTPPipeliningPriority(nsRequest, shouldForceHTTPPipeliningPriorityHigh() ? 2 : priority);
+ }
+#endif
+
[nsRequest setCachePolicy:(NSURLRequestCachePolicy)cachePolicy()];
if (timeoutInterval() != unspecifiedTimeoutInterval)
[nsRequest setTimeoutInterval:timeoutInterval()];
@@ -154,12 +168,6 @@ void ResourceRequest::applyWebArchiveHackForMail()
// Hack because Mail checks for this property to detect data / archive loads
[NSURLProtocol setProperty:@"" forKey:@"WebDataRequest" inRequest:(NSMutableURLRequest *)nsURLRequest()];
}
-
-unsigned initializeMaximumHTTPConnectionCountPerHost()
-{
- static const unsigned preferredConnectionCount = 6;
- return wkInitializeMaximumHTTPConnectionCountPerHost(preferredConnectionCount);
-}
} // namespace WebCore
diff --git a/Source/WebCore/platform/network/qt/QtNAMThreadSafeProxy.cpp b/Source/WebCore/platform/network/qt/QtNAMThreadSafeProxy.cpp
index e0d6e69..a98b4f4 100644
--- a/Source/WebCore/platform/network/qt/QtNAMThreadSafeProxy.cpp
+++ b/Source/WebCore/platform/network/qt/QtNAMThreadSafeProxy.cpp
@@ -35,6 +35,18 @@ QtNAMThreadSafeProxy::QtNAMThreadSafeProxy(QNetworkAccessManager *manager)
connect(this, SIGNAL(localSetCookiesRequested(const QUrl&, const QString&)), SLOT(localSetCookies(const QUrl&, const QString&)));
connect(this, SIGNAL(localCookiesForUrlRequested(const QUrl&, bool*, QList<QNetworkCookie>*)), SLOT(localCookiesForUrl(const QUrl&, bool*, QList<QNetworkCookie>*)));
connect(this, SIGNAL(localWillLoadFromCacheRequested(const QUrl&, bool*, bool*)), SLOT(localWillLoadFromCache(const QUrl&, bool*, bool*)));
+ connect(this, SIGNAL(hasCookieJarRequested(bool*, bool*)), SLOT(hasCookieJar(bool*, bool*)));
+}
+
+bool QtNAMThreadSafeProxy::hasCookieJar()
+{
+ bool result;
+ bool done = false;
+ emit hasCookieJarRequested(&done, &result);
+ QMutexLocker lock(&m_resultMutex);
+ while (!done)
+ m_resultWaitCondition.wait(&m_resultMutex);
+ return result;
}
void QtNAMThreadSafeProxy::localSetCookies(const QUrl& url, const QString& cookies)
@@ -69,6 +81,14 @@ void QtNAMThreadSafeProxy::localWillLoadFromCache(const QUrl& url, bool* done, b
m_resultWaitCondition.wakeAll();
}
+void QtNAMThreadSafeProxy::hasCookieJar(bool* done, bool* result)
+{
+ QMutexLocker lock(&m_resultMutex);
+ *result = !!m_manager->cookieJar();
+ *done = true;
+ m_resultWaitCondition.wakeAll();
+}
+
QtNetworkReplyThreadSafeProxy::QtNetworkReplyThreadSafeProxy(QNetworkAccessManager *manager)
: m_manager(manager)
, m_reply(0)
diff --git a/Source/WebCore/platform/network/qt/QtNAMThreadSafeProxy.h b/Source/WebCore/platform/network/qt/QtNAMThreadSafeProxy.h
index ae963cf..4906fe2 100644
--- a/Source/WebCore/platform/network/qt/QtNAMThreadSafeProxy.h
+++ b/Source/WebCore/platform/network/qt/QtNAMThreadSafeProxy.h
@@ -67,15 +67,19 @@ public:
return result;
}
+ bool hasCookieJar();
+
signals:
void localSetCookiesRequested(const QUrl&, const QString& cookies);
void localCookiesForUrlRequested(const QUrl&, bool* done, QList<QNetworkCookie>* result);
void localWillLoadFromCacheRequested(const QUrl&, bool* done, bool* result);
+ void hasCookieJarRequested(bool* done, bool* result);
private slots:
void localSetCookies(const QUrl&, const QString& cookies);
void localCookiesForUrl(const QUrl&, bool* done, QList<QNetworkCookie>* result);
void localWillLoadFromCache(const QUrl&, bool* done, bool* result);
+ void hasCookieJar(bool* done, bool* result);
private:
QNetworkAccessManager* m_manager;
diff --git a/Source/WebCore/platform/network/soup/CookieJarSoup.cpp b/Source/WebCore/platform/network/soup/CookieJarSoup.cpp
index ba29622..e2c2f05 100644
--- a/Source/WebCore/platform/network/soup/CookieJarSoup.cpp
+++ b/Source/WebCore/platform/network/soup/CookieJarSoup.cpp
@@ -38,9 +38,7 @@ SoupCookieJar* defaultCookieJar()
cookiesInitialized = true;
cookieJar = soup_cookie_jar_new();
-#ifdef HAVE_LIBSOUP_2_29_90
soup_cookie_jar_set_accept_policy(cookieJar, SOUP_COOKIE_JAR_ACCEPT_NO_THIRD_PARTY);
-#endif
}
return cookieJar;
@@ -67,18 +65,12 @@ void setCookies(Document* document, const KURL& url, const String& value)
GOwnPtr<SoupURI> origin(soup_uri_new(url.string().utf8().data()));
-#ifdef HAVE_LIBSOUP_2_29_90
GOwnPtr<SoupURI> firstParty(soup_uri_new(document->firstPartyForCookies().string().utf8().data()));
soup_cookie_jar_set_cookie_with_first_party(jar,
origin.get(),
firstParty.get(),
value.utf8().data());
-#else
- soup_cookie_jar_set_cookie(jar,
- origin.get(),
- value.utf8().data());
-#endif
}
String cookies(const Document* /*document*/, const KURL& url)
diff --git a/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp b/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp
index a7170fe..3b1f157 100644
--- a/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp
+++ b/Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp
@@ -45,12 +45,14 @@
#include "ResourceHandleInternal.h"
#include "ResourceResponse.h"
#include "SharedBuffer.h"
-#include "soup-request-http.h"
#include "TextEncoding.h"
#include <errno.h>
#include <fcntl.h>
#include <gio/gio.h>
#include <glib.h>
+#define LIBSOUP_USE_UNSTABLE_REQUEST_API
+#include <libsoup/soup-request-http.h>
+#include <libsoup/soup-requester.h>
#include <libsoup/soup.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -127,7 +129,7 @@ static void cleanupSoupRequestOperation(ResourceHandle*, bool isDestroying);
static void sendRequestCallback(GObject*, GAsyncResult*, gpointer);
static void readCallback(GObject*, GAsyncResult*, gpointer);
static void closeCallback(GObject*, GAsyncResult*, gpointer);
-static bool startGio(ResourceHandle*, KURL);
+static bool startNonHTTPRequest(ResourceHandle*, KURL);
ResourceHandleInternal::~ResourceHandleInternal()
{
@@ -145,14 +147,48 @@ ResourceHandle::~ResourceHandle()
cleanupSoupRequestOperation(this, true);
}
+static void ensureSessionIsInitialized(SoupSession* session)
+{
+ // Values taken from http://stevesouders.com/ua/index.php following
+ // the rule "Do What Every Other Modern Browser Is Doing". They seem
+ // to significantly improve page loading time compared to soup's
+ // default values.
+ static const int maxConnections = 60;
+ static const int maxConnectionsPerHost = 6;
+
+ if (g_object_get_data(G_OBJECT(session), "webkit-init"))
+ return;
+
+ SoupCookieJar* jar = SOUP_COOKIE_JAR(soup_session_get_feature(session, SOUP_TYPE_COOKIE_JAR));
+ if (!jar)
+ soup_session_add_feature(session, SOUP_SESSION_FEATURE(defaultCookieJar()));
+ else
+ setDefaultCookieJar(jar);
+
+ 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_session_add_feature(session, SOUP_SESSION_FEATURE(logger));
+ g_object_unref(logger);
+ }
+
+ SoupRequester* requester = soup_requester_new();
+ soup_session_add_feature(session, SOUP_SESSION_FEATURE(requester));
+ g_object_unref(requester);
+
+ g_object_set(session,
+ SOUP_SESSION_MAX_CONNS, maxConnections,
+ SOUP_SESSION_MAX_CONNS_PER_HOST, maxConnectionsPerHost,
+ NULL);
+
+ g_object_set_data(G_OBJECT(session), "webkit-init", reinterpret_cast<void*>(0xdeadbeef));
+}
+
void ResourceHandle::prepareForURL(const KURL &url)
{
-#ifdef HAVE_LIBSOUP_2_29_90
GOwnPtr<SoupURI> soupURI(soup_uri_new(url.prettyURL().utf8().data()));
if (!soupURI)
return;
soup_session_prepare_for_uri(ResourceHandle::defaultSession(), soupURI.get());
-#endif
}
// All other kinds of redirections, except for the *304* status code
@@ -206,14 +242,12 @@ static void restartedCallback(SoupMessage* msg, gpointer data)
if (d->m_cancelled)
return;
-#ifdef HAVE_LIBSOUP_2_29_90
// Update the first party in case the base URL changed with the redirect
String firstPartyString = request.firstPartyForCookies().string();
if (!firstPartyString.isEmpty()) {
GOwnPtr<SoupURI> firstParty(soup_uri_new(firstPartyString.utf8().data()));
soup_message_set_first_party(d->m_soupMessage.get(), firstParty.get());
}
-#endif
}
static void contentSniffedCallback(SoupMessage*, const char*, GHashTable*, gpointer);
@@ -263,7 +297,26 @@ static void gotHeadersCallback(SoupMessage* msg, gpointer data)
client->didReceiveResponse(handle.get(), d->m_response);
}
-// This callback will not be called if the content sniffer is disabled in startHttp.
+static void wroteBodyDataCallback(SoupMessage*, SoupBuffer* buffer, gpointer data)
+{
+ RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(data);
+ if (!handle)
+ return;
+
+ ASSERT(buffer);
+ ResourceHandleInternal* internal = handle->getInternal();
+ internal->m_bodyDataSent += buffer->length;
+
+ if (internal->m_cancelled)
+ return;
+ ResourceHandleClient* client = handle->client();
+ if (!client)
+ return;
+
+ client->didSendData(handle.get(), internal->m_bodyDataSent, internal->m_bodySize);
+}
+
+// This callback will not be called if the content sniffer is disabled in startHTTPRequest.
static void contentSniffedCallback(SoupMessage* msg, const char* sniffedType, GHashTable *params, gpointer data)
{
if (sniffedType) {
@@ -312,136 +365,11 @@ static void gotChunkCallback(SoupMessage* msg, SoupBuffer* chunk, gpointer data)
client->didReceiveData(handle.get(), chunk->data, chunk->length, false);
}
-static gboolean parseDataUrl(gpointer callbackData)
-{
- ResourceHandle* handle = static_cast<ResourceHandle*>(callbackData);
- ResourceHandleClient* client = handle->client();
- ResourceHandleInternal* d = handle->getInternal();
- if (d->m_cancelled)
- return false;
-
- d->m_idleHandler = 0;
-
- ASSERT(client);
- if (!client)
- return false;
-
- String url = handle->firstRequest().url().string();
- ASSERT(url.startsWith("data:", false));
-
- int index = url.find(',');
- if (index == -1) {
- client->cannotShowURL(handle);
- return false;
- }
-
- String mediaType = url.substring(5, index - 5);
-
- bool isBase64 = mediaType.endsWith(";base64", false);
- if (isBase64)
- mediaType = mediaType.left(mediaType.length() - 7);
-
- if (mediaType.isEmpty())
- mediaType = "text/plain;charset=US-ASCII";
-
- String mimeType = extractMIMETypeFromMediaType(mediaType);
- String charset = extractCharsetFromMediaType(mediaType);
-
- ASSERT(d->m_response.isNull());
-
- d->m_response.setURL(handle->firstRequest().url());
- d->m_response.setMimeType(mimeType);
-
- // For non base64 encoded data we have to convert to UTF-16 early
- // due to limitations in KURL
- d->m_response.setTextEncodingName(isBase64 ? charset : "UTF-16");
- client->didReceiveResponse(handle, d->m_response);
-
- // The load may be cancelled, and the client may be destroyed
- // by any of the client reporting calls, so we check, and bail
- // out in either of those cases.
- if (d->m_cancelled || !handle->client())
- return false;
-
- SoupSession* session = handle->defaultSession();
- GOwnPtr<GError> error;
- d->m_soupRequest = adoptGRef(webkit_soup_requester_request(d->m_requester.get(), handle->firstRequest().url().string().utf8().data(), session, &error.outPtr()));
- if (error) {
- d->m_soupRequest = 0;
- client->didFinishLoading(handle, 0);
- return false;
- }
-
- d->m_inputStream = adoptGRef(webkit_soup_request_send(d->m_soupRequest.get(), 0, &error.outPtr()));
- if (error) {
- d->m_inputStream = 0;
- client->didFinishLoading(handle, 0);
- return false;
- }
-
- d->m_buffer = static_cast<char*>(g_slice_alloc0(READ_BUFFER_SIZE));
- d->m_total = 0;
-
- g_object_set_data(G_OBJECT(d->m_inputStream.get()), "webkit-resource", handle);
- // balanced by a deref() in cleanupSoupRequestOperation, which should always run
- handle->ref();
-
- d->m_cancellable = adoptGRef(g_cancellable_new());
- g_input_stream_read_async(d->m_inputStream.get(), d->m_buffer, READ_BUFFER_SIZE, G_PRIORITY_DEFAULT,
- d->m_cancellable.get(), readCallback, GINT_TO_POINTER(!isBase64));
-
- return false;
-}
-
-static bool startData(ResourceHandle* handle, String urlString)
-{
- 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_timeout_add(0, parseDataUrl, handle);
- return true;
-}
-
static SoupSession* createSoupSession()
{
return soup_session_async_new();
}
-// Values taken from http://stevesouders.com/ua/index.php following
-// the rule "Do What Every Other Modern Browser Is Doing". They seem
-// to significantly improve page loading time compared to soup's
-// default values.
-#define MAX_CONNECTIONS 60
-#define MAX_CONNECTIONS_PER_HOST 6
-
-static void ensureSessionIsInitialized(SoupSession* session)
-{
- if (g_object_get_data(G_OBJECT(session), "webkit-init"))
- return;
-
- 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);
-
- 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(session,
- SOUP_SESSION_MAX_CONNS, MAX_CONNECTIONS,
- SOUP_SESSION_MAX_CONNS_PER_HOST, MAX_CONNECTIONS_PER_HOST,
- NULL);
-
- g_object_set_data(G_OBJECT(session), "webkit-init", reinterpret_cast<void*>(0xdeadbeef));
-}
-
static void cleanupSoupRequestOperation(ResourceHandle* handle, bool isDestroying = false)
{
ResourceHandleInternal* d = handle->getInternal();
@@ -495,14 +423,14 @@ static void sendRequestCallback(GObject* source, GAsyncResult* res, gpointer use
}
GOwnPtr<GError> error;
- GInputStream* in = webkit_soup_request_send_finish(d->m_soupRequest.get(), res, &error.outPtr());
+ GInputStream* in = soup_request_send_finish(d->m_soupRequest.get(), res, &error.outPtr());
if (error) {
SoupMessage* soupMsg = d->m_soupMessage.get();
gboolean isTransportError = d->m_soupMessage && SOUP_STATUS_IS_TRANSPORT_ERROR(soupMsg->status_code);
if (isTransportError || (error->domain == G_IO_ERROR)) {
- SoupURI* uri = webkit_soup_request_get_uri(d->m_soupRequest.get());
+ SoupURI* uri = soup_request_get_uri(d->m_soupRequest.get());
GOwnPtr<char> uriStr(soup_uri_to_string(uri, false));
gint errorCode = isTransportError ? static_cast<gint>(soupMsg->status_code) : error->code;
const gchar* errorMsg = isTransportError ? soupMsg->reason_phrase : error->message;
@@ -550,13 +478,14 @@ static void sendRequestCallback(GObject* source, GAsyncResult* res, gpointer use
// readCallback needs it
g_object_set_data(G_OBJECT(d->m_inputStream.get()), "webkit-resource", handle.get());
- // Ensure a response is sent for any protocols that don't explicitly support responses
- // through got-headers signal or content sniffing.
- // (e.g. file and GIO based protocol).
- if (!handle->shouldContentSniff() && d->m_response.isNull()) {
+ // If not using SoupMessage we need to call didReceiveResponse now.
+ // (This will change later when SoupRequest supports content sniffing.)
+ if (!d->m_soupMessage) {
d->m_response.setURL(handle->firstRequest().url());
- d->m_response.setMimeType(webkit_soup_request_get_content_type(d->m_soupRequest.get()));
- d->m_response.setExpectedContentLength(webkit_soup_request_get_content_length(d->m_soupRequest.get()));
+ const gchar* contentType = soup_request_get_content_type(d->m_soupRequest.get());
+ d->m_response.setMimeType(extractMIMETypeFromMediaType(contentType));
+ d->m_response.setTextEncodingName(extractCharsetFromMediaType(contentType));
+ d->m_response.setExpectedContentLength(soup_request_get_content_length(d->m_soupRequest.get()));
client->didReceiveResponse(handle.get(), d->m_response);
if (d->m_cancelled) {
@@ -572,12 +501,56 @@ static void sendRequestCallback(GObject* source, GAsyncResult* res, gpointer use
G_PRIORITY_DEFAULT, d->m_cancellable.get(), readCallback, 0);
}
-static bool startHttp(ResourceHandle* handle)
+static bool addFormElementsToSoupMessage(SoupMessage* message, const char* contentType, FormData* httpBody, unsigned long& totalBodySize)
+{
+ size_t numElements = httpBody->elements().size();
+ if (numElements < 2) { // No file upload is the most common case.
+ Vector<char> body;
+ httpBody->flatten(body);
+ totalBodySize = body.size();
+ soup_message_set_request(message, contentType, SOUP_MEMORY_COPY, body.data(), body.size());
+ return true;
+ }
+
+ // We have more than one element to upload, and some may be large files,
+ // which we will want to mmap instead of copying into memory
+ soup_message_body_set_accumulate(message->request_body, FALSE);
+ for (size_t i = 0; i < numElements; i++) {
+ const FormDataElement& element = httpBody->elements()[i];
+
+ if (element.m_type == FormDataElement::data) {
+ totalBodySize += element.m_data.size();
+ soup_message_body_append(message->request_body, SOUP_MEMORY_TEMPORARY,
+ element.m_data.data(), element.m_data.size());
+ continue;
+ }
+
+ // This technique is inspired by libsoup's simple-httpd test.
+ GOwnPtr<GError> error;
+ CString fileName = fileSystemRepresentation(element.m_filename);
+ GMappedFile* fileMapping = g_mapped_file_new(fileName.data(), false, &error.outPtr());
+ if (error)
+ return false;
+
+ gsize mappedFileSize = g_mapped_file_get_length(fileMapping);
+ totalBodySize += mappedFileSize;
+ SoupBuffer* soupBuffer = soup_buffer_new_with_owner(g_mapped_file_get_contents(fileMapping),
+ mappedFileSize, fileMapping,
+ reinterpret_cast<GDestroyNotify>(g_mapped_file_unref));
+ soup_message_body_append_buffer(message->request_body, soupBuffer);
+ soup_buffer_free(soupBuffer);
+ }
+
+ return true;
+}
+
+static bool startHTTPRequest(ResourceHandle* handle)
{
ASSERT(handle);
SoupSession* session = handle->defaultSession();
ensureSessionIsInitialized(session);
+ SoupRequester* requester = SOUP_REQUESTER(soup_session_get_feature(session, SOUP_TYPE_REQUESTER));
ResourceHandleInternal* d = handle->getInternal();
@@ -587,7 +560,7 @@ static bool startHttp(ResourceHandle* handle)
request.setURL(url);
GOwnPtr<GError> error;
- d->m_soupRequest = adoptGRef(webkit_soup_requester_request(d->m_requester.get(), url.string().utf8().data(), session, &error.outPtr()));
+ d->m_soupRequest = adoptGRef(soup_requester_request(requester, url.string().utf8().data(), &error.outPtr()));
if (error) {
d->m_soupRequest = 0;
return false;
@@ -595,7 +568,7 @@ static bool startHttp(ResourceHandle* handle)
g_object_set_data(G_OBJECT(d->m_soupRequest.get()), "webkit-resource", handle);
- d->m_soupMessage = adoptGRef(webkit_soup_request_http_get_message(WEBKIT_SOUP_REQUEST_HTTP(d->m_soupRequest.get())));
+ d->m_soupMessage = adoptGRef(soup_request_http_get_message(SOUP_REQUEST_HTTP(d->m_soupRequest.get())));
if (!d->m_soupMessage)
return false;
@@ -609,65 +582,23 @@ static bool startHttp(ResourceHandle* handle)
g_signal_connect(soupMessage, "restarted", G_CALLBACK(restartedCallback), handle);
g_signal_connect(soupMessage, "got-headers", G_CALLBACK(gotHeadersCallback), handle);
+ g_signal_connect(soupMessage, "wrote-body-data", G_CALLBACK(wroteBodyDataCallback), handle);
d->m_gotChunkHandler = g_signal_connect(soupMessage, "got-chunk", G_CALLBACK(gotChunkCallback), handle);
-#ifdef HAVE_LIBSOUP_2_29_90
String firstPartyString = request.firstPartyForCookies().string();
if (!firstPartyString.isEmpty()) {
GOwnPtr<SoupURI> firstParty(soup_uri_new(firstPartyString.utf8().data()));
soup_message_set_first_party(soupMessage, firstParty.get());
}
-#endif
FormData* httpBody = d->m_firstRequest.httpBody();
- if (httpBody && !httpBody->isEmpty()) {
- 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(soupMessage, d->m_firstRequest.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(soupMessage->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(soupMessage->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
- */
- GOwnPtr<GError> error;
- CString fileName = fileSystemRepresentation(element.m_filename);
- GMappedFile* fileMapping = g_mapped_file_new(fileName.data(), false, &error.outPtr());
-
- if (error) {
- g_signal_handlers_disconnect_matched(soupMessage, G_SIGNAL_MATCH_DATA,
- 0, 0, 0, 0, handle);
- d->m_soupMessage.clear();
-
- 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_unref));
- soup_message_body_append_buffer(soupMessage->request_body, soupBuffer);
- soup_buffer_free(soupBuffer);
- }
- }
- }
+ CString contentType = d->m_firstRequest.httpContentType().utf8().data();
+ if (httpBody && !httpBody->isEmpty()
+ && !addFormElementsToSoupMessage(soupMessage, contentType.data(), httpBody, d->m_bodySize)) {
+ // We failed to prepare the body data, so just fail this load.
+ g_signal_handlers_disconnect_matched(soupMessage, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, handle);
+ d->m_soupMessage.clear();
+ return false;
}
// balanced by a deref() in cleanupSoupRequestOperation, which should always run
@@ -681,7 +612,7 @@ static bool startHttp(ResourceHandle* handle)
// Send the request only if it's not been explicitely deferred.
if (!d->m_defersLoading) {
d->m_cancellable = adoptGRef(g_cancellable_new());
- webkit_soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, 0);
+ soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, 0);
}
return true;
@@ -715,19 +646,13 @@ bool ResourceHandle::start(NetworkingContext* context)
// Used to set the authentication dialog toplevel; may be NULL
d->m_context = context;
- if (equalIgnoringCase(protocol, "data"))
- return startData(this, urlString);
-
if (equalIgnoringCase(protocol, "http") || equalIgnoringCase(protocol, "https")) {
- if (startHttp(this))
+ if (startHTTPRequest(this))
return true;
}
- if (equalIgnoringCase(protocol, "file") || equalIgnoringCase(protocol, "ftp") || equalIgnoringCase(protocol, "ftps")) {
- // FIXME: should we be doing any other protocols here?
- if (startGio(this, url))
- return true;
- }
+ if (startNonHTTPRequest(this, url))
+ return true;
// Error must not be reported immediately
this->scheduleFailure(InvalidURLFailure);
@@ -764,7 +689,7 @@ void ResourceHandle::platformSetDefersLoading(bool defersLoading)
if (!defersLoading && !d->m_cancellable && d->m_soupRequest.get()) {
d->m_cancellable = adoptGRef(g_cancellable_new());
- webkit_soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, 0);
+ soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, 0);
return;
}
@@ -795,11 +720,13 @@ bool ResourceHandle::willLoadFromCache(ResourceRequest&, Frame*)
void ResourceHandle::loadResourceSynchronously(NetworkingContext* context, const ResourceRequest& request, StoredCredentials /*storedCredentials*/, ResourceError& error, ResourceResponse& response, Vector<char>& data)
{
WebCoreSynchronousLoader syncLoader(error, response, data);
- // FIXME: we should use the ResourceHandle::create method here,
- // but it makes us timeout in a couple of tests. See
- // https://bugs.webkit.org/show_bug.cgi?id=41823
- RefPtr<ResourceHandle> handle = adoptRef(new ResourceHandle(request, &syncLoader, false /*defersLoading*/, false /*shouldContentSniff*/));
- handle->start(context);
+ RefPtr<ResourceHandle> handle = create(context, request, &syncLoader, false /*defersLoading*/, false /*shouldContentSniff*/);
+ if (!handle)
+ return;
+
+ // If the request has already failed, do not run the main loop, or else we'll block indefinitely.
+ if (handle->d->m_scheduledFailureType != NoFailure)
+ return;
syncLoader.run();
}
@@ -811,18 +738,8 @@ static void closeCallback(GObject* source, GAsyncResult* res, gpointer)
return;
ResourceHandleInternal* d = handle->getInternal();
- ResourceHandleClient* client = handle->client();
-
g_input_stream_close_finish(d->m_inputStream.get(), res, 0);
cleanupSoupRequestOperation(handle.get());
-
- // The load may have been cancelled, the client may have been
- // destroyed already. In such cases calling didFinishLoading is a
- // bad idea.
- if (d->m_cancelled || !client)
- return;
-
- client->didFinishLoading(handle.get(), 0);
}
static void readCallback(GObject* source, GAsyncResult* asyncResult, gpointer data)
@@ -844,7 +761,7 @@ static void readCallback(GObject* source, GAsyncResult* asyncResult, gpointer da
gssize bytesRead = g_input_stream_read_finish(d->m_inputStream.get(), asyncResult, &error.outPtr());
if (error) {
- SoupURI* uri = webkit_soup_request_get_uri(d->m_soupRequest.get());
+ SoupURI* uri = soup_request_get_uri(d->m_soupRequest.get());
GOwnPtr<char> uriStr(soup_uri_to_string(uri, false));
ResourceError resourceError(g_quark_to_string(G_IO_ERROR), error->code, uriStr.get(),
error ? String::fromUTF8(error->message) : String());
@@ -854,6 +771,10 @@ static void readCallback(GObject* source, GAsyncResult* asyncResult, gpointer da
}
if (!bytesRead) {
+ // Finish the load. We do not wait for the stream to
+ // close. Instead we better notify WebCore as soon as possible
+ client->didFinishLoading(handle.get(), 0);
+
g_input_stream_close_async(d->m_inputStream.get(), G_PRIORITY_DEFAULT,
0, closeCallback, 0);
return;
@@ -881,7 +802,7 @@ static void readCallback(GObject* source, GAsyncResult* asyncResult, gpointer da
d->m_cancellable.get(), readCallback, data);
}
-static bool startGio(ResourceHandle* handle, KURL url)
+static bool startNonHTTPRequest(ResourceHandle* handle, KURL url)
{
ASSERT(handle);
@@ -889,18 +810,14 @@ static bool startGio(ResourceHandle* handle, KURL url)
return false;
SoupSession* session = handle->defaultSession();
+ ensureSessionIsInitialized(session);
+ SoupRequester* requester = SOUP_REQUESTER(soup_session_get_feature(session, SOUP_TYPE_REQUESTER));
ResourceHandleInternal* d = handle->getInternal();
- // 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.removeFragmentIdentifier();
- url.setQuery(String());
- url.removePort();
CString urlStr = url.string().utf8();
GOwnPtr<GError> error;
- d->m_soupRequest = adoptGRef(webkit_soup_requester_request(d->m_requester.get(), urlStr.data(), session, &error.outPtr()));
+ d->m_soupRequest = adoptGRef(soup_requester_request(requester, urlStr.data(), &error.outPtr()));
if (error) {
d->m_soupRequest = 0;
return false;
@@ -912,7 +829,7 @@ static bool startGio(ResourceHandle* handle, KURL url)
handle->ref();
d->m_cancellable = adoptGRef(g_cancellable_new());
- webkit_soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, 0);
+ soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, 0);
return true;
}
diff --git a/Source/WebCore/platform/network/soup/ResourceRequestSoup.cpp b/Source/WebCore/platform/network/soup/ResourceRequestSoup.cpp
index d46e47b..5016bf1 100644
--- a/Source/WebCore/platform/network/soup/ResourceRequestSoup.cpp
+++ b/Source/WebCore/platform/network/soup/ResourceRequestSoup.cpp
@@ -46,13 +46,11 @@ void ResourceRequest::updateSoupMessage(SoupMessage* soupMessage) const
soup_message_headers_append(soupHeaders, it->first.string().utf8().data(), it->second.utf8().data());
}
-#ifdef HAVE_LIBSOUP_2_29_90
String firstPartyString = firstPartyForCookies().string();
if (!firstPartyString.isEmpty()) {
GOwnPtr<SoupURI> firstParty(soup_uri_new(firstPartyString.utf8().data()));
soup_message_set_first_party(soupMessage, firstParty.get());
}
-#endif
soup_message_set_flags(soupMessage, m_soupFlags);
}
@@ -71,13 +69,11 @@ SoupMessage* ResourceRequest::toSoupMessage() const
soup_message_headers_append(soupHeaders, it->first.string().utf8().data(), it->second.utf8().data());
}
-#ifdef HAVE_LIBSOUP_2_29_90
String firstPartyString = firstPartyForCookies().string();
if (!firstPartyString.isEmpty()) {
GOwnPtr<SoupURI> firstParty(soup_uri_new(firstPartyString.utf8().data()));
soup_message_set_first_party(soupMessage, firstParty.get());
}
-#endif
soup_message_set_flags(soupMessage, m_soupFlags);
@@ -104,11 +100,9 @@ void ResourceRequest::updateFromSoupMessage(SoupMessage* soupMessage)
if (soupMessage->request_body->data)
m_httpBody = FormData::create(soupMessage->request_body->data, soupMessage->request_body->length);
-#ifdef HAVE_LIBSOUP_2_29_90
SoupURI* firstParty = soup_message_get_first_party(soupMessage);
if (firstParty)
m_firstPartyForCookies = soupURIToKURL(firstParty);
-#endif
m_soupFlags = soup_message_get_flags(soupMessage);
diff --git a/Source/WebCore/platform/network/soup/SocketStreamHandle.h b/Source/WebCore/platform/network/soup/SocketStreamHandle.h
index 3168fae..c8fe3b3 100644
--- a/Source/WebCore/platform/network/soup/SocketStreamHandle.h
+++ b/Source/WebCore/platform/network/soup/SocketStreamHandle.h
@@ -60,7 +60,7 @@ namespace WebCore {
private:
GRefPtr<GSocketConnection> m_socketConnection;
GRefPtr<GInputStream> m_inputStream;
- GRefPtr<GOutputStream> m_outputStream;
+ GRefPtr<GPollableOutputStream> m_outputStream;
GRefPtr<GSource> m_writeReadySource;
char* m_readBuffer;
void* m_id;
diff --git a/Source/WebCore/platform/network/soup/SocketStreamHandleSoup.cpp b/Source/WebCore/platform/network/soup/SocketStreamHandleSoup.cpp
index 841e209..34382dd 100644
--- a/Source/WebCore/platform/network/soup/SocketStreamHandleSoup.cpp
+++ b/Source/WebCore/platform/network/soup/SocketStreamHandleSoup.cpp
@@ -50,7 +50,7 @@ namespace WebCore {
// These functions immediately call the similarly named SocketStreamHandle methods.
static void connectedCallback(GSocketClient*, GAsyncResult*, void*);
static void readReadyCallback(GInputStream*, GAsyncResult*, void*);
-static gboolean writeReadyCallback(GSocket*, GIOCondition, void*);
+static gboolean writeReadyCallback(GPollableOutputStream*, void*);
// Having a list of active handles means that we do not have to worry about WebCore
// reference counting in GLib callbacks. Once the handle is off the active handles list
@@ -82,13 +82,12 @@ SocketStreamHandle::SocketStreamHandle(const KURL& url, SocketStreamHandleClient
: SocketStreamHandleBase(url, client)
, m_readBuffer(0)
{
- // No support for SSL sockets yet.
- if (url.protocolIs("wss"))
- return;
- unsigned int port = url.hasPort() ? url.port() : 80;
+ unsigned int port = url.hasPort() ? url.port() : (url.protocolIs("wss") ? 443 : 80);
m_id = activateHandle(this);
GRefPtr<GSocketClient> socketClient = adoptGRef(g_socket_client_new());
+ if (url.protocolIs("wss"))
+ g_socket_client_set_tls(socketClient.get(), TRUE);
g_socket_client_connect_to_host_async(socketClient.get(), url.host().utf8().data(), port, 0,
reinterpret_cast<GAsyncReadyCallback>(connectedCallback), m_id);
}
@@ -108,7 +107,7 @@ void SocketStreamHandle::connected(GSocketConnection* socketConnection, GError*
}
m_socketConnection = adoptGRef(socketConnection);
- m_outputStream = g_io_stream_get_output_stream(G_IO_STREAM(m_socketConnection.get()));
+ m_outputStream = G_POLLABLE_OUTPUT_STREAM(g_io_stream_get_output_stream(G_IO_STREAM(m_socketConnection.get())));
m_inputStream = g_io_stream_get_input_stream(G_IO_STREAM(m_socketConnection.get()));
m_readBuffer = new char[READ_BUFFER_SIZE];
@@ -156,14 +155,14 @@ void SocketStreamHandle::writeReady()
int SocketStreamHandle::platformSend(const char* data, int length)
{
- if (!g_socket_condition_check(g_socket_connection_get_socket(m_socketConnection.get()), G_IO_OUT)) {
+ if (!g_pollable_output_stream_is_writable(m_outputStream.get())) {
beginWaitingForSocketWritability();
return 0;
}
GOwnPtr<GError> error;
- gssize written = g_output_stream_write(m_outputStream.get(), data, length, 0, &error.outPtr());
- if (error) {
+ gssize written = g_pollable_output_stream_write_nonblocking(m_outputStream.get(), data, length, 0, &error.outPtr());
+ if (error && !g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) {
m_client->didFail(this, SocketStreamError(error->code)); // FIXME: Provide a sensible error.
return 0;
}
@@ -222,8 +221,7 @@ void SocketStreamHandle::beginWaitingForSocketWritability()
if (m_writeReadySource) // Already waiting.
return;
- m_writeReadySource = adoptGRef(g_socket_create_source(
- g_socket_connection_get_socket(m_socketConnection.get()), static_cast<GIOCondition>(G_IO_OUT), 0));
+ m_writeReadySource = adoptGRef(g_pollable_output_stream_create_source(m_outputStream.get(), 0));
g_source_set_callback(m_writeReadySource.get(), reinterpret_cast<GSourceFunc>(writeReadyCallback), m_id, 0);
g_source_attach(m_writeReadySource.get(), 0);
}
@@ -266,24 +264,13 @@ static void readReadyCallback(GInputStream* stream, GAsyncResult* result, void*
handle->readBytes(bytesRead, error.get());
}
-static gboolean writeReadyCallback(GSocket*, GIOCondition condition, void* id)
+static gboolean writeReadyCallback(GPollableOutputStream*, void* id)
{
SocketStreamHandle* handle = getHandleFromId(id);
if (!handle)
return FALSE;
- // G_IO_HUP and G_IO_ERR are are always active. See:
- // http://library.gnome.org/devel/gio/stable/GSocket.html#g-socket-create-source
- if (condition & G_IO_HUP) {
- handle->close();
- return FALSE;
- }
- if (condition & G_IO_ERR) {
- handle->client()->didFail(handle, SocketStreamError(0)); // FIXME: Provide a sensible error.
- return FALSE;
- }
- if (condition & G_IO_OUT)
- handle->writeReady();
+ handle->writeReady();
return TRUE;
}
diff --git a/Source/WebCore/platform/network/soup/cache/soup-directory-input-stream.c b/Source/WebCore/platform/network/soup/cache/soup-directory-input-stream.c
deleted file mode 100644
index c14863b..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-directory-input-stream.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2008 Red Hat, Inc.
- * Copyright (C) 2010 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "soup-directory-input-stream.h"
-
-#include <libsoup/soup.h>
-#include <stdio.h>
-#include <string.h>
-
-#define INIT_STRING "<html><head><title>OMG!</title></head><body><table>"
-#define EXIT_STRING "</table></html>"
-
-G_DEFINE_TYPE (WebKitSoupDirectoryInputStream, webkit_soup_directory_input_stream, G_TYPE_INPUT_STREAM)
-
-static SoupBuffer *
-webkit_soup_directory_input_stream_parse_info (WebKitSoupDirectoryInputStream * stream,
- GFileInfo * info)
-{
- SoupBuffer *buffer;
- GString *string;
- const char *s;
- char *escaped, *path, *xml_string;
-
- if (!g_file_info_get_name (info))
- return NULL;
-
- s = g_file_info_get_display_name (info);
- if (!s) {
- s = g_file_info_get_name (info);
- /* FIXME: convert somehow? */
- if (!g_utf8_validate (s, -1, NULL))
- return NULL;
- }
- string = g_string_new ("<tr>");
-
- xml_string = g_markup_escape_text (s, -1);
- escaped = g_uri_escape_string (g_file_info_get_name (info), NULL, FALSE);
- path = g_strconcat (stream->uri, "/", escaped, NULL);
- g_free (escaped);
- g_string_append_printf (string, "<td><a href=\"%s\">%s</a></td>", path, xml_string);
- g_free (path);
- g_free (xml_string);
- g_string_append (string, "</tr>");
-
- buffer = soup_buffer_new (SOUP_MEMORY_TAKE, string->str, string->len);
- g_string_free (string, FALSE);
-
- return buffer;
-}
-
-static SoupBuffer *
-webkit_soup_directory_input_stream_read_next_file (WebKitSoupDirectoryInputStream *stream,
- GCancellable *cancellable,
- GError **error)
-{
- GFileInfo *info;
- SoupBuffer *buffer;
- GError *err = NULL;
-
- do {
- info = g_file_enumerator_next_file (stream->enumerator, cancellable, &err);
- if (info == NULL) {
- if (err) {
- g_propagate_error (error, err);
- return NULL;
- } else if (!stream->done) {
- stream->done = TRUE;
- return soup_buffer_new (SOUP_MEMORY_STATIC,
- EXIT_STRING,
- sizeof (EXIT_STRING));
- } else {
- return NULL;
- }
- }
-
- buffer = webkit_soup_directory_input_stream_parse_info (stream, info);
- } while (buffer == NULL);
-
- return buffer;
-}
-
-static gssize
-webkit_soup_directory_input_stream_read (GInputStream *input,
- void *buffer,
- gsize count,
- GCancellable *cancellable,
- GError **error)
-{
- WebKitSoupDirectoryInputStream *stream = WEBKIT_SOUP_DIRECTORY_INPUT_STREAM (input);
- gsize total, size;
-
- for (total = 0; total < count; total += size) {
- if (stream->buffer == NULL) {
- stream->buffer = webkit_soup_directory_input_stream_read_next_file (stream, cancellable, error);
- if (stream->buffer == NULL) {
- /* FIXME: Is this correct or should we forward the error? */
- if (total)
- g_clear_error (error);
- return total;
- }
- }
-
- size = MIN (stream->buffer->length, count - total);
- memcpy ((char *)buffer + total, stream->buffer->data, size);
- if (size == stream->buffer->length) {
- soup_buffer_free (stream->buffer);
- stream->buffer = NULL;
- } else {
- SoupBuffer *sub = soup_buffer_new_subbuffer (stream->buffer,
- size,
- stream->buffer->length - size);
- soup_buffer_free (stream->buffer);
- stream->buffer = sub;
- }
- }
-
- return total;
-}
-
-static gboolean
-webkit_soup_directory_input_stream_close (GInputStream *input,
- GCancellable *cancellable,
- GError **error)
-{
- WebKitSoupDirectoryInputStream *stream = WEBKIT_SOUP_DIRECTORY_INPUT_STREAM (input);
- gboolean result;
-
- if (stream->buffer) {
- soup_buffer_free (stream->buffer);
- stream->buffer = NULL;
- }
-
- result = g_file_enumerator_close (stream->enumerator,
- cancellable,
- error);
- g_object_unref (stream->enumerator);
- stream->enumerator = NULL;
-
- g_free (stream->uri);
- stream->uri = NULL;
-
- return result;
-}
-
-static void
-webkit_soup_directory_input_stream_class_init (WebKitSoupDirectoryInputStreamClass *stream_class)
-{
- GInputStreamClass *inputstream_class = G_INPUT_STREAM_CLASS (stream_class);
-
- inputstream_class->read_fn = webkit_soup_directory_input_stream_read;
- inputstream_class->close_fn = webkit_soup_directory_input_stream_close;
-}
-
-static void
-webkit_soup_directory_input_stream_init (WebKitSoupDirectoryInputStream *stream)
-{
- stream->buffer = soup_buffer_new (SOUP_MEMORY_STATIC,
- INIT_STRING,
- sizeof (INIT_STRING));
-}
-
-GInputStream *
-webkit_soup_directory_input_stream_new (GFileEnumerator *enumerator,
- SoupURI *uri)
-{
- GInputStream *stream;
-
- g_return_val_if_fail (G_IS_FILE_ENUMERATOR (enumerator), NULL);
- g_return_val_if_fail (uri != NULL, NULL);
-
- stream = g_object_new (WEBKIT_TYPE_SOUP_DIRECTORY_INPUT_STREAM, NULL);
-
- WEBKIT_SOUP_DIRECTORY_INPUT_STREAM (stream)->enumerator = g_object_ref (enumerator);
- WEBKIT_SOUP_DIRECTORY_INPUT_STREAM (stream)->uri = soup_uri_to_string (uri, FALSE);
-
- return stream;
-}
-
diff --git a/Source/WebCore/platform/network/soup/cache/soup-directory-input-stream.h b/Source/WebCore/platform/network/soup/cache/soup-directory-input-stream.h
deleted file mode 100644
index 0c5b0be..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-directory-input-stream.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2010 Red Hat, Inc.
- * Copyright (C) 2010 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef WEBKIT_SOUP_DIRECTORY_INPUT_STREAM_H
-#define WEBKIT_SOUP_DIRECTORY_INPUT_STREAM_H 1
-
-#include <gio/gio.h>
-#include <libsoup/soup-types.h>
-#include <libsoup/soup-message-body.h>
-
-G_BEGIN_DECLS
-
-#define WEBKIT_TYPE_SOUP_DIRECTORY_INPUT_STREAM (webkit_soup_directory_input_stream_get_type ())
-#define WEBKIT_SOUP_DIRECTORY_INPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), WEBKIT_TYPE_SOUP_DIRECTORY_INPUT_STREAM, WebKitSoupDirectoryInputStream))
-#define WEBKIT_SOUP_DIRECTORY_INPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), WEBKIT_TYPE_SOUP_DIRECTORY_INPUT_STREAM, WebKitSoupDirectoryInputStreamClass))
-#define WEBKIT_IS_SOUP_DIRECTORY_INPUT_STREAM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WEBKIT_TYPE_SOUP_DIRECTORY_INPUT_STREAM))
-#define WEBKIT_IS_SOUP_DIRECTORY_INPUT_STREAM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), WEBKIT_TYPE_SOUP_DIRECTORY_INPUT_STREAM))
-#define WEBKIT_SOUP_DIRECTORY_INPUT_STREAM_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), WEBKIT_TYPE_SOUP_DIRECTORY_INPUT_STREAM, WebKitSoupDirectoryInputStreamClass))
-
-typedef struct _WebKitSoupDirectoryInputStream WebKitSoupDirectoryInputStream;
-typedef struct _WebKitSoupDirectoryInputStreamClass WebKitSoupDirectoryInputStreamClass;
-
-struct _WebKitSoupDirectoryInputStream {
- GInputStream parent;
-
- GFileEnumerator *enumerator;
- char *uri;
- SoupBuffer *buffer;
- gboolean done;
-};
-
-struct _WebKitSoupDirectoryInputStreamClass {
- GInputStreamClass parent_class;
-};
-
-GType webkit_soup_directory_input_stream_get_type (void);
-
-GInputStream *webkit_soup_directory_input_stream_new (GFileEnumerator *enumerator,
- SoupURI *uri);
-
-
-G_END_DECLS
-
-#endif /* WEBKIT_SOUP_DIRECTORY_INPUT_STREAM_H */
diff --git a/Source/WebCore/platform/network/soup/cache/soup-http-input-stream.c b/Source/WebCore/platform/network/soup/cache/soup-http-input-stream.c
deleted file mode 100644
index 2a5d995..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-http-input-stream.c
+++ /dev/null
@@ -1,922 +0,0 @@
-/* soup-input-stream.c, based on gsocketinputstream.c
- *
- * Copyright (C) 2006-2007 Red Hat, Inc.
- * Copyright (C) 2010 Igalia, S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include <config.h>
-
-#include <string.h>
-
-#include <glib.h>
-#include <gio/gio.h>
-
-#include <libsoup/soup.h>
-
-#include "soup-http-input-stream.h"
-
-static void webkit_soup_http_input_stream_seekable_iface_init (GSeekableIface *seekable_iface);
-
-G_DEFINE_TYPE_WITH_CODE (WebKitSoupHTTPInputStream, webkit_soup_http_input_stream, G_TYPE_INPUT_STREAM,
- G_IMPLEMENT_INTERFACE (G_TYPE_SEEKABLE,
- webkit_soup_http_input_stream_seekable_iface_init))
-
-typedef void (*WebKitSoupHTTPInputStreamCallback)(GInputStream *);
-
-typedef struct {
- SoupSession *session;
- GMainContext *async_context;
- SoupMessage *msg;
- gboolean got_headers, finished;
- goffset offset;
-
- GCancellable *cancellable;
- GSource *cancel_watch;
- WebKitSoupHTTPInputStreamCallback got_headers_cb;
- WebKitSoupHTTPInputStreamCallback got_chunk_cb;
- WebKitSoupHTTPInputStreamCallback finished_cb;
- WebKitSoupHTTPInputStreamCallback cancelled_cb;
-
- guchar *leftover_buffer;
- gsize leftover_bufsize, leftover_offset;
-
- guchar *caller_buffer;
- gsize caller_bufsize, caller_nread;
- GAsyncReadyCallback outstanding_callback;
- GSimpleAsyncResult *result;
-} WebKitSoupHTTPInputStreamPrivate;
-#define WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), WEBKIT_TYPE_SOUP_HTTP_INPUT_STREAM, WebKitSoupHTTPInputStreamPrivate))
-
-
-static gssize webkit_soup_http_input_stream_read (GInputStream *stream,
- void *buffer,
- gsize count,
- GCancellable *cancellable,
- GError **error);
-static gboolean webkit_soup_http_input_stream_close (GInputStream *stream,
- GCancellable *cancellable,
- GError **error);
-static void webkit_soup_http_input_stream_read_async (GInputStream *stream,
- void *buffer,
- gsize count,
- int io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer data);
-static gssize webkit_soup_http_input_stream_read_finish (GInputStream *stream,
- GAsyncResult *result,
- GError **error);
-static void webkit_soup_http_input_stream_close_async (GInputStream *stream,
- int io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer data);
-static gboolean webkit_soup_http_input_stream_close_finish (GInputStream *stream,
- GAsyncResult *result,
- GError **error);
-
-static goffset webkit_soup_http_input_stream_tell (GSeekable *seekable);
-
-static gboolean webkit_soup_http_input_stream_can_seek (GSeekable *seekable);
-static gboolean webkit_soup_http_input_stream_seek (GSeekable *seekable,
- goffset offset,
- GSeekType type,
- GCancellable *cancellable,
- GError **error);
-
-static gboolean webkit_soup_http_input_stream_can_truncate (GSeekable *seekable);
-static gboolean webkit_soup_http_input_stream_truncate (GSeekable *seekable,
- goffset offset,
- GCancellable *cancellable,
- GError **error);
-
-static void webkit_soup_http_input_stream_got_headers (SoupMessage *msg, gpointer stream);
-static void webkit_soup_http_input_stream_got_chunk (SoupMessage *msg, SoupBuffer *chunk, gpointer stream);
-static void webkit_soup_http_input_stream_finished (SoupMessage *msg, gpointer stream);
-
-static void
-webkit_soup_http_input_stream_finalize (GObject *object)
-{
- WebKitSoupHTTPInputStream *stream = WEBKIT_SOUP_HTTP_INPUT_STREAM (object);
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
-
- g_object_unref (priv->session);
-
- g_signal_handlers_disconnect_by_func (priv->msg, G_CALLBACK (webkit_soup_http_input_stream_got_headers), stream);
- g_signal_handlers_disconnect_by_func (priv->msg, G_CALLBACK (webkit_soup_http_input_stream_got_chunk), stream);
- g_signal_handlers_disconnect_by_func (priv->msg, G_CALLBACK (webkit_soup_http_input_stream_finished), stream);
- g_object_unref (priv->msg);
- g_free (priv->leftover_buffer);
-
- if (G_OBJECT_CLASS (webkit_soup_http_input_stream_parent_class)->finalize)
- (*G_OBJECT_CLASS (webkit_soup_http_input_stream_parent_class)->finalize)(object);
-}
-
-static void
-webkit_soup_http_input_stream_class_init (WebKitSoupHTTPInputStreamClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass);
-
- g_type_class_add_private (klass, sizeof (WebKitSoupHTTPInputStreamPrivate));
-
- gobject_class->finalize = webkit_soup_http_input_stream_finalize;
-
- stream_class->read_fn = webkit_soup_http_input_stream_read;
- stream_class->close_fn = webkit_soup_http_input_stream_close;
- stream_class->read_async = webkit_soup_http_input_stream_read_async;
- stream_class->read_finish = webkit_soup_http_input_stream_read_finish;
- stream_class->close_async = webkit_soup_http_input_stream_close_async;
- stream_class->close_finish = webkit_soup_http_input_stream_close_finish;
-}
-
-static void
-webkit_soup_http_input_stream_seekable_iface_init (GSeekableIface *seekable_iface)
-{
- seekable_iface->tell = webkit_soup_http_input_stream_tell;
- seekable_iface->can_seek = webkit_soup_http_input_stream_can_seek;
- seekable_iface->seek = webkit_soup_http_input_stream_seek;
- seekable_iface->can_truncate = webkit_soup_http_input_stream_can_truncate;
- seekable_iface->truncate_fn = webkit_soup_http_input_stream_truncate;
-}
-
-static void
-webkit_soup_http_input_stream_init (WebKitSoupHTTPInputStream *stream)
-{
- ;
-}
-
-static void
-webkit_soup_http_input_stream_queue_message (WebKitSoupHTTPInputStream *stream)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
-
- priv->got_headers = priv->finished = FALSE;
-
- /* Add an extra ref since soup_session_queue_message steals one */
- g_object_ref (priv->msg);
- soup_session_queue_message (priv->session, priv->msg, NULL, NULL);
-}
-
-/**
- * webkit_soup_http_input_stream_new:
- * @session: the #SoupSession to use
- * @msg: the #SoupMessage whose response will be streamed
- *
- * Prepares to send @msg over @session, and returns a #GInputStream
- * that can be used to read the response.
- *
- * @msg may not be sent until the first read call; if you need to look
- * at the status code or response headers before reading the body, you
- * can use webkit_soup_http_input_stream_send() or webkit_soup_http_input_stream_send_async()
- * to force the message to be sent and the response headers read.
- *
- * If @msg gets a non-2xx result, the first read (or send) will return
- * an error with type %WEBKIT_SOUP_HTTP_INPUT_STREAM_HTTP_ERROR.
- *
- * Internally, #WebKitSoupHTTPInputStream is implemented using asynchronous I/O,
- * so if you are using the synchronous API (eg,
- * g_input_stream_read()), you should create a new #GMainContext and
- * set it as the %SOUP_SESSION_ASYNC_CONTEXT property on @session. (If
- * you don't, then synchronous #GInputStream calls will cause the main
- * loop to be run recursively.) The async #GInputStream API works fine
- * with %SOUP_SESSION_ASYNC_CONTEXT either set or unset.
- *
- * Returns: a new #GInputStream.
- **/
-WebKitSoupHTTPInputStream *
-webkit_soup_http_input_stream_new (SoupSession *session, SoupMessage *msg)
-{
- WebKitSoupHTTPInputStream *stream;
- WebKitSoupHTTPInputStreamPrivate *priv;
-
- g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
-
- stream = g_object_new (WEBKIT_TYPE_SOUP_HTTP_INPUT_STREAM, NULL);
- priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
-
- priv->session = g_object_ref (session);
- priv->async_context = soup_session_get_async_context (session);
- priv->msg = g_object_ref (msg);
-
- g_signal_connect (msg, "got_headers",
- G_CALLBACK (webkit_soup_http_input_stream_got_headers), stream);
- g_signal_connect (msg, "got_chunk",
- G_CALLBACK (webkit_soup_http_input_stream_got_chunk), stream);
- g_signal_connect (msg, "finished",
- G_CALLBACK (webkit_soup_http_input_stream_finished), stream);
-
- webkit_soup_http_input_stream_queue_message (stream);
- return stream;
-}
-
-static void
-webkit_soup_http_input_stream_got_headers (SoupMessage *msg, gpointer stream)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
-
- /* If the status is unsuccessful, we just ignore the signal and let
- * libsoup keep going (eventually either it will requeue the request
- * (after handling authentication/redirection), or else the
- * "finished" handler will run).
- */
- if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
- return;
-
- priv->got_headers = TRUE;
- if (!priv->caller_buffer) {
- /* Not ready to read the body yet */
- soup_session_pause_message (priv->session, msg);
- }
-
- if (priv->got_headers_cb)
- priv->got_headers_cb (stream);
-}
-
-static void
-webkit_soup_http_input_stream_got_chunk (SoupMessage *msg, SoupBuffer *chunk_buffer,
- gpointer stream)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
- const gchar *chunk = chunk_buffer->data;
- gsize chunk_size = chunk_buffer->length;
-
- /* We only pay attention to the chunk if it's part of a successful
- * response.
- */
- if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code))
- return;
-
- /* Sanity check */
- if (priv->caller_bufsize == 0 || priv->leftover_bufsize != 0)
- g_warning ("webkit_soup_http_input_stream_got_chunk called again before previous chunk was processed");
-
- /* Copy what we can into priv->caller_buffer */
- if (priv->caller_bufsize > priv->caller_nread) {
- gsize nread = MIN (chunk_size, priv->caller_bufsize - priv->caller_nread);
-
- memcpy (priv->caller_buffer + priv->caller_nread, chunk, nread);
- priv->caller_nread += nread;
- priv->offset += nread;
- chunk += nread;
- chunk_size -= nread;
- }
-
- if (chunk_size > 0) {
- /* Copy the rest into priv->leftover_buffer. If
- * there's already some data there, realloc and
- * append. Otherwise just copy.
- */
- if (priv->leftover_bufsize) {
- priv->leftover_buffer = g_realloc (priv->leftover_buffer,
- priv->leftover_bufsize + chunk_size);
- memcpy (priv->leftover_buffer + priv->leftover_bufsize,
- chunk, chunk_size);
- priv->leftover_bufsize += chunk_size;
- } else {
- priv->leftover_bufsize = chunk_size;
- priv->leftover_buffer = g_memdup (chunk, chunk_size);
- priv->leftover_offset = 0;
- }
- }
-
- soup_session_pause_message (priv->session, msg);
- if (priv->got_chunk_cb)
- priv->got_chunk_cb (stream);
-}
-
-static void
-webkit_soup_http_input_stream_finished (SoupMessage *msg, gpointer stream)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
-
- priv->finished = TRUE;
-
- if (priv->finished_cb)
- priv->finished_cb (stream);
-}
-
-static gboolean
-webkit_soup_http_input_stream_cancelled (GIOChannel *chan, GIOCondition condition,
- gpointer stream)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
-
- priv->cancel_watch = NULL;
-
- soup_session_pause_message (priv->session, priv->msg);
- if (priv->cancelled_cb)
- priv->cancelled_cb (stream);
-
- return FALSE;
-}
-
-static void
-webkit_soup_http_input_stream_prepare_for_io (GInputStream *stream,
- GCancellable *cancellable,
- guchar *buffer,
- gsize count)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
- int cancel_fd;
-
- priv->cancellable = cancellable;
- cancel_fd = g_cancellable_get_fd (cancellable);
- if (cancel_fd != -1) {
- GIOChannel *chan = g_io_channel_unix_new (cancel_fd);
- priv->cancel_watch = soup_add_io_watch (priv->async_context, chan,
- G_IO_IN | G_IO_ERR | G_IO_HUP,
- webkit_soup_http_input_stream_cancelled,
- stream);
- g_io_channel_unref (chan);
- }
-
- priv->caller_buffer = buffer;
- priv->caller_bufsize = count;
- priv->caller_nread = 0;
-
- if (priv->got_headers)
- soup_session_unpause_message (priv->session, priv->msg);
-}
-
-static void
-webkit_soup_http_input_stream_done_io (GInputStream *stream)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
-
- if (priv->cancel_watch) {
- g_source_destroy (priv->cancel_watch);
- priv->cancel_watch = NULL;
- g_cancellable_release_fd (priv->cancellable);
- }
- priv->cancellable = NULL;
-
- priv->caller_buffer = NULL;
- priv->caller_bufsize = 0;
-}
-
-static gboolean
-set_error_if_http_failed (SoupMessage *msg, GError **error)
-{
- if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) {
- g_set_error_literal (error, SOUP_HTTP_ERROR,
- msg->status_code, msg->reason_phrase);
- return TRUE;
- }
- return FALSE;
-}
-
-static gsize
-read_from_leftover (WebKitSoupHTTPInputStreamPrivate *priv,
- gpointer buffer, gsize bufsize)
-{
- gsize nread;
-
- if (priv->leftover_bufsize - priv->leftover_offset <= bufsize) {
- nread = priv->leftover_bufsize - priv->leftover_offset;
- memcpy (buffer, priv->leftover_buffer + priv->leftover_offset, nread);
-
- g_free (priv->leftover_buffer);
- priv->leftover_buffer = NULL;
- priv->leftover_bufsize = priv->leftover_offset = 0;
- } else {
- nread = bufsize;
- memcpy (buffer, priv->leftover_buffer + priv->leftover_offset, nread);
- priv->leftover_offset += nread;
- }
-
- priv->offset += nread;
- return nread;
-}
-
-/* This does the work of webkit_soup_http_input_stream_send(), assuming that the
- * GInputStream pending flag has already been set. It is also used by
- * webkit_soup_http_input_stream_send_async() in some circumstances.
- */
-static gboolean
-webkit_soup_http_input_stream_send_internal (GInputStream *stream,
- GCancellable *cancellable,
- GError **error)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
-
- webkit_soup_http_input_stream_prepare_for_io (stream, cancellable, NULL, 0);
- while (!priv->finished && !priv->got_headers &&
- !g_cancellable_is_cancelled (cancellable))
- g_main_context_iteration (priv->async_context, TRUE);
- webkit_soup_http_input_stream_done_io (stream);
-
- if (g_cancellable_set_error_if_cancelled (cancellable, error))
- return FALSE;
- else if (set_error_if_http_failed (priv->msg, error))
- return FALSE;
- return TRUE;
-}
-
-static void
-send_sync_finished (GInputStream *stream)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
- GError *error = NULL;
-
- if (!g_cancellable_set_error_if_cancelled (priv->cancellable, &error))
- set_error_if_http_failed (priv->msg, &error);
-
- priv->got_headers_cb = NULL;
- priv->finished_cb = NULL;
-
- /* Wake up the main context iteration */
- g_source_attach (g_idle_source_new (), NULL);
-}
-
-/**
- * webkit_soup_http_input_stream_send:
- * @httpstream: a #WebKitSoupHTTPInputStream
- * @cancellable: optional #GCancellable object, %NULL to ignore.
- * @error: location to store the error occuring, or %NULL to ignore
- *
- * Synchronously sends the HTTP request associated with @stream, and
- * reads the response headers. Call this after webkit_soup_http_input_stream_new()
- * and before the first g_input_stream_read() if you want to check the
- * HTTP status code before you start reading.
- *
- * Return value: %TRUE if msg has a successful (2xx) status, %FALSE if
- * not.
- **/
-gboolean
-webkit_soup_http_input_stream_send (WebKitSoupHTTPInputStream *httpstream,
- GCancellable *cancellable,
- GError **error)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (httpstream);
- GInputStream *istream = (GInputStream *)httpstream;
- gboolean result;
-
- g_return_val_if_fail (WEBKIT_IS_SOUP_HTTP_INPUT_STREAM (httpstream), FALSE);
-
- if (!g_input_stream_set_pending (istream, error))
- return FALSE;
-
- priv->got_headers_cb = send_sync_finished;
- priv->finished_cb = send_sync_finished;
-
- result = webkit_soup_http_input_stream_send_internal (istream, cancellable, error);
- g_input_stream_clear_pending (istream);
-
- return result;
-}
-
-static gssize
-webkit_soup_http_input_stream_read (GInputStream *stream,
- void *buffer,
- gsize count,
- GCancellable *cancellable,
- GError **error)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
-
- if (priv->finished)
- return 0;
-
- /* If there is data leftover from a previous read, return it. */
- if (priv->leftover_bufsize)
- return read_from_leftover (priv, buffer, count);
-
- /* No leftover data, accept one chunk from the network */
- webkit_soup_http_input_stream_prepare_for_io (stream, cancellable, buffer, count);
- while (!priv->finished && priv->caller_nread == 0 &&
- !g_cancellable_is_cancelled (cancellable))
- g_main_context_iteration (priv->async_context, TRUE);
- webkit_soup_http_input_stream_done_io (stream);
-
- if (priv->caller_nread > 0)
- return priv->caller_nread;
-
- if (g_cancellable_set_error_if_cancelled (cancellable, error))
- return -1;
- else if (set_error_if_http_failed (priv->msg, error))
- return -1;
- else
- return 0;
-}
-
-static gboolean
-webkit_soup_http_input_stream_close (GInputStream *stream,
- GCancellable *cancellable,
- GError **error)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
-
- if (!priv->finished)
- soup_session_cancel_message (priv->session, priv->msg, SOUP_STATUS_CANCELLED);
-
- return TRUE;
-}
-
-static void
-wrapper_callback (GObject *source_object, GAsyncResult *res,
- gpointer user_data)
-{
- GInputStream *stream = G_INPUT_STREAM (source_object);
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
-
- g_input_stream_clear_pending (stream);
- if (priv->outstanding_callback)
- (*priv->outstanding_callback)(source_object, res, user_data);
- priv->outstanding_callback = NULL;
- g_object_unref (stream);
-}
-
-static void
-send_async_thread (GSimpleAsyncResult *res,
- GObject *object,
- GCancellable *cancellable)
-{
- GError *error = NULL;
- gboolean success;
-
- success = webkit_soup_http_input_stream_send_internal (G_INPUT_STREAM (object),
- cancellable, &error);
- g_simple_async_result_set_op_res_gboolean (res, success);
- if (error) {
- g_simple_async_result_set_from_error (res, error);
- g_error_free (error);
- }
-}
-
-static void
-webkit_soup_http_input_stream_send_async_in_thread (GInputStream *stream,
- int io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GSimpleAsyncResult *res;
-
- res = g_simple_async_result_new (G_OBJECT (stream), callback, user_data,
- webkit_soup_http_input_stream_send_async_in_thread);
- g_simple_async_result_run_in_thread (res, send_async_thread,
- io_priority, cancellable);
- g_object_unref (res);
-}
-
-static void
-send_async_finished (GInputStream *stream)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
- GSimpleAsyncResult *result;
- GError *error = NULL;
-
- if (!g_cancellable_set_error_if_cancelled (priv->cancellable, &error))
- set_error_if_http_failed (priv->msg, &error);
-
- priv->got_headers_cb = NULL;
- priv->finished_cb = NULL;
- webkit_soup_http_input_stream_done_io (stream);
-
- result = priv->result;
- priv->result = NULL;
-
- g_simple_async_result_set_op_res_gboolean (result, error == NULL);
- if (error) {
- g_simple_async_result_set_from_error (result, error);
- g_error_free (error);
- }
- g_simple_async_result_complete (result);
- g_object_unref (result);
-}
-
-static void
-webkit_soup_http_input_stream_send_async_internal (GInputStream *stream,
- int io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
-
- g_object_ref (stream);
- priv->outstanding_callback = callback;
-
- /* If the session uses the default GMainContext, then we can do
- * async I/O directly. But if it has its own main context, it's
- * easier to just run it in another thread.
- */
- if (soup_session_get_async_context (priv->session)) {
- webkit_soup_http_input_stream_send_async_in_thread (stream, io_priority, cancellable,
- wrapper_callback, user_data);
- return;
- }
-
- priv->got_headers_cb = send_async_finished;
- priv->finished_cb = send_async_finished;
-
- webkit_soup_http_input_stream_prepare_for_io (stream, cancellable, NULL, 0);
- priv->result = g_simple_async_result_new (G_OBJECT (stream),
- wrapper_callback, user_data,
- webkit_soup_http_input_stream_send_async);
-}
-
-/**
- * webkit_soup_http_input_stream_send_async:
- * @httpstream: a #WebKitSoupHTTPInputStream
- * @io_priority: the io priority of the request.
- * @cancellable: optional #GCancellable object, %NULL to ignore.
- * @callback: callback to call when the request is satisfied
- * @user_data: the data to pass to callback function
- *
- * Asynchronously sends the HTTP request associated with @stream, and
- * reads the response headers. Call this after webkit_soup_http_input_stream_new()
- * and before the first g_input_stream_read_async() if you want to
- * check the HTTP status code before you start reading.
- **/
-void
-webkit_soup_http_input_stream_send_async (WebKitSoupHTTPInputStream *httpstream,
- int io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GInputStream *istream = (GInputStream *)httpstream;
- GError *error = NULL;
-
- g_return_if_fail (WEBKIT_IS_SOUP_HTTP_INPUT_STREAM (httpstream));
-
- if (!g_input_stream_set_pending (istream, &error)) {
- g_simple_async_report_gerror_in_idle (G_OBJECT (httpstream),
- callback,
- user_data,
- error);
- g_error_free (error);
- return;
- }
- webkit_soup_http_input_stream_send_async_internal (istream, io_priority, cancellable,
- callback, user_data);
-}
-
-/**
- * webkit_soup_http_input_stream_send_finish:
- * @httpstream: a #WebKitSoupHTTPInputStream
- * @result: a #GAsyncResult.
- * @error: a #GError location to store the error occuring, or %NULL to
- * ignore.
- *
- * Finishes a webkit_soup_http_input_stream_send_async() operation.
- *
- * Return value: %TRUE if the message was sent successfully and
- * received a successful status code, %FALSE if not.
- **/
-gboolean
-webkit_soup_http_input_stream_send_finish (WebKitSoupHTTPInputStream *httpstream,
- GAsyncResult *result,
- GError **error)
-{
- GSimpleAsyncResult *simple;
-
- g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), FALSE);
- simple = G_SIMPLE_ASYNC_RESULT (result);
-
- g_return_val_if_fail (g_simple_async_result_get_source_tag (simple) == webkit_soup_http_input_stream_send_async, FALSE);
-
- if (g_simple_async_result_propagate_error (simple, error))
- return FALSE;
-
- return g_simple_async_result_get_op_res_gboolean (simple);
-}
-
-static void
-read_async_done (GInputStream *stream)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
- GSimpleAsyncResult *result;
- GError *error = NULL;
-
- result = priv->result;
- priv->result = NULL;
-
- if (g_cancellable_set_error_if_cancelled (priv->cancellable, &error) ||
- set_error_if_http_failed (priv->msg, &error)) {
- g_simple_async_result_set_from_error (result, error);
- g_error_free (error);
- } else
- g_simple_async_result_set_op_res_gssize (result, priv->caller_nread);
-
- priv->got_chunk_cb = NULL;
- priv->finished_cb = NULL;
- priv->cancelled_cb = NULL;
- webkit_soup_http_input_stream_done_io (stream);
-
- g_simple_async_result_complete (result);
- g_object_unref (result);
-}
-
-static void
-webkit_soup_http_input_stream_read_async (GInputStream *stream,
- void *buffer,
- gsize count,
- int io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (stream);
- GSimpleAsyncResult *result;
-
- /* If the session uses the default GMainContext, then we can do
- * async I/O directly. But if it has its own main context, we fall
- * back to the async-via-sync-in-another-thread implementation.
- */
- if (soup_session_get_async_context (priv->session)) {
- G_INPUT_STREAM_CLASS (webkit_soup_http_input_stream_parent_class)->
- read_async (stream, buffer, count, io_priority,
- cancellable, callback, user_data);
- return;
- }
-
- result = g_simple_async_result_new (G_OBJECT (stream),
- callback, user_data,
- webkit_soup_http_input_stream_read_async);
-
- if (priv->finished) {
- g_simple_async_result_set_op_res_gssize (result, 0);
- g_simple_async_result_complete_in_idle (result);
- g_object_unref (result);
- return;
- }
-
- if (priv->leftover_bufsize) {
- gsize nread = read_from_leftover (priv, buffer, count);
- g_simple_async_result_set_op_res_gssize (result, nread);
- g_simple_async_result_complete_in_idle (result);
- g_object_unref (result);
- return;
- }
-
- priv->result = result;
-
- priv->got_chunk_cb = read_async_done;
- priv->finished_cb = read_async_done;
- priv->cancelled_cb = read_async_done;
- webkit_soup_http_input_stream_prepare_for_io (stream, cancellable, buffer, count);
-}
-
-static gssize
-webkit_soup_http_input_stream_read_finish (GInputStream *stream,
- GAsyncResult *result,
- GError **error)
-{
- GSimpleAsyncResult *simple;
-
- g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (result), -1);
- simple = G_SIMPLE_ASYNC_RESULT (result);
- g_return_val_if_fail (g_simple_async_result_get_source_tag (simple) == webkit_soup_http_input_stream_read_async, -1);
-
- return g_simple_async_result_get_op_res_gssize (simple);
-}
-
-static void
-webkit_soup_http_input_stream_close_async (GInputStream *stream,
- int io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GSimpleAsyncResult *result;
- gboolean success;
- GError *error = NULL;
-
- result = g_simple_async_result_new (G_OBJECT (stream),
- callback, user_data,
- webkit_soup_http_input_stream_close_async);
- success = webkit_soup_http_input_stream_close (stream, cancellable, &error);
- g_simple_async_result_set_op_res_gboolean (result, success);
- if (error) {
- g_simple_async_result_set_from_error (result, error);
- g_error_free (error);
- }
-
- g_simple_async_result_complete_in_idle (result);
- g_object_unref (result);
-}
-
-static gboolean
-webkit_soup_http_input_stream_close_finish (GInputStream *stream,
- GAsyncResult *result,
- GError **error)
-{
- /* Failures handled in generic close_finish code */
- return TRUE;
-}
-
-static goffset
-webkit_soup_http_input_stream_tell (GSeekable *seekable)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (seekable);
-
- return priv->offset;
-}
-
-static gboolean
-webkit_soup_http_input_stream_can_seek (GSeekable *seekable)
-{
- return TRUE;
-}
-
-extern void soup_message_io_cleanup (SoupMessage *msg);
-
-static gboolean
-webkit_soup_http_input_stream_seek (GSeekable *seekable,
- goffset offset,
- GSeekType type,
- GCancellable *cancellable,
- GError **error)
-{
- GInputStream *stream = G_INPUT_STREAM (seekable);
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (seekable);
- char *range;
-
- if (type == G_SEEK_END) {
- /* FIXME: we could send "bytes=-offset", but unless we
- * know the Content-Length, we wouldn't be able to
- * answer a tell() properly. We could find the
- * Content-Length by doing a HEAD...
- */
-
- g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
- "G_SEEK_END not currently supported");
- return FALSE;
- }
-
- if (!g_input_stream_set_pending (stream, error))
- return FALSE;
-
- soup_session_cancel_message (priv->session, priv->msg, SOUP_STATUS_CANCELLED);
- soup_message_io_cleanup (priv->msg);
-
- switch (type) {
- case G_SEEK_CUR:
- offset += priv->offset;
- /* fall through */
-
- case G_SEEK_SET:
- range = g_strdup_printf ("bytes=%" G_GUINT64_FORMAT "-", (guint64)offset);
- priv->offset = offset;
- break;
-
- case G_SEEK_END:
- range = NULL; /* keep compilers happy */
- g_return_val_if_reached (FALSE);
- break;
-
- default:
- g_return_val_if_reached (FALSE);
- }
-
- soup_message_headers_remove (priv->msg->request_headers, "Range");
- soup_message_headers_append (priv->msg->request_headers, "Range", range);
- g_free (range);
-
- webkit_soup_http_input_stream_queue_message (WEBKIT_SOUP_HTTP_INPUT_STREAM (stream));
-
- g_input_stream_clear_pending (stream);
- return TRUE;
-}
-
-static gboolean
-webkit_soup_http_input_stream_can_truncate (GSeekable *seekable)
-{
- return FALSE;
-}
-
-static gboolean
-webkit_soup_http_input_stream_truncate (GSeekable *seekable,
- goffset offset,
- GCancellable *cancellable,
- GError **error)
-{
- g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
- "Truncate not allowed on input stream");
- return FALSE;
-}
-
-SoupMessage *
-webkit_soup_http_input_stream_get_message (WebKitSoupHTTPInputStream *httpstream)
-{
- WebKitSoupHTTPInputStreamPrivate *priv = WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_PRIVATE (httpstream);
- return priv->msg ? g_object_ref (priv->msg) : NULL;
-}
diff --git a/Source/WebCore/platform/network/soup/cache/soup-http-input-stream.h b/Source/WebCore/platform/network/soup/cache/soup-http-input-stream.h
deleted file mode 100644
index 6b98559..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-http-input-stream.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2006, 2007, 2009 Red Hat, Inc.
- * Copyright (C) 2010 Igalia, S.L.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General
- * Public License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef __WEBKIT_SOUP_HTTP_INPUT_STREAM_H__
-#define __WEBKIT_SOUP_HTTP_INPUT_STREAM_H__
-
-#include <gio/gio.h>
-#include <libsoup/soup-types.h>
-
-G_BEGIN_DECLS
-
-#define WEBKIT_TYPE_SOUP_HTTP_INPUT_STREAM (webkit_soup_http_input_stream_get_type ())
-#define WEBKIT_SOUP_HTTP_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), WEBKIT_TYPE_SOUP_HTTP_INPUT_STREAM, WebKitSoupHTTPInputStream))
-#define WEBKIT_SOUP_HTTP_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), WEBKIT_TYPE_SOUP_HTTP_INPUT_STREAM, WebKitSoupHTTPInputStreamClass))
-#define WEBKIT_IS_SOUP_HTTP_INPUT_STREAM(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), WEBKIT_TYPE_SOUP_HTTP_INPUT_STREAM))
-#define WEBKIT_IS_SOUP_HTTP_INPUT_STREAM_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), WEBKIT_TYPE_SOUP_HTTP_INPUT_STREAM))
-#define WEBKIT_SOUP_HTTP_INPUT_STREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), WEBKIT_TYPE_SOUP_HTTP_INPUT_STREAM, WebKitSoupHTTPInputStreamClass))
-
-typedef struct WebKitSoupHTTPInputStream WebKitSoupHTTPInputStream;
-typedef struct WebKitSoupHTTPInputStreamClass WebKitSoupHTTPInputStreamClass;
-
-struct WebKitSoupHTTPInputStream {
- GInputStream parent;
-};
-
-struct WebKitSoupHTTPInputStreamClass {
- GInputStreamClass parent_class;
-
- /* Padding for future expansion */
- void (*_g_reserved1)(void);
- void (*_g_reserved2)(void);
- void (*_g_reserved3)(void);
- void (*_g_reserved4)(void);
- void (*_g_reserved5)(void);
-};
-
-GType webkit_soup_http_input_stream_get_type (void) G_GNUC_CONST;
-
-WebKitSoupHTTPInputStream *webkit_soup_http_input_stream_new (SoupSession *session,
- SoupMessage *msg);
-
-gboolean webkit_soup_http_input_stream_send (WebKitSoupHTTPInputStream *httpstream,
- GCancellable *cancellable,
- GError **error);
-
-void webkit_soup_http_input_stream_send_async (WebKitSoupHTTPInputStream *httpstream,
- int io_priority,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-gboolean webkit_soup_http_input_stream_send_finish (WebKitSoupHTTPInputStream *httpstream,
- GAsyncResult *result,
- GError **error);
-
-SoupMessage *webkit_soup_http_input_stream_get_message (WebKitSoupHTTPInputStream *httpstream);
-
-G_END_DECLS
-
-#endif /* __WEBKIT_SOUP_HTTP_INPUT_STREAM_H__ */
diff --git a/Source/WebCore/platform/network/soup/cache/soup-request-data.c b/Source/WebCore/platform/network/soup/cache/soup-request-data.c
deleted file mode 100644
index ced5c4a..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-request-data.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * soup-request-data.c: data: URI request object
- *
- * Copyright (C) 2009 Red Hat, Inc.
- * Copyright (C) 2010 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "soup-request-data.h"
-
-#include "soup-requester.h"
-#include <libsoup/soup.h>
-#include <glib/gi18n.h>
-
-G_DEFINE_TYPE (WebKitSoupRequestData, webkit_soup_request_data, WEBKIT_TYPE_SOUP_REQUEST)
-
-struct _WebKitSoupRequestDataPrivate {
- gsize content_length;
- char *content_type;
-};
-
-static void
-webkit_soup_request_data_init (WebKitSoupRequestData *data)
-{
- data->priv = G_TYPE_INSTANCE_GET_PRIVATE (data, WEBKIT_TYPE_SOUP_REQUEST_DATA, WebKitSoupRequestDataPrivate);
-}
-
-static void
-webkit_soup_request_data_finalize (GObject *object)
-{
- WebKitSoupRequestData *data = WEBKIT_SOUP_REQUEST_DATA (object);
-
- g_free (data->priv->content_type);
-
- G_OBJECT_CLASS (webkit_soup_request_data_parent_class)->finalize (object);
-}
-
-static gboolean
-webkit_soup_request_data_check_uri (WebKitSoupRequest *request,
- SoupURI *uri,
- GError **error)
-{
- return uri->host == NULL;
-}
-
-static GInputStream *
-webkit_soup_request_data_send (WebKitSoupRequest *request,
- GCancellable *cancellable,
- GError **error)
-{
- WebKitSoupRequestData *data = WEBKIT_SOUP_REQUEST_DATA (request);
- SoupURI *uri = webkit_soup_request_get_uri (request);
- GInputStream *memstream;
- const char *comma, *semi, *start, *end;
- gboolean base64 = FALSE;
-
- gchar *uristr = soup_uri_to_string (uri, FALSE);
- comma = strchr (uristr, ',');
- if (comma && comma != uristr) {
- /* Deal with MIME type / params */
- semi = memchr (uristr, ';', comma - uristr);
- end = semi ? semi : comma;
-
- if (semi && !g_ascii_strncasecmp (semi, ";base64", MAX ((size_t) (comma - semi), strlen (";base64"))))
- base64 = TRUE;
-
- if (end != uristr)
- if (base64)
- data->priv->content_type = g_strndup (uristr, end - uristr);
- else
- data->priv->content_type =
- webkit_soup_request_uri_decoded_copy (uristr, end - uristr);
- }
-
- memstream = g_memory_input_stream_new ();
-
- start = comma ? comma + 1 : uristr;
-
- if (*start) {
- guchar *buf;
-
- if (base64) {
- int inlen, state = 0;
- guint save = 0;
-
- inlen = strlen (start);
- buf = g_malloc0 (inlen * 3 / 4 + 3);
- data->priv->content_length =
- g_base64_decode_step (start, inlen, buf,
- &state, &save);
- if (state != 0) {
- g_free (buf);
- goto fail;
- }
- } else {
- /* Cannot use g_uri_unescape_string nor
- soup_uri_decode because we don't want to
- fail for things like "%3E%%3C" -> ">%<" */
- buf = (guchar *)webkit_soup_request_uri_decoded_copy (start, strlen (start));
- if (!buf)
- goto fail;
- data->priv->content_length = strlen ((char *)buf);
- }
-
- g_memory_input_stream_add_data (G_MEMORY_INPUT_STREAM (memstream),
- buf, data->priv->content_length,
- g_free);
- }
- g_free (uristr);
-
- return memstream;
-
- fail:
- g_free (uristr);
- g_set_error (error, WEBKIT_SOUP_ERROR, WEBKIT_SOUP_ERROR_BAD_URI,
- _ ("Unable to decode URI: %s"), start);
- g_object_unref (memstream);
- return NULL;
-}
-
-static goffset
-webkit_soup_request_data_get_content_length (WebKitSoupRequest *request)
-{
- WebKitSoupRequestData *data = WEBKIT_SOUP_REQUEST_DATA (request);
-
- return data->priv->content_length;
-}
-
-static const char *
-webkit_soup_request_data_get_content_type (WebKitSoupRequest *request)
-{
- WebKitSoupRequestData *data = WEBKIT_SOUP_REQUEST_DATA (request);
-
- return data->priv->content_type;
-}
-
-static void
-webkit_soup_request_data_class_init (WebKitSoupRequestDataClass *request_data_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (request_data_class);
- WebKitSoupRequestClass *request_class =
- WEBKIT_SOUP_REQUEST_CLASS (request_data_class);
-
- g_type_class_add_private (request_data_class, sizeof (WebKitSoupRequestDataPrivate));
-
- object_class->finalize = webkit_soup_request_data_finalize;
-
- request_class->check_uri = webkit_soup_request_data_check_uri;
- request_class->send = webkit_soup_request_data_send;
- request_class->get_content_length = webkit_soup_request_data_get_content_length;
- request_class->get_content_type = webkit_soup_request_data_get_content_type;
-}
diff --git a/Source/WebCore/platform/network/soup/cache/soup-request-data.h b/Source/WebCore/platform/network/soup/cache/soup-request-data.h
deleted file mode 100644
index c9631a4..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-request-data.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2009 Red Hat, Inc.
- * Copyright (C) 2010 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef WEBKIT_SOUP_REQUEST_DATA_H
-#define WEBKIT_SOUP_REQUEST_DATA_H 1
-
-#include "soup-request.h"
-
-G_BEGIN_DECLS
-
-#define WEBKIT_TYPE_SOUP_REQUEST_DATA (webkit_soup_request_data_get_type ())
-#define WEBKIT_SOUP_REQUEST_DATA(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), WEBKIT_TYPE_SOUP_REQUEST_DATA, WebKitSoupRequestData))
-#define WEBKIT_SOUP_REQUEST_DATA_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), WEBKIT_TYPE_SOUP_REQUEST_DATA, WebKitSoupRequestDataClass))
-#define WEBKIT_IS_SOUP_REQUEST_DATA(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), WEBKIT_TYPE_SOUP_REQUEST_DATA))
-#define WEBKIT_IS_SOUP_REQUEST_DATA_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), WEBKIT_TYPE_SOUP_REQUEST_DATA))
-#define WEBKIT_SOUP_REQUEST_DATA_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), WEBKIT_TYPE_SOUP_REQUEST_DATA, WebKitSoupRequestDataClass))
-
-typedef struct _WebKitSoupRequestDataPrivate WebKitSoupRequestDataPrivate;
-
-typedef struct {
- WebKitSoupRequest parent;
-
- WebKitSoupRequestDataPrivate *priv;
-} WebKitSoupRequestData;
-
-typedef struct {
- WebKitSoupRequestClass parent;
-} WebKitSoupRequestDataClass;
-
-GType webkit_soup_request_data_get_type (void);
-
-G_END_DECLS
-
-#endif /* WEBKIT_SOUP_REQUEST_DATA_H */
diff --git a/Source/WebCore/platform/network/soup/cache/soup-request-file.c b/Source/WebCore/platform/network/soup/cache/soup-request-file.c
deleted file mode 100644
index 24ccb10..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-request-file.c
+++ /dev/null
@@ -1,331 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * soup-request-file.c: file: URI request object
- *
- * Copyright (C) 2009 Red Hat, Inc.
- * Copyright (C) 2010 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "soup-request-file.h"
-#include "soup-directory-input-stream.h"
-#include "soup-requester.h"
-#include <glib/gi18n.h>
-
-G_DEFINE_TYPE (WebKitSoupRequestFile, webkit_soup_request_file, WEBKIT_TYPE_SOUP_REQUEST)
-
-struct _WebKitSoupRequestFilePrivate {
- GFile *gfile;
-
- char *mime_type;
- goffset size;
-};
-
-GFile *
-webkit_soup_request_file_get_file (WebKitSoupRequestFile *file)
-{
- return g_object_ref (file->priv->gfile);
-}
-
-static void
-webkit_soup_request_file_init (WebKitSoupRequestFile *file)
-{
- file->priv = G_TYPE_INSTANCE_GET_PRIVATE (file, WEBKIT_TYPE_SOUP_REQUEST_FILE, WebKitSoupRequestFilePrivate);
-
- file->priv->size = -1;
-}
-
-static void
-webkit_soup_request_file_finalize (GObject *object)
-{
- WebKitSoupRequestFile *file = WEBKIT_SOUP_REQUEST_FILE (object);
-
- if (file->priv->gfile)
- g_object_unref (file->priv->gfile);
- g_free (file->priv->mime_type);
-
- G_OBJECT_CLASS (webkit_soup_request_file_parent_class)->finalize (object);
-}
-
-static gboolean
-webkit_soup_request_file_check_uri (WebKitSoupRequest *request,
- SoupURI *uri,
- GError **error)
-{
- /* "file:/foo" is not valid */
- if (!uri->host)
- return FALSE;
-
- /* but it must be "file:///..." or "file://localhost/..." */
- if (uri->scheme == SOUP_URI_SCHEME_FILE &&
- *uri->host &&
- g_ascii_strcasecmp (uri->host, "localhost") != 0)
- return FALSE;
-
- return TRUE;
-}
-
-static void
-webkit_soup_request_file_ftp_main_loop_quit (GObject *object,
- GAsyncResult *result,
- gpointer loop)
-{
- g_main_loop_quit (loop);
-}
-
-/* This is a somewhat hacky way to get FTP to almost work. The proper way to
- * get FTP to _really_ work involves hacking GIO to have APIs to handle
- * canoncial URLs.
- */
-static GFile *
-webkit_soup_request_file_ensure_file_ftp (SoupURI *uri,
- GCancellable *cancellable,
- GError **error)
-{
- SoupURI *host;
- char *s;
- GFile *file, *result;
- GMount *mount;
-
- host = soup_uri_copy_host (uri);
- s = soup_uri_to_string (host, FALSE);
- file = g_file_new_for_uri (s);
- soup_uri_free (host);
- g_free (s);
-
- mount = g_file_find_enclosing_mount (file, cancellable, error);
- if (mount == NULL && g_file_supports_thread_contexts (file)) {
- GMainContext *context = g_main_context_new ();
- GMainLoop *loop = g_main_loop_new (context, FALSE);
-
- g_clear_error (error);
- g_main_context_push_thread_default (context);
- g_file_mount_enclosing_volume (file,
- G_MOUNT_MOUNT_NONE,
- NULL, /* FIXME! */
- cancellable,
- webkit_soup_request_file_ftp_main_loop_quit,
- loop);
- g_main_loop_run (loop);
- g_main_context_pop_thread_default (context);
- g_main_loop_unref (loop);
- g_main_context_unref (context);
- mount = g_file_find_enclosing_mount (file, cancellable, error);
- }
- if (mount == NULL)
- return NULL;
- g_object_unref (file);
-
- file = g_mount_get_default_location (mount);
- g_object_unref (mount);
-
- s = g_strdup (uri->path);
- if (strchr (s, ';'))
- *strchr (s, ';') = 0;
-
- result = g_file_resolve_relative_path (file, s);
- g_free (s);
- g_object_unref (file);
-
- return result;
-}
-
-static gboolean
-webkit_soup_request_file_ensure_file (WebKitSoupRequestFile *file,
- GCancellable *cancellable,
- GError **error)
-{
- SoupURI *uri;
-
- if (file->priv->gfile)
- return TRUE;
-
- uri = webkit_soup_request_get_uri (WEBKIT_SOUP_REQUEST (file));
- if (uri->scheme == SOUP_URI_SCHEME_FILE) {
- /* We cannot use soup_uri_decode as it incorrectly
- * returns NULL for incorrectly encoded URIs (that
- * could be valid filenames). This will be hopefully
- * shipped in libsoup 2.32.1 but we want to land this
- * first. TODO: replace uri_decoded_copy by
- * soup_uri_decode when the required libsoup version
- * is bumped out to 2.32.1
- */
- gchar *decoded_uri = webkit_soup_request_uri_decoded_copy (uri->path, strlen (uri->path));
-
- if (decoded_uri) {
- /* Do not use new_for_uri() as the decoded URI
- * could not be a valid URI
- */
- file->priv->gfile = g_file_new_for_path (decoded_uri);
- g_free (decoded_uri);
- }
-
- return TRUE;
- } else if (uri->scheme == SOUP_URI_SCHEME_FTP) {
- file->priv->gfile = webkit_soup_request_file_ensure_file_ftp (uri,
- cancellable,
- error);
- return file->priv->gfile != NULL;
- }
-
- g_set_error (error, WEBKIT_SOUP_ERROR, WEBKIT_SOUP_ERROR_UNSUPPORTED_URI_SCHEME,
- _ ("Unsupported URI scheme '%s'"), uri->scheme);
- return FALSE;
-}
-
-static GInputStream *
-webkit_soup_request_file_send (WebKitSoupRequest *request,
- GCancellable *cancellable,
- GError **error)
-{
- WebKitSoupRequestFile *file = WEBKIT_SOUP_REQUEST_FILE (request);
- GInputStream *stream;
- GError *my_error = NULL;
-
- if (!webkit_soup_request_file_ensure_file (file, cancellable, error))
- return NULL;
-
- stream = G_INPUT_STREAM (g_file_read (file->priv->gfile,
- cancellable, &my_error));
- if (stream == NULL) {
- if (g_error_matches (my_error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY)) {
- GFileEnumerator *enumerator;
- g_clear_error (&my_error);
- enumerator = g_file_enumerate_children (file->priv->gfile,
- "*",
- G_FILE_QUERY_INFO_NONE,
- cancellable,
- error);
- if (enumerator) {
- stream = webkit_soup_directory_input_stream_new (enumerator,
- webkit_soup_request_get_uri (request));
- g_object_unref (enumerator);
- file->priv->mime_type = g_strdup ("text/html");
- }
- } else {
- g_propagate_error (error, my_error);
- }
- } else {
- GFileInfo *info = g_file_query_info (file->priv->gfile,
- G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE ","
- G_FILE_ATTRIBUTE_STANDARD_SIZE,
- 0, cancellable, NULL);
- if (info) {
- const char *content_type;
- file->priv->size = g_file_info_get_size (info);
- content_type = g_file_info_get_content_type (info);
-
- if (content_type)
- file->priv->mime_type = g_content_type_get_mime_type (content_type);
- g_object_unref (info);
- }
- }
-
- return stream;
-}
-
-static void
-webkit_soup_request_file_send_async_thread (GSimpleAsyncResult *res,
- GObject *object,
- GCancellable *cancellable)
-{
- GInputStream *stream;
- WebKitSoupRequest *request;
- GError *error = NULL;
-
- request = WEBKIT_SOUP_REQUEST (object);
-
- stream = webkit_soup_request_file_send (request, cancellable, &error);
-
- if (stream == NULL) {
- g_simple_async_result_set_from_error (res, error);
- g_error_free (error);
- } else {
- g_simple_async_result_set_op_res_gpointer (res, stream, g_object_unref);
- }
-}
-
-static void
-webkit_soup_request_file_send_async (WebKitSoupRequest *request,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GSimpleAsyncResult *res;
-
- res = g_simple_async_result_new (G_OBJECT (request), callback, user_data, webkit_soup_request_file_send_async);
-
- g_simple_async_result_run_in_thread (res, webkit_soup_request_file_send_async_thread, G_PRIORITY_DEFAULT, cancellable);
- g_object_unref (res);
-}
-
-static GInputStream *
-webkit_soup_request_file_send_finish (WebKitSoupRequest *request,
- GAsyncResult *result,
- GError **error)
-{
- GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (result);
-
- g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == webkit_soup_request_file_send_async);
-
- if (g_simple_async_result_propagate_error (simple, error))
- return NULL;
-
- return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
-}
-
-static goffset
-webkit_soup_request_file_get_content_length (WebKitSoupRequest *request)
-{
- WebKitSoupRequestFile *file = WEBKIT_SOUP_REQUEST_FILE (request);
-
- return file->priv->size;
-}
-
-static const char *
-webkit_soup_request_file_get_content_type (WebKitSoupRequest *request)
-{
- WebKitSoupRequestFile *file = WEBKIT_SOUP_REQUEST_FILE (request);
-
- if (!file->priv->mime_type)
- return "application/octet-stream";
-
- return file->priv->mime_type;
-}
-
-static void
-webkit_soup_request_file_class_init (WebKitSoupRequestFileClass *request_file_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (request_file_class);
- WebKitSoupRequestClass *request_class =
- WEBKIT_SOUP_REQUEST_CLASS (request_file_class);
-
- g_type_class_add_private (request_file_class, sizeof (WebKitSoupRequestFilePrivate));
-
- object_class->finalize = webkit_soup_request_file_finalize;
-
- request_class->check_uri = webkit_soup_request_file_check_uri;
- request_class->send = webkit_soup_request_file_send;
- request_class->send_async = webkit_soup_request_file_send_async;
- request_class->send_finish = webkit_soup_request_file_send_finish;
- request_class->get_content_length = webkit_soup_request_file_get_content_length;
- request_class->get_content_type = webkit_soup_request_file_get_content_type;
-}
diff --git a/Source/WebCore/platform/network/soup/cache/soup-request-file.h b/Source/WebCore/platform/network/soup/cache/soup-request-file.h
deleted file mode 100644
index 459e82a..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-request-file.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2009 Red Hat, Inc.
- * Copyright (C) 2010 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef WEBKIT_SOUP_REQUEST_FILE_H
-#define WEBKIT_SOUP_REQUEST_FILE_H 1
-
-#include "soup-request.h"
-
-G_BEGIN_DECLS
-
-#define WEBKIT_TYPE_SOUP_REQUEST_FILE (webkit_soup_request_file_get_type ())
-#define WEBKIT_SOUP_REQUEST_FILE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), WEBKIT_TYPE_SOUP_REQUEST_FILE, WebKitSoupRequestFile))
-#define WEBKIT_SOUP_REQUEST_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), WEBKIT_TYPE_SOUP_REQUEST_FILE, WebKitSoupRequestFileClass))
-#define WEBKIT_IS_SOUP_REQUEST_FILE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), WEBKIT_TYPE_SOUP_REQUEST_FILE))
-#define WEBKIT_IS_SOUP_REQUEST_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), WEBKIT_TYPE_SOUP_REQUEST_FILE))
-#define WEBKIT_SOUP_REQUEST_FILE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), WEBKIT_TYPE_SOUP_REQUEST_FILE, WebKitSoupRequestFileClass))
-
-typedef struct _WebKitSoupRequestFilePrivate WebKitSoupRequestFilePrivate;
-
-typedef struct {
- WebKitSoupRequest parent;
-
- WebKitSoupRequestFilePrivate *priv;
-} WebKitSoupRequestFile;
-
-typedef struct {
- WebKitSoupRequestClass parent;
-} WebKitSoupRequestFileClass;
-
-GType webkit_soup_request_file_get_type (void);
-
-GFile *webkit_soup_request_file_get_file (WebKitSoupRequestFile *file);
-
-G_END_DECLS
-
-#endif /* WEBKIT_SOUP_REQUEST_FILE_H */
diff --git a/Source/WebCore/platform/network/soup/cache/soup-request-http.c b/Source/WebCore/platform/network/soup/cache/soup-request-http.c
deleted file mode 100644
index 777fd72..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-request-http.c
+++ /dev/null
@@ -1,356 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * soup-request-http.c: http: URI request object
- *
- * Copyright (C) 2009 Red Hat, Inc.
- * Copyright (C) 2010 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <glib/gi18n.h>
-
-#include "soup-cache.h"
-#include "soup-cache-private.h"
-#include "soup-http-input-stream.h"
-#include "soup-request-http.h"
-
-G_DEFINE_TYPE (WebKitSoupRequestHTTP, webkit_soup_request_http, WEBKIT_TYPE_SOUP_REQUEST)
-
-struct _WebKitSoupRequestHTTPPrivate {
- SoupMessage *msg;
-};
-
-/**
- * webkit_soup_request_http_get_message:
- * @http: a #WebKitSoupRequestHTTP object
- *
- * Gets a new reference to the #SoupMessage associated to this SoupRequest
- *
- * Returns: a new reference to the #SoupMessage
- **/
-SoupMessage *
-webkit_soup_request_http_get_message (WebKitSoupRequestHTTP *http)
-{
- g_return_val_if_fail (WEBKIT_IS_SOUP_REQUEST_HTTP (http), NULL);
-
- return g_object_ref (http->priv->msg);
-}
-
-static void
-webkit_soup_request_http_init (WebKitSoupRequestHTTP *http)
-{
- http->priv = G_TYPE_INSTANCE_GET_PRIVATE (http, WEBKIT_TYPE_SOUP_REQUEST_HTTP, WebKitSoupRequestHTTPPrivate);
-}
-
-static gboolean
-webkit_soup_request_http_check_uri (WebKitSoupRequest *request,
- SoupURI *uri,
- GError **error)
-{
- WebKitSoupRequestHTTP *http = WEBKIT_SOUP_REQUEST_HTTP (request);
-
- if (!SOUP_URI_VALID_FOR_HTTP (uri))
- return FALSE;
-
- http->priv->msg = soup_message_new_from_uri (SOUP_METHOD_GET, uri);
- return TRUE;
-}
-
-static void
-webkit_soup_request_http_finalize (GObject *object)
-{
- WebKitSoupRequestHTTP *http = WEBKIT_SOUP_REQUEST_HTTP (object);
-
- if (http->priv->msg)
- g_object_unref (http->priv->msg);
-
- G_OBJECT_CLASS (webkit_soup_request_http_parent_class)->finalize (object);
-}
-
-static GInputStream *
-webkit_soup_request_http_send (WebKitSoupRequest *request,
- GCancellable *cancellable,
- GError **error)
-{
- WebKitSoupHTTPInputStream *httpstream;
- WebKitSoupRequestHTTP *http = WEBKIT_SOUP_REQUEST_HTTP (request);
-
- httpstream = webkit_soup_http_input_stream_new (webkit_soup_request_get_session (request), http->priv->msg);
- if (!webkit_soup_http_input_stream_send (httpstream, cancellable, error)) {
- g_object_unref (httpstream);
- return NULL;
- }
- return (GInputStream *)httpstream;
-}
-
-
-static void
-sent_async (GObject *source, GAsyncResult *result, gpointer user_data)
-{
- WebKitSoupHTTPInputStream *httpstream = WEBKIT_SOUP_HTTP_INPUT_STREAM (source);
- GSimpleAsyncResult *simple = user_data;
- GError *error = NULL;
-
- if (webkit_soup_http_input_stream_send_finish (httpstream, result, &error)) {
- g_simple_async_result_set_op_res_gpointer (simple, httpstream, g_object_unref);
- } else {
- g_simple_async_result_set_from_error (simple, error);
- g_error_free (error);
- g_object_unref (httpstream);
- }
- g_simple_async_result_complete (simple);
- g_object_unref (simple);
-}
-
-
-typedef struct {
- WebKitSoupRequestHTTP *req;
- SoupMessage *original;
- GCancellable *cancellable;
- GAsyncReadyCallback callback;
- gpointer user_data;
-} ConditionalHelper;
-
-
-static void
-conditional_get_ready_cb (SoupSession *session, SoupMessage *msg, gpointer user_data)
-{
- ConditionalHelper *helper = (ConditionalHelper *)user_data;
- GSimpleAsyncResult *simple;
- WebKitSoupHTTPInputStream *httpstream;
-
- simple = g_simple_async_result_new (G_OBJECT (helper->req),
- helper->callback, helper->user_data,
- conditional_get_ready_cb);
-
- if (msg->status_code == SOUP_STATUS_NOT_MODIFIED) {
- WebKitSoupCache *cache = (WebKitSoupCache *)soup_session_get_feature (session, WEBKIT_TYPE_SOUP_CACHE);
-
- httpstream = (WebKitSoupHTTPInputStream *)webkit_soup_cache_send_response (cache, msg);
- if (httpstream) {
- const gchar *content_type;
-
- g_simple_async_result_set_op_res_gpointer (simple, httpstream, g_object_unref);
-
- soup_message_got_headers (helper->original);
-
- /* FIXME: Uncomment this when this becomes part of libsoup
- * if (!soup_message_disables_feature(helper->original, SOUP_TYPE_CONTENT_SNIFFER)) {
- * const gchar *content_type = soup_message_headers_get_content_type (msg->response_headers, NULL);
- * soup_message_content_sniffed (helper->original, content_type, NULL);
- * }
- */
- content_type = soup_message_headers_get_content_type (msg->response_headers, NULL);
- soup_message_content_sniffed (helper->original, content_type, NULL);
-
- g_simple_async_result_complete (simple);
-
- soup_message_finished (helper->original);
-
- g_object_unref (simple);
- } else {
- /* Ask again for the resource, somehow the cache cannot locate it */
- httpstream = webkit_soup_http_input_stream_new (session, helper->original);
- webkit_soup_http_input_stream_send_async (httpstream, G_PRIORITY_DEFAULT,
- helper->cancellable, sent_async, simple);
- }
- } else {
- /* It is in the cache but it was modified remotely */
- httpstream = webkit_soup_http_input_stream_new (session, helper->original);
- webkit_soup_http_input_stream_send_async (httpstream, G_PRIORITY_DEFAULT,
- helper->cancellable, sent_async, simple);
- }
-
- g_object_unref (helper->req);
- g_object_unref (helper->original);
- g_slice_free (ConditionalHelper, helper);
-}
-
-typedef struct {
- WebKitSoupRequestHTTP *http;
- GAsyncReadyCallback callback;
- gpointer user_data;
- WebKitSoupHTTPInputStream *httpstream;
-} SendAsyncHelper;
-
-static void webkit_soup_request_http_send_async (WebKitSoupRequest *request,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-
-static gboolean
-send_async_cb (gpointer data)
-{
- GSimpleAsyncResult *simple;
- SendAsyncHelper *helper = (SendAsyncHelper *)data;
- const gchar *content_type;
-
- simple = g_simple_async_result_new (G_OBJECT (helper->http),
- helper->callback, helper->user_data,
- webkit_soup_request_http_send_async);
- g_simple_async_result_set_op_res_gpointer (simple, helper->httpstream, g_object_unref);
-
- /* Update message status */
- soup_message_set_status (helper->http->priv->msg, SOUP_STATUS_OK);
-
- /* Issue signals */
- soup_message_got_headers (helper->http->priv->msg);
-
- /* FIXME: Uncomment this when this becomes part of libsoup
- * if (!soup_message_disables_feature(helper->http->priv->msg, SOUP_TYPE_CONTENT_SNIFFER)) {
- * const gchar *content_type = soup_message_headers_get_content_type (helper->http->priv->msg->response_headers, NULL);
- * soup_message_content_sniffed (helper->http->priv->msg, content_type, NULL);
- * }
- */
- content_type = soup_message_headers_get_content_type (helper->http->priv->msg->response_headers, NULL);
- soup_message_content_sniffed (helper->http->priv->msg, content_type, NULL);
-
- g_simple_async_result_complete (simple);
-
- soup_message_finished (helper->http->priv->msg);
-
- g_object_unref (simple);
-
- g_object_unref (helper->http);
- g_slice_free (SendAsyncHelper, helper);
-
- return FALSE;
-}
-
-static void
-webkit_soup_request_http_send_async (WebKitSoupRequest *request,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- WebKitSoupRequestHTTP *http = WEBKIT_SOUP_REQUEST_HTTP (request);
- WebKitSoupHTTPInputStream *httpstream;
- GSimpleAsyncResult *simple;
- SoupSession *session;
- WebKitSoupCache *cache;
-
- session = webkit_soup_request_get_session (request);
- cache = (WebKitSoupCache *)soup_session_get_feature (session, WEBKIT_TYPE_SOUP_CACHE);
-
- if (cache) {
- WebKitSoupCacheResponse response;
-
- response = webkit_soup_cache_has_response (cache, http->priv->msg);
- if (response == WEBKIT_SOUP_CACHE_RESPONSE_FRESH) {
- WebKitSoupHTTPInputStream *httpstream;
-
- httpstream = (WebKitSoupHTTPInputStream *)
- webkit_soup_cache_send_response (cache, SOUP_MESSAGE (http->priv->msg));
-
- /* Cached resource file could have been deleted outside
- */
- if (httpstream) {
- /* Do return the stream asynchronously as in
- * the other cases. It's not enough to use
- * g_simple_async_result_complete_in_idle as
- * the signals must be also emitted
- * asynchronously
- */
- SendAsyncHelper *helper = g_slice_new (SendAsyncHelper);
- helper->http = g_object_ref (http);
- helper->callback = callback;
- helper->user_data = user_data;
- helper->httpstream = httpstream;
- g_timeout_add (0, send_async_cb, helper);
- return;
- }
- } else if (response == WEBKIT_SOUP_CACHE_RESPONSE_NEEDS_VALIDATION) {
- SoupMessage *conditional_msg;
- ConditionalHelper *helper;
-
- conditional_msg = webkit_soup_cache_generate_conditional_request (cache, http->priv->msg);
-
- helper = g_slice_new0 (ConditionalHelper);
- helper->req = g_object_ref (http);
- helper->original = g_object_ref (http->priv->msg);
- helper->cancellable = cancellable;
- helper->callback = callback;
- helper->user_data = user_data;
- soup_session_queue_message (session, conditional_msg,
- conditional_get_ready_cb,
- helper);
- return;
- }
- }
-
- simple = g_simple_async_result_new (G_OBJECT (http),
- callback, user_data,
- webkit_soup_request_http_send_async);
- httpstream = webkit_soup_http_input_stream_new (webkit_soup_request_get_session (request),
- http->priv->msg);
- webkit_soup_http_input_stream_send_async (httpstream, G_PRIORITY_DEFAULT,
- cancellable, sent_async, simple);
-}
-
-static GInputStream *
-webkit_soup_request_http_send_finish (WebKitSoupRequest *request,
- GAsyncResult *result,
- GError **error)
-{
- GSimpleAsyncResult *simple;
-
- g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (request), webkit_soup_request_http_send_async) || g_simple_async_result_is_valid (result, G_OBJECT (request), conditional_get_ready_cb), NULL);
-
- simple = G_SIMPLE_ASYNC_RESULT (result);
- if (g_simple_async_result_propagate_error (simple, error))
- return NULL;
- return g_object_ref (g_simple_async_result_get_op_res_gpointer (simple));
-}
-
-static goffset
-webkit_soup_request_http_get_content_length (WebKitSoupRequest *request)
-{
- WebKitSoupRequestHTTP *http = WEBKIT_SOUP_REQUEST_HTTP (request);
-
- return soup_message_headers_get_content_length (http->priv->msg->response_headers);
-}
-
-static const char *
-webkit_soup_request_http_get_content_type (WebKitSoupRequest *request)
-{
- WebKitSoupRequestHTTP *http = WEBKIT_SOUP_REQUEST_HTTP (request);
-
- return soup_message_headers_get_content_type (http->priv->msg->response_headers, NULL);
-}
-
-static void
-webkit_soup_request_http_class_init (WebKitSoupRequestHTTPClass *request_http_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (request_http_class);
- WebKitSoupRequestClass *request_class =
- WEBKIT_SOUP_REQUEST_CLASS (request_http_class);
-
- g_type_class_add_private (request_http_class, sizeof (WebKitSoupRequestHTTPPrivate));
-
- object_class->finalize = webkit_soup_request_http_finalize;
-
- request_class->check_uri = webkit_soup_request_http_check_uri;
- request_class->send = webkit_soup_request_http_send;
- request_class->send_async = webkit_soup_request_http_send_async;
- request_class->send_finish = webkit_soup_request_http_send_finish;
- request_class->get_content_length = webkit_soup_request_http_get_content_length;
- request_class->get_content_type = webkit_soup_request_http_get_content_type;
-}
diff --git a/Source/WebCore/platform/network/soup/cache/soup-request-http.h b/Source/WebCore/platform/network/soup/cache/soup-request-http.h
deleted file mode 100644
index a06a821..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-request-http.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2009 Red Hat, Inc.
- * Copyright (C) 2010 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef WEBKIT_SOUP_REQUEST_HTTP_H
-#define WEBKIT_SOUP_REQUEST_HTTP_H 1
-
-#include "soup-request.h"
-
-G_BEGIN_DECLS
-
-#define WEBKIT_TYPE_SOUP_REQUEST_HTTP (webkit_soup_request_http_get_type ())
-#define WEBKIT_SOUP_REQUEST_HTTP(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), WEBKIT_TYPE_SOUP_REQUEST_HTTP, WebKitSoupRequestHTTP))
-#define WEBKIT_SOUP_REQUEST_HTTP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), WEBKIT_TYPE_SOUP_REQUEST_HTTP, WebKitSoupRequestHTTPClass))
-#define WEBKIT_IS_SOUP_REQUEST_HTTP(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), WEBKIT_TYPE_SOUP_REQUEST_HTTP))
-#define WEBKIT_IS_SOUP_REQUEST_HTTP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), WEBKIT_TYPE_SOUP_REQUEST_HTTP))
-#define WEBKIT_SOUP_REQUEST_HTTP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), WEBKIT_TYPE_SOUP_REQUEST_HTTP, WebKitSoupRequestHTTPClass))
-
-typedef struct _WebKitSoupRequestHTTPPrivate WebKitSoupRequestHTTPPrivate;
-
-typedef struct {
- WebKitSoupRequest parent;
-
- WebKitSoupRequestHTTPPrivate *priv;
-} WebKitSoupRequestHTTP;
-
-typedef struct {
- WebKitSoupRequestClass parent;
-} WebKitSoupRequestHTTPClass;
-
-GType webkit_soup_request_http_get_type (void);
-
-SoupMessage *webkit_soup_request_http_get_message (WebKitSoupRequestHTTP *http);
-
-G_END_DECLS
-
-#endif /* WEBKIT_SOUP_REQUEST_HTTP_H */
diff --git a/Source/WebCore/platform/network/soup/cache/soup-request.c b/Source/WebCore/platform/network/soup/cache/soup-request.c
deleted file mode 100644
index 46b9f5a..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-request.c
+++ /dev/null
@@ -1,312 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * soup-request.c: Protocol-independent streaming request interface
- *
- * Copyright (C) 2009 Red Hat, Inc.
- * Copyright (C) 2010, 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <glib/gi18n.h>
-
-#include "soup-request.h"
-#include "soup-requester.h"
-
-/**
- * SECTION:soup-request
- * @short_description: Protocol-independent streaming request interface
- *
- * FIXME
- **/
-
-/**
- * WebKitSoupRequest:
- *
- * FIXME
- *
- * Since: 2.30
- **/
-
-static void webkit_soup_request_initable_interface_init (GInitableIface *initable_interface);
-
-G_DEFINE_TYPE_WITH_CODE (WebKitSoupRequest, webkit_soup_request, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
- webkit_soup_request_initable_interface_init))
-
-enum {
- PROP_0,
- PROP_URI,
- PROP_SESSION
-};
-
-struct _WebKitSoupRequestPrivate {
- SoupURI *uri;
- SoupSession *session;
-};
-
-static void
-webkit_soup_request_init (WebKitSoupRequest *request)
-{
- request->priv = G_TYPE_INSTANCE_GET_PRIVATE (request, WEBKIT_TYPE_SOUP_REQUEST, WebKitSoupRequestPrivate);
-}
-
-static void
-webkit_soup_request_finalize (GObject *object)
-{
- WebKitSoupRequest *request = WEBKIT_SOUP_REQUEST (object);
-
- if (request->priv->uri)
- soup_uri_free (request->priv->uri);
- if (request->priv->session)
- g_object_unref (request->priv->session);
-
- G_OBJECT_CLASS (webkit_soup_request_parent_class)->finalize (object);
-}
-
-static void
-webkit_soup_request_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
-{
- WebKitSoupRequest *request = WEBKIT_SOUP_REQUEST (object);
-
- switch (prop_id) {
- case PROP_URI:
- if (request->priv->uri)
- soup_uri_free (request->priv->uri);
- request->priv->uri = g_value_dup_boxed (value);
- break;
- case PROP_SESSION:
- if (request->priv->session)
- g_object_unref (request->priv->session);
- request->priv->session = g_value_dup_object (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-webkit_soup_request_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
-{
- WebKitSoupRequest *request = WEBKIT_SOUP_REQUEST (object);
-
- switch (prop_id) {
- case PROP_URI:
- g_value_set_boxed (value, request->priv->uri);
- break;
- case PROP_SESSION:
- g_value_set_object (value, request->priv->session);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static gboolean
-webkit_soup_request_initable_init (GInitable *initable,
- GCancellable *cancellable,
- GError **error)
-{
- WebKitSoupRequest *request = WEBKIT_SOUP_REQUEST (initable);
- gboolean ok;
-
- if (!request->priv->uri) {
- g_set_error (error, WEBKIT_SOUP_ERROR, WEBKIT_SOUP_ERROR_BAD_URI,
- _ ("No URI provided"));
- return FALSE;
- }
-
- ok = WEBKIT_SOUP_REQUEST_GET_CLASS (initable)->
- check_uri (request, request->priv->uri, error);
-
- if (!ok && error) {
- char *uri_string = soup_uri_to_string (request->priv->uri, FALSE);
- g_set_error (error, WEBKIT_SOUP_ERROR, WEBKIT_SOUP_ERROR_BAD_URI,
- _ ("Invalid '%s' URI: %s"),
- request->priv->uri->scheme,
- uri_string);
- g_free (uri_string);
- }
-
- return ok;
-}
-
-static gboolean
-webkit_soup_request_default_check_uri (WebKitSoupRequest *request,
- SoupURI *uri,
- GError **error)
-{
- return TRUE;
-}
-
-/* Default implementation: assume the sync implementation doesn't block */
-static void
-webkit_soup_request_default_send_async (WebKitSoupRequest *request,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- GSimpleAsyncResult *simple;
-
- simple = g_simple_async_result_new (G_OBJECT (request),
- callback, user_data,
- webkit_soup_request_default_send_async);
- g_simple_async_result_complete_in_idle (simple);
- g_object_unref (simple);
-}
-
-static GInputStream *
-webkit_soup_request_default_send_finish (WebKitSoupRequest *request,
- GAsyncResult *result,
- GError **error)
-{
- g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (request), webkit_soup_request_default_send_async), NULL);
-
- return webkit_soup_request_send (request, NULL, error);
-}
-
-GInputStream *
-webkit_soup_request_send (WebKitSoupRequest *request,
- GCancellable *cancellable,
- GError **error)
-{
- return WEBKIT_SOUP_REQUEST_GET_CLASS (request)->
- send (request, cancellable, error);
-}
-
-void
-webkit_soup_request_send_async (WebKitSoupRequest *request,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- WEBKIT_SOUP_REQUEST_GET_CLASS (request)->
- send_async (request, cancellable, callback, user_data);
-}
-
-GInputStream *
-webkit_soup_request_send_finish (WebKitSoupRequest *request,
- GAsyncResult *result,
- GError **error)
-{
- return WEBKIT_SOUP_REQUEST_GET_CLASS (request)->
- send_finish (request, result, error);
-}
-
-static void
-webkit_soup_request_class_init (WebKitSoupRequestClass *request_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (request_class);
-
- g_type_class_add_private (request_class, sizeof (WebKitSoupRequestPrivate));
-
- request_class->check_uri = webkit_soup_request_default_check_uri;
- request_class->send_async = webkit_soup_request_default_send_async;
- request_class->send_finish = webkit_soup_request_default_send_finish;
-
- object_class->finalize = webkit_soup_request_finalize;
- object_class->set_property = webkit_soup_request_set_property;
- object_class->get_property = webkit_soup_request_get_property;
-
- g_object_class_install_property (
- object_class, PROP_URI,
- g_param_spec_boxed (WEBKIT_SOUP_REQUEST_URI,
- "URI",
- "The request URI",
- SOUP_TYPE_URI,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
- g_object_class_install_property (
- object_class, PROP_SESSION,
- g_param_spec_object (WEBKIT_SOUP_REQUEST_SESSION,
- "Session",
- "The request's session",
- SOUP_TYPE_SESSION,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-}
-
-static void
-webkit_soup_request_initable_interface_init (GInitableIface *initable_interface)
-{
- initable_interface->init = webkit_soup_request_initable_init;
-}
-
-SoupURI *
-webkit_soup_request_get_uri (WebKitSoupRequest *request)
-{
- return request->priv->uri;
-}
-
-SoupSession *
-webkit_soup_request_get_session (WebKitSoupRequest *request)
-{
- return request->priv->session;
-}
-
-goffset
-webkit_soup_request_get_content_length (WebKitSoupRequest *request)
-{
- return WEBKIT_SOUP_REQUEST_GET_CLASS (request)->get_content_length (request);
-}
-
-const char *
-webkit_soup_request_get_content_type (WebKitSoupRequest *request)
-{
- return WEBKIT_SOUP_REQUEST_GET_CLASS (request)->get_content_type (request);
-}
-
-#define XDIGIT(c) ((c) <= '9' ? (c) - '0' : ((c) & 0x4F) - 'A' + 10)
-#define HEXCHAR(s) ((XDIGIT (s[1]) << 4) + XDIGIT (s[2]))
-
-/* Copy&pasted from libsoup's soup-uri.c after applying the patch in
- * https://bugzilla.gnome.org/show_bug.cgi?id=630540. We need this
- * instead of soup_uri_decode() as it incorrectly returns NULL for
- * incorrectly encoded URLs. TODO: remove this when required libsoup
- * version is bumped out to 2.32.1
- */
-gchar *
-webkit_soup_request_uri_decoded_copy (const char *part, int length)
-{
- unsigned char *s, *d;
- char *decoded = g_strndup (part, length);
-
- s = d = (unsigned char *)decoded;
- do {
- if (*s == '%') {
- if (!g_ascii_isxdigit (s[1]) ||
- !g_ascii_isxdigit (s[2])) {
- *d++ = *s;
- continue;
- }
- *d++ = HEXCHAR (s);
- s += 2;
- } else
- *d++ = *s;
- } while (*s++);
-
- return decoded;
-}
diff --git a/Source/WebCore/platform/network/soup/cache/soup-request.h b/Source/WebCore/platform/network/soup/cache/soup-request.h
deleted file mode 100644
index 837d8f4..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-request.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2009 Red Hat, Inc.
- * Copyright (C) 2010 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef WEBKIT_SOUP_REQUEST_H
-#define WEBKIT_SOUP_REQUEST_H 1
-
-#include <libsoup/soup.h>
-#include <gio/gio.h>
-
-G_BEGIN_DECLS
-
-#define WEBKIT_TYPE_SOUP_REQUEST (webkit_soup_request_get_type ())
-#define WEBKIT_SOUP_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), WEBKIT_TYPE_SOUP_REQUEST, WebKitSoupRequest))
-#define WEBKIT_SOUP_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), WEBKIT_TYPE_SOUP_REQUEST, WebKitSoupRequestClass))
-#define WEBKIT_IS_SOUP_REQUEST(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WEBKIT_TYPE_SOUP_REQUEST))
-#define WEBKIT_IS_SOUP_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), WEBKIT_TYPE_SOUP_REQUEST))
-#define WEBKIT_SOUP_REQUEST_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), WEBKIT_TYPE_SOUP_REQUEST, WebKitSoupRequestClass))
-
-typedef struct _WebKitSoupRequest WebKitSoupRequest;
-typedef struct _WebKitSoupRequestPrivate WebKitSoupRequestPrivate;
-typedef struct _WebKitSoupRequestClass WebKitSoupRequestClass;
-
-struct _WebKitSoupRequest {
- GObject parent;
-
- WebKitSoupRequestPrivate *priv;
-};
-
-struct _WebKitSoupRequestClass {
- GObjectClass parent;
-
- gboolean (*check_uri)(WebKitSoupRequest *req_base,
- SoupURI *uri,
- GError **error);
-
- GInputStream * (*send)(WebKitSoupRequest *request,
- GCancellable *cancellable,
- GError **error);
- void (*send_async)(WebKitSoupRequest *request,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
- GInputStream * (*send_finish)(WebKitSoupRequest *request,
- GAsyncResult *result,
- GError **error);
-
- goffset (*get_content_length)(WebKitSoupRequest *request);
- const char * (*get_content_type)(WebKitSoupRequest *request);
-};
-
-GType webkit_soup_request_get_type (void);
-
-#define WEBKIT_SOUP_REQUEST_URI "uri"
-#define WEBKIT_SOUP_REQUEST_SESSION "session"
-
-GInputStream *webkit_soup_request_send (WebKitSoupRequest *request,
- GCancellable *cancellable,
- GError **error);
-void webkit_soup_request_send_async (WebKitSoupRequest *request,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-GInputStream *webkit_soup_request_send_finish (WebKitSoupRequest *request,
- GAsyncResult *result,
- GError **error);
-
-SoupURI *webkit_soup_request_get_uri (WebKitSoupRequest *request);
-SoupSession *webkit_soup_request_get_session (WebKitSoupRequest *request);
-
-goffset webkit_soup_request_get_content_length (WebKitSoupRequest *request);
-const char *webkit_soup_request_get_content_type (WebKitSoupRequest *request);
-
-/* Used by WebKitSoupRequestFile and WebKitSoupRequestData. Ideally
- * should be located in some util file but I'll place it here as it
- * will be removed with libsoup 2.32.1 that will ship fixed versions
- * of soup_uri_decode/normalize
- */
-gchar *webkit_soup_request_uri_decoded_copy (const char *part, int length);
-
-G_END_DECLS
-
-#endif /* WEBKIT_SOUP_REQUEST_H */
diff --git a/Source/WebCore/platform/network/soup/cache/soup-requester.c b/Source/WebCore/platform/network/soup/cache/soup-requester.c
deleted file mode 100644
index 4d8a860..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-requester.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * soup-requester.c:
- *
- * Copyright (C) 2010, 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#include "config.h"
-#include "soup-requester.h"
-
-#include "soup-request-data.h"
-#include "soup-request-file.h"
-#include "soup-request-http.h"
-#include <glib/gi18n.h>
-#include <libsoup/soup.h>
-
-struct _WebKitSoupRequesterPrivate {
- GHashTable *request_types;
-};
-
-#define WEBKIT_SOUP_REQUESTER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), WEBKIT_TYPE_SOUP_REQUESTER, WebKitSoupRequesterPrivate))
-
-G_DEFINE_TYPE (WebKitSoupRequester, webkit_soup_requester, G_TYPE_OBJECT)
-
-static void webkit_soup_requester_init (WebKitSoupRequester *requester)
-{
- requester->priv = WEBKIT_SOUP_REQUESTER_GET_PRIVATE (requester);
-
- requester->priv->request_types = 0;
-}
-
-static void finalize (GObject *object)
-{
- WebKitSoupRequester *requester = WEBKIT_SOUP_REQUESTER (object);
-
- if (requester->priv->request_types)
- g_hash_table_destroy (requester->priv->request_types);
-
- G_OBJECT_CLASS (webkit_soup_requester_parent_class)->finalize (object);
-}
-
-static void webkit_soup_requester_class_init (WebKitSoupRequesterClass *requester_class)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (requester_class);
-
- g_type_class_add_private (requester_class, sizeof (WebKitSoupRequesterPrivate));
-
- /* virtual method override */
- object_class->finalize = finalize;
-}
-
-static void init_request_types (WebKitSoupRequesterPrivate *priv)
-{
- if (priv->request_types)
- return;
-
- priv->request_types = g_hash_table_new_full (soup_str_case_hash,
- soup_str_case_equal,
- g_free, 0);
- g_hash_table_insert (priv->request_types, g_strdup ("file"),
- GSIZE_TO_POINTER (WEBKIT_TYPE_SOUP_REQUEST_FILE));
- g_hash_table_insert (priv->request_types, g_strdup ("data"),
- GSIZE_TO_POINTER (WEBKIT_TYPE_SOUP_REQUEST_DATA));
- g_hash_table_insert (priv->request_types, g_strdup ("http"),
- GSIZE_TO_POINTER (WEBKIT_TYPE_SOUP_REQUEST_HTTP));
- g_hash_table_insert (priv->request_types, g_strdup ("https"),
- GSIZE_TO_POINTER (WEBKIT_TYPE_SOUP_REQUEST_HTTP));
- g_hash_table_insert (priv->request_types, g_strdup ("ftp"),
- GSIZE_TO_POINTER (WEBKIT_TYPE_SOUP_REQUEST_FILE));
-}
-
-WebKitSoupRequester *webkit_soup_requester_new (void)
-{
- return (WebKitSoupRequester *)g_object_new (WEBKIT_TYPE_SOUP_REQUESTER, NULL);
-}
-
-WebKitSoupRequest *webkit_soup_requester_request (WebKitSoupRequester *requester, const char *uriString, SoupSession *session, GError **error)
-{
- SoupURI *uri = NULL;
- WebKitSoupRequest *req;
-
- uri = soup_uri_new (uriString);
- if (!uri) {
- g_set_error (error, WEBKIT_SOUP_ERROR, WEBKIT_SOUP_ERROR_BAD_URI,
- _ ("Could not parse URI '%s'"), uriString);
- return 0;
- }
-
- req = webkit_soup_requester_request_uri (requester, uri, session, error);
- soup_uri_free (uri);
- return req;
-}
-
-WebKitSoupRequest *webkit_soup_requester_request_uri (WebKitSoupRequester *requester, SoupURI *uri, SoupSession *session, GError **error)
-{
- GType requestType;
-
- g_return_val_if_fail (WEBKIT_IS_SOUP_REQUESTER (requester), 0);
-
- init_request_types (requester->priv);
- requestType = (GType)GPOINTER_TO_SIZE (g_hash_table_lookup (requester->priv->request_types, uri->scheme));
- if (!requestType) {
- g_set_error (error, WEBKIT_SOUP_ERROR, WEBKIT_SOUP_ERROR_UNSUPPORTED_URI_SCHEME,
- _ ("Unsupported URI scheme '%s'"), uri->scheme);
- return 0;
- }
-
- if (g_type_is_a (requestType, G_TYPE_INITABLE)) {
- return (WebKitSoupRequest *)g_initable_new (requestType, 0, error,
- "uri", uri,
- "session", session,
- NULL);
- } else {
- return (WebKitSoupRequest *)g_object_new (requestType,
- "uri", uri,
- "session", session,
- NULL);
- }
-}
-
-/* RFC 2396, 3.1 */
-static gboolean
-soup_scheme_is_valid (const char *scheme)
-{
- if (scheme == NULL ||
- !g_ascii_isalpha (*scheme))
- return FALSE;
-
- scheme++;
- while (*scheme) {
- if (!g_ascii_isalpha (*scheme) &&
- !g_ascii_isdigit (*scheme) &&
- *scheme != '+' &&
- *scheme != '-' &&
- *scheme != '.')
- return FALSE;
- scheme++;
- }
- return TRUE;
-}
-
-void
-webkit_soup_requester_add_protocol (WebKitSoupRequester *requester,
- const char *scheme,
- GType request_type)
-{
- g_return_if_fail (WEBKIT_IS_SOUP_REQUESTER (requester));
- g_return_if_fail (soup_scheme_is_valid (scheme));
-
- init_request_types (requester->priv);
- g_hash_table_insert (requester->priv->request_types, g_strdup (scheme),
- GSIZE_TO_POINTER (request_type));
-}
-
-void
-webkit_soup_requester_remove_protocol (WebKitSoupRequester *requester,
- const char *scheme)
-{
- g_return_if_fail (WEBKIT_IS_SOUP_REQUESTER (requester));
- g_return_if_fail (soup_scheme_is_valid (scheme));
-
- init_request_types (requester->priv);
- g_hash_table_remove (requester->priv->request_types, scheme);
-}
-
-GQuark
-webkit_soup_error_quark (void)
-{
- static GQuark error;
- if (!error)
- error = g_quark_from_static_string ("webkit_soup_error_quark");
- return error;
-}
diff --git a/Source/WebCore/platform/network/soup/cache/soup-requester.h b/Source/WebCore/platform/network/soup/cache/soup-requester.h
deleted file mode 100644
index 71ff103..0000000
--- a/Source/WebCore/platform/network/soup/cache/soup-requester.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright (C) 2010 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef WEBKIT_SOUP_REQUESTER_H
-#define WEBKIT_SOUP_REQUESTER_H 1
-
-#include "soup-request.h"
-#include <libsoup/soup.h>
-
-G_BEGIN_DECLS
-
-#define WEBKIT_TYPE_SOUP_REQUESTER (webkit_soup_requester_get_type ())
-#define WEBKIT_SOUP_REQUESTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), WEBKIT_TYPE_SOUP_REQUESTER, WebKitSoupRequester))
-#define WEBKIT_SOUP_REQUESTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), WEBKIT_TYPE_SOUP_REQUESTER, WebKitSoupRequesterClass))
-#define WEBKIT_IS_SOUP_REQUESTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WEBKIT_TYPE_SOUP_REQUESTER))
-#define WEBKIT_IS_SOUP_REQUESTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), WEBKIT_TYPE_SOUP_REQUESTER))
-#define WEBKIT_SOUP_REQUESTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), WEBKIT_TYPE_SOUP_REQUESTER, WebKitSoupRequesterClass))
-
-#define WEBKIT_SOUP_ERROR webkit_soup_error_quark ()
-
-typedef enum {
- WEBKIT_SOUP_ERROR_BAD_URI,
- WEBKIT_SOUP_ERROR_UNSUPPORTED_URI_SCHEME
-} WebKitSoupError;
-
-typedef struct _WebKitSoupRequester WebKitSoupRequester;
-typedef struct _WebKitSoupRequesterPrivate WebKitSoupRequesterPrivate;
-
-struct _WebKitSoupRequester {
- GObject parent;
-
- WebKitSoupRequesterPrivate *priv;
-};
-
-typedef struct {
- GObjectClass parent_class;
-} WebKitSoupRequesterClass;
-
-GType webkit_soup_requester_get_type (void);
-
-WebKitSoupRequester *webkit_soup_requester_new (void);
-
-GQuark webkit_soup_error_quark (void);
-
-WebKitSoupRequest *webkit_soup_requester_request (WebKitSoupRequester *requester,
- const char *uriString,
- SoupSession *session,
- GError **error);
-
-WebKitSoupRequest *webkit_soup_requester_request_uri (WebKitSoupRequester *requester,
- SoupURI *uri,
- SoupSession *session,
- GError **error);
-
-void webkit_soup_requester_add_protocol (WebKitSoupRequester *requester,
- const char *scheme,
- GType request_type);
-
-void webkit_soup_requester_remove_protocol (WebKitSoupRequester *requester,
- const char *scheme);
-
-G_END_DECLS
-
-#endif /* WEBKIT_SOUP_REQUESTER_H */
diff --git a/Source/WebCore/platform/network/soup/cache/webkit/soup-cache-private.h b/Source/WebCore/platform/network/soup/cache/webkit/soup-cache-private.h
deleted file mode 100644
index 8af8de2..0000000
--- a/Source/WebCore/platform/network/soup/cache/webkit/soup-cache-private.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * soup-cache-private.h:
- *
- * Copyright (C) 2010 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef WEBKIT_SOUP_CACHE_PRIVATE_H
-#define WEBKIT_SOUP_CACHE_PRIVATE_H 1
-
-#include "soup-cache.h"
-#include <libsoup/soup-message.h>
-
-G_BEGIN_DECLS
-
-WebKitSoupCacheResponse webkit_soup_cache_has_response (WebKitSoupCache *cache,
- SoupMessage *msg);
-GInputStream *webkit_soup_cache_send_response (WebKitSoupCache *cache,
- SoupMessage *msg);
-WebKitSoupCacheability webkit_soup_cache_get_cacheability (WebKitSoupCache *cache,
- SoupMessage *msg);
-SoupMessage *webkit_soup_cache_generate_conditional_request (WebKitSoupCache *cache,
- SoupMessage *original);
-
-G_END_DECLS
-
-#endif /* WEBKIT_SOUP_CACHE_PRIVATE_H */
diff --git a/Source/WebCore/platform/network/soup/cache/webkit/soup-cache.c b/Source/WebCore/platform/network/soup/cache/webkit/soup-cache.c
deleted file mode 100644
index b96428d..0000000
--- a/Source/WebCore/platform/network/soup/cache/webkit/soup-cache.c
+++ /dev/null
@@ -1,1677 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * soup-cache.c
- *
- * Copyright (C) 2009, 2010 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-/* TODO:
- * - Need to hook the feature in the sync SoupSession.
- * - Need more tests.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "soup-cache.h"
-#include "soup-cache-private.h"
-#include <libsoup/soup.h>
-#include <gio/gio.h>
-#include <stdlib.h>
-
-static SoupSessionFeatureInterface *webkit_soup_cache_default_feature_interface;
-static void webkit_soup_cache_session_feature_init (SoupSessionFeatureInterface *feature_interface, gpointer interface_data);
-
-#define DEFAULT_MAX_SIZE 50 * 1024 * 1024
-#define MAX_ENTRY_DATA_PERCENTAGE 10 /* Percentage of the total size
- of the cache that can be
- filled by a single entry */
-
-typedef struct _WebKitSoupCacheEntry {
- char *key;
- char *filename;
- guint freshness_lifetime;
- gboolean must_revalidate;
- GString *data;
- gsize pos;
- gsize length;
- time_t corrected_initial_age;
- time_t response_time;
- gboolean writing;
- gboolean dirty;
- gboolean got_body;
- gboolean being_validated;
- SoupMessageHeaders *headers;
- GOutputStream *stream;
- GError *error;
- guint hits;
- GCancellable *cancellable;
-} WebKitSoupCacheEntry;
-
-struct _WebKitSoupCachePrivate {
- char *cache_dir;
- GHashTable *cache;
- guint n_pending;
- SoupSession *session;
- WebKitSoupCacheType cache_type;
- guint size;
- guint max_size;
- guint max_entry_data_size; /* Computed value. Here for performance reasons */
- GList *lru_start;
-};
-
-typedef struct {
- WebKitSoupCache *cache;
- WebKitSoupCacheEntry *entry;
- SoupMessage *msg;
- gulong got_chunk_handler;
- gulong got_body_handler;
- gulong restarted_handler;
-} WebKitSoupCacheWritingFixture;
-
-enum {
- PROP_0,
- PROP_CACHE_DIR,
- PROP_CACHE_TYPE
-};
-
-#define WEBKIT_SOUP_CACHE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), WEBKIT_TYPE_SOUP_CACHE, WebKitSoupCachePrivate))
-
-G_DEFINE_TYPE_WITH_CODE (WebKitSoupCache, webkit_soup_cache, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE,
- webkit_soup_cache_session_feature_init))
-
-static gboolean webkit_soup_cache_entry_remove (WebKitSoupCache *cache, WebKitSoupCacheEntry *entry);
-static void make_room_for_new_entry (WebKitSoupCache *cache, guint length_to_add);
-static gboolean cache_accepts_entries_of_size (WebKitSoupCache *cache, guint length_to_add);
-
-static WebKitSoupCacheability
-get_cacheability (WebKitSoupCache *cache, SoupMessage *msg)
-{
- WebKitSoupCacheability cacheability;
- const char *cache_control;
-
- /* 1. The request method must be cacheable */
- if (msg->method == SOUP_METHOD_GET)
- cacheability = WEBKIT_SOUP_CACHE_CACHEABLE;
- else if (msg->method == SOUP_METHOD_HEAD ||
- msg->method == SOUP_METHOD_TRACE ||
- msg->method == SOUP_METHOD_CONNECT)
- return WEBKIT_SOUP_CACHE_UNCACHEABLE;
- else
- return (WEBKIT_SOUP_CACHE_UNCACHEABLE | WEBKIT_SOUP_CACHE_INVALIDATES);
-
- cache_control = soup_message_headers_get (msg->response_headers, "Cache-Control");
- if (cache_control) {
- GHashTable *hash;
- WebKitSoupCachePrivate *priv = WEBKIT_SOUP_CACHE_GET_PRIVATE (cache);
-
- hash = soup_header_parse_param_list (cache_control);
-
- /* Shared caches MUST NOT store private resources */
- if (priv->cache_type == WEBKIT_SOUP_CACHE_SHARED) {
- if (g_hash_table_lookup_extended (hash, "private", NULL, NULL)) {
- soup_header_free_param_list (hash);
- return WEBKIT_SOUP_CACHE_UNCACHEABLE;
- }
- }
-
- /* 2. The 'no-store' cache directive does not appear in the
- * headers
- */
- if (g_hash_table_lookup_extended (hash, "no-store", NULL, NULL)) {
- soup_header_free_param_list (hash);
- return WEBKIT_SOUP_CACHE_UNCACHEABLE;
- }
-
- /* This does not appear in section 2.1, but I think it makes
- * sense to check it too?
- */
- if (g_hash_table_lookup_extended (hash, "no-cache", NULL, NULL)) {
- soup_header_free_param_list (hash);
- return WEBKIT_SOUP_CACHE_UNCACHEABLE;
- }
-
- soup_header_free_param_list (hash);
- }
-
- switch (msg->status_code) {
- case SOUP_STATUS_PARTIAL_CONTENT:
- /* We don't cache partial responses, but they only
- * invalidate cached full responses if the headers
- * don't match.
- */
- cacheability = WEBKIT_SOUP_CACHE_UNCACHEABLE;
- break;
-
- case SOUP_STATUS_NOT_MODIFIED:
- /* A 304 response validates an existing cache entry */
- cacheability = WEBKIT_SOUP_CACHE_VALIDATES;
- break;
-
- case SOUP_STATUS_MULTIPLE_CHOICES:
- case SOUP_STATUS_MOVED_PERMANENTLY:
- case SOUP_STATUS_GONE:
- /* FIXME: cacheable unless indicated otherwise */
- cacheability = WEBKIT_SOUP_CACHE_UNCACHEABLE;
- break;
-
- case SOUP_STATUS_FOUND:
- case SOUP_STATUS_TEMPORARY_REDIRECT:
- /* FIXME: cacheable if explicitly indicated */
- cacheability = WEBKIT_SOUP_CACHE_UNCACHEABLE;
- break;
-
- case SOUP_STATUS_SEE_OTHER:
- case SOUP_STATUS_FORBIDDEN:
- case SOUP_STATUS_NOT_FOUND:
- case SOUP_STATUS_METHOD_NOT_ALLOWED:
- return (WEBKIT_SOUP_CACHE_UNCACHEABLE | WEBKIT_SOUP_CACHE_INVALIDATES);
-
- default:
- /* Any 5xx status or any 4xx status not handled above
- * is uncacheable but doesn't break the cache.
- */
- if ((msg->status_code >= SOUP_STATUS_BAD_REQUEST &&
- msg->status_code <= SOUP_STATUS_FAILED_DEPENDENCY) ||
- msg->status_code >= SOUP_STATUS_INTERNAL_SERVER_ERROR)
- return WEBKIT_SOUP_CACHE_UNCACHEABLE;
-
- /* An unrecognized 2xx, 3xx, or 4xx response breaks
- * the cache.
- */
- if ((msg->status_code > SOUP_STATUS_PARTIAL_CONTENT &&
- msg->status_code < SOUP_STATUS_MULTIPLE_CHOICES) ||
- (msg->status_code > SOUP_STATUS_TEMPORARY_REDIRECT &&
- msg->status_code < SOUP_STATUS_INTERNAL_SERVER_ERROR))
- return (WEBKIT_SOUP_CACHE_UNCACHEABLE | WEBKIT_SOUP_CACHE_INVALIDATES);
- break;
- }
-
- return cacheability;
-}
-
-static void
-webkit_soup_cache_entry_free (WebKitSoupCacheEntry *entry, gboolean purge)
-{
- if (purge) {
- GFile *file = g_file_new_for_path (entry->filename);
- g_file_delete (file, NULL, NULL);
- g_object_unref (file);
- }
-
- g_free (entry->filename);
- entry->filename = NULL;
- g_free (entry->key);
- entry->key = NULL;
-
- if (entry->headers) {
- soup_message_headers_free (entry->headers);
- entry->headers = NULL;
- }
-
- if (entry->data) {
- g_string_free (entry->data, TRUE);
- entry->data = NULL;
- }
- if (entry->error) {
- g_error_free (entry->error);
- entry->error = NULL;
- }
- if (entry->cancellable) {
- g_object_unref (entry->cancellable);
- entry->cancellable = NULL;
- }
-
- g_slice_free (WebKitSoupCacheEntry, entry);
-}
-
-static void
-copy_headers (const char *name, const char *value, SoupMessageHeaders *headers)
-{
- soup_message_headers_append (headers, name, value);
-}
-
-static void
-update_headers (const char *name, const char *value, SoupMessageHeaders *headers)
-{
- if (soup_message_headers_get (headers, name))
- soup_message_headers_replace (headers, name, value);
- else
- soup_message_headers_append (headers, name, value);
-}
-
-static guint
-webkit_soup_cache_entry_get_current_age (WebKitSoupCacheEntry *entry)
-{
- time_t now = time (NULL);
- time_t resident_time;
-
- resident_time = now - entry->response_time;
- return entry->corrected_initial_age + resident_time;
-}
-
-static gboolean
-webkit_soup_cache_entry_is_fresh_enough (WebKitSoupCacheEntry *entry, gint min_fresh)
-{
- guint limit = (min_fresh == -1) ? webkit_soup_cache_entry_get_current_age (entry) : (guint) min_fresh;
- return entry->freshness_lifetime > limit;
-}
-
-static char *
-soup_message_get_cache_key (SoupMessage *msg)
-{
- SoupURI *uri = soup_message_get_uri (msg);
- return soup_uri_to_string (uri, FALSE);
-}
-
-static void
-webkit_soup_cache_entry_set_freshness (WebKitSoupCacheEntry *entry, SoupMessage *msg, WebKitSoupCache *cache)
-{
- const char *cache_control;
- const char *expires, *date, *last_modified;
-
- cache_control = soup_message_headers_get (entry->headers, "Cache-Control");
- if (cache_control) {
- const char *max_age, *s_maxage;
- gint64 freshness_lifetime = 0;
- GHashTable *hash;
- WebKitSoupCachePrivate *priv = WEBKIT_SOUP_CACHE_GET_PRIVATE (cache);
-
- hash = soup_header_parse_param_list (cache_control);
-
- /* Should we re-validate the entry when it goes stale */
- entry->must_revalidate = g_hash_table_lookup_extended (hash, "must-revalidate", NULL, NULL);
-
- /* Section 2.3.1 */
- if (priv->cache_type == WEBKIT_SOUP_CACHE_SHARED) {
- s_maxage = g_hash_table_lookup (hash, "s-maxage");
- if (s_maxage) {
- freshness_lifetime = g_ascii_strtoll (s_maxage, NULL, 10);
- if (freshness_lifetime) {
- /* Implies proxy-revalidate. TODO: is it true? */
- entry->must_revalidate = TRUE;
- soup_header_free_param_list (hash);
- return;
- }
- }
- }
-
- /* If 'max-age' cache directive is present, use that */
- max_age = g_hash_table_lookup (hash, "max-age");
- if (max_age)
- freshness_lifetime = g_ascii_strtoll (max_age, NULL, 10);
-
- if (freshness_lifetime) {
- entry->freshness_lifetime = (guint)MIN (freshness_lifetime, G_MAXUINT32);
- soup_header_free_param_list (hash);
- return;
- }
-
- soup_header_free_param_list (hash);
- }
-
- /* If the 'Expires' response header is present, use its value
- * minus the value of the 'Date' response header
- */
- expires = soup_message_headers_get (entry->headers, "Expires");
- date = soup_message_headers_get (entry->headers, "Date");
- if (expires && date) {
- SoupDate *expires_d, *date_d;
- time_t expires_t, date_t;
-
- expires_d = soup_date_new_from_string (expires);
- if (expires_d) {
- date_d = soup_date_new_from_string (date);
-
- expires_t = soup_date_to_time_t (expires_d);
- date_t = soup_date_to_time_t (date_d);
-
- soup_date_free (expires_d);
- soup_date_free (date_d);
-
- if (expires_t && date_t) {
- entry->freshness_lifetime = (guint)MAX (expires_t - date_t, 0);
- return;
- }
- } else {
- /* If Expires is not a valid date we should
- treat it as already expired, see section
- 3.3 */
- entry->freshness_lifetime = 0;
- return;
- }
- }
-
- /* Otherwise an heuristic may be used */
-
- /* Heuristics MUST NOT be used with these status codes
- (section 2.3.1.1) */
- if (msg->status_code != SOUP_STATUS_OK &&
- msg->status_code != SOUP_STATUS_NON_AUTHORITATIVE &&
- msg->status_code != SOUP_STATUS_PARTIAL_CONTENT &&
- msg->status_code != SOUP_STATUS_MULTIPLE_CHOICES &&
- msg->status_code != SOUP_STATUS_MOVED_PERMANENTLY &&
- msg->status_code != SOUP_STATUS_GONE)
- goto expire;
-
- /* TODO: attach warning 113 if response's current_age is more
- than 24h (section 2.3.1.1) when using heuristics */
-
- /* Last-Modified based heuristic */
- last_modified = soup_message_headers_get (entry->headers, "Last-Modified");
- if (last_modified) {
- SoupDate *soup_date;
- time_t now, last_modified_t;
-
- soup_date = soup_date_new_from_string (last_modified);
- last_modified_t = soup_date_to_time_t (soup_date);
- now = time (NULL);
-
-#define HEURISTIC_FACTOR 0.1 /* From Section 2.3.1.1 */
-
- entry->freshness_lifetime = MAX (0, (now - last_modified_t) * HEURISTIC_FACTOR);
- soup_date_free (soup_date);
- }
-
- return;
-
- expire:
- /* If all else fails, make the entry expire immediately */
- entry->freshness_lifetime = 0;
-}
-
-static WebKitSoupCacheEntry *
-webkit_soup_cache_entry_new (WebKitSoupCache *cache, SoupMessage *msg, time_t request_time, time_t response_time)
-{
- WebKitSoupCacheEntry *entry;
- SoupMessageHeaders *headers;
- const char *date;
- char *md5;
-
- entry = g_slice_new0 (WebKitSoupCacheEntry);
- entry->dirty = FALSE;
- entry->writing = FALSE;
- entry->got_body = FALSE;
- entry->being_validated = FALSE;
- entry->data = g_string_new (NULL);
- entry->pos = 0;
- entry->error = NULL;
-
- /* key & filename */
- entry->key = soup_message_get_cache_key (msg);
- md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, entry->key, -1);
- entry->filename = g_build_filename (cache->priv->cache_dir, md5, NULL);
- g_free (md5);
-
- /* Headers */
- headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_RESPONSE);
- soup_message_headers_foreach (msg->response_headers,
- (SoupMessageHeadersForeachFunc)copy_headers,
- headers);
- entry->headers = headers;
-
- /* LRU list */
- entry->hits = 0;
-
- /* Section 2.3.1, Freshness Lifetime */
- webkit_soup_cache_entry_set_freshness (entry, msg, cache);
-
- /* Section 2.3.2, Calculating Age */
- date = soup_message_headers_get (entry->headers, "Date");
-
- if (date) {
- SoupDate *soup_date;
- const char *age;
- time_t date_value, apparent_age, corrected_received_age, response_delay, age_value = 0;
-
- soup_date = soup_date_new_from_string (date);
- date_value = soup_date_to_time_t (soup_date);
- soup_date_free (soup_date);
-
- age = soup_message_headers_get (entry->headers, "Age");
- if (age)
- age_value = g_ascii_strtoll (age, NULL, 10);
-
- entry->response_time = response_time;
- apparent_age = MAX (0, entry->response_time - date_value);
- corrected_received_age = MAX (apparent_age, age_value);
- response_delay = entry->response_time - request_time;
- entry->corrected_initial_age = corrected_received_age + response_delay;
- } else {
- /* Is this correct ? */
- entry->corrected_initial_age = time (NULL);
- }
-
- return entry;
-}
-
-static void
-webkit_soup_cache_writing_fixture_free (WebKitSoupCacheWritingFixture *fixture)
-{
- /* Free fixture. And disconnect signals, we don't want to
- listen to more SoupMessage events as we're finished with
- this resource */
- if (g_signal_handler_is_connected (fixture->msg, fixture->got_chunk_handler))
- g_signal_handler_disconnect (fixture->msg, fixture->got_chunk_handler);
- if (g_signal_handler_is_connected (fixture->msg, fixture->got_body_handler))
- g_signal_handler_disconnect (fixture->msg, fixture->got_body_handler);
- if (g_signal_handler_is_connected (fixture->msg, fixture->restarted_handler))
- g_signal_handler_disconnect (fixture->msg, fixture->restarted_handler);
- g_object_unref (fixture->msg);
- g_object_unref (fixture->cache);
- g_slice_free (WebKitSoupCacheWritingFixture, fixture);
-}
-
-static void
-close_ready_cb (GObject *source, GAsyncResult *result, WebKitSoupCacheWritingFixture *fixture)
-{
- WebKitSoupCacheEntry *entry = fixture->entry;
- WebKitSoupCache *cache = fixture->cache;
- GOutputStream *stream = G_OUTPUT_STREAM (source);
- goffset content_length;
-
- g_warn_if_fail (entry->error == NULL);
-
- /* FIXME: what do we do on error ? */
-
- if (stream) {
- g_output_stream_close_finish (stream, result, NULL);
- g_object_unref (stream);
- }
- entry->stream = NULL;
-
- content_length = soup_message_headers_get_content_length (entry->headers);
-
- /* If the process was cancelled, then delete the entry from
- the cache. Do it also if the size of a chunked resource is
- too much for the cache */
- if (g_cancellable_is_cancelled (entry->cancellable)) {
- entry->dirty = FALSE;
- webkit_soup_cache_entry_remove (cache, entry);
- webkit_soup_cache_entry_free (entry, TRUE);
- entry = NULL;
- } else if ((soup_message_headers_get_encoding (entry->headers) == SOUP_ENCODING_CHUNKED) ||
- entry->length != (gsize) content_length) {
- /** Two options here:
- *
- * 1. "chunked" data, entry was temporarily added to
- * cache (as content-length is 0) and now that we have
- * the actual size we have to evaluate if we want it
- * in the cache or not
- *
- * 2. Content-Length has a different value than actual
- * length, means that the content was encoded for
- * transmission (typically compressed) and thus we
- * have to substract the content-length value that was
- * added to the cache and add the unencoded length
- **/
- gint length_to_add = entry->length - content_length;
-
- /* Make room in cache if needed */
- if (cache_accepts_entries_of_size (cache, length_to_add)) {
- make_room_for_new_entry (cache, length_to_add);
-
- cache->priv->size += length_to_add;
- } else {
- entry->dirty = FALSE;
- webkit_soup_cache_entry_remove (cache, entry);
- webkit_soup_cache_entry_free (entry, TRUE);
- entry = NULL;
- }
- }
-
- if (entry) {
- /* Get rid of the GString in memory for the resource now */
- if (entry->data) {
- g_string_free (entry->data, TRUE);
- entry->data = NULL;
- }
-
- entry->dirty = FALSE;
- entry->writing = FALSE;
- entry->got_body = FALSE;
- entry->pos = 0;
-
- g_object_unref (entry->cancellable);
- entry->cancellable = NULL;
- }
-
- cache->priv->n_pending--;
-
- /* Frees */
- webkit_soup_cache_writing_fixture_free (fixture);
-}
-
-static void
-write_ready_cb (GObject *source, GAsyncResult *result, WebKitSoupCacheWritingFixture *fixture)
-{
- GOutputStream *stream = G_OUTPUT_STREAM (source);
- GError *error = NULL;
- gssize write_size;
- WebKitSoupCacheEntry *entry = fixture->entry;
-
- if (g_cancellable_is_cancelled (entry->cancellable)) {
- g_output_stream_close_async (stream,
- G_PRIORITY_LOW,
- entry->cancellable,
- (GAsyncReadyCallback)close_ready_cb,
- fixture);
- return;
- }
-
- write_size = g_output_stream_write_finish (stream, result, &error);
- if (write_size <= 0 || error) {
- if (error)
- entry->error = error;
- g_output_stream_close_async (stream,
- G_PRIORITY_LOW,
- entry->cancellable,
- (GAsyncReadyCallback)close_ready_cb,
- fixture);
- /* FIXME: We should completely stop caching the
- resource at this point */
- } else {
- entry->pos += write_size;
-
- /* Are we still writing and is there new data to write
- already ? */
- if (entry->data && entry->pos < entry->data->len) {
- g_output_stream_write_async (entry->stream,
- entry->data->str + entry->pos,
- entry->data->len - entry->pos,
- G_PRIORITY_LOW,
- entry->cancellable,
- (GAsyncReadyCallback)write_ready_cb,
- fixture);
- } else {
- entry->writing = FALSE;
-
- if (entry->got_body) {
- /* If we already received 'got-body'
- and we have written all the data,
- we can close the stream */
- g_output_stream_close_async (entry->stream,
- G_PRIORITY_LOW,
- entry->cancellable,
- (GAsyncReadyCallback)close_ready_cb,
- fixture);
- }
- }
- }
-}
-
-static void
-msg_got_chunk_cb (SoupMessage *msg, SoupBuffer *chunk, WebKitSoupCacheWritingFixture *fixture)
-{
- WebKitSoupCacheEntry *entry = fixture->entry;
-
- g_return_if_fail (chunk->data && chunk->length);
- g_return_if_fail (entry);
-
- /* Ignore this if the writing or appending was cancelled */
- if (!g_cancellable_is_cancelled (entry->cancellable)) {
- g_string_append_len (entry->data, chunk->data, chunk->length);
- entry->length = entry->data->len;
-
- if (!cache_accepts_entries_of_size (fixture->cache, entry->length)) {
- /* Quickly cancel the caching of the resource */
- g_cancellable_cancel (entry->cancellable);
- }
- }
-
- /* FIXME: remove the error check when we cancel the caching at
- the first write error */
- /* Only write if the entry stream is ready */
- if (entry->writing == FALSE && entry->error == NULL && entry->stream) {
- GString *data = entry->data;
- entry->writing = TRUE;
- g_output_stream_write_async (entry->stream,
- data->str + entry->pos,
- data->len - entry->pos,
- G_PRIORITY_LOW,
- entry->cancellable,
- (GAsyncReadyCallback)write_ready_cb,
- fixture);
- }
-}
-
-static void
-msg_got_body_cb (SoupMessage *msg, WebKitSoupCacheWritingFixture *fixture)
-{
- WebKitSoupCacheEntry *entry = fixture->entry;
- g_return_if_fail (entry);
-
- entry->got_body = TRUE;
-
- if (!entry->stream && entry->pos != entry->length)
- /* The stream is not ready to be written but we still
- have data to write, we'll write it when the stream
- is opened for writing */
- return;
-
-
- if (entry->pos != entry->length) {
- /* If we still have data to write, write it,
- write_ready_cb will close the stream */
- if (entry->writing == FALSE && entry->error == NULL && entry->stream) {
- g_output_stream_write_async (entry->stream,
- entry->data->str + entry->pos,
- entry->data->len - entry->pos,
- G_PRIORITY_LOW,
- entry->cancellable,
- (GAsyncReadyCallback)write_ready_cb,
- fixture);
- }
- return;
- }
-
- if (entry->stream && !entry->writing)
- g_output_stream_close_async (entry->stream,
- G_PRIORITY_LOW,
- entry->cancellable,
- (GAsyncReadyCallback)close_ready_cb,
- fixture);
-}
-
-static gboolean
-webkit_soup_cache_entry_remove (WebKitSoupCache *cache, WebKitSoupCacheEntry *entry)
-{
- GList *lru_item;
-
- /* if (entry->dirty && !g_cancellable_is_cancelled (entry->cancellable)) { */
- if (entry->dirty) {
- g_cancellable_cancel (entry->cancellable);
- return FALSE;
- }
-
- g_assert (!entry->dirty);
- g_assert (g_list_length (cache->priv->lru_start) == g_hash_table_size (cache->priv->cache));
-
- /* Remove from cache */
- if (!g_hash_table_remove (cache->priv->cache, entry->key))
- return FALSE;
-
- /* Remove from LRU */
- lru_item = g_list_find (cache->priv->lru_start, entry);
- cache->priv->lru_start = g_list_delete_link (cache->priv->lru_start, lru_item);
-
- /* Adjust cache size */
- cache->priv->size -= entry->length;
-
- g_assert (g_list_length (cache->priv->lru_start) == g_hash_table_size (cache->priv->cache));
-
- return TRUE;
-}
-
-static gint
-lru_compare_func (gconstpointer a, gconstpointer b)
-{
- WebKitSoupCacheEntry *entry_a = (WebKitSoupCacheEntry *)a;
- WebKitSoupCacheEntry *entry_b = (WebKitSoupCacheEntry *)b;
-
- /** The rationale of this sorting func is
- *
- * 1. sort by hits -> LRU algorithm, then
- *
- * 2. sort by freshness lifetime, we better discard first
- * entries that are close to expire
- *
- * 3. sort by size, replace first small size resources as they
- * are cheaper to download
- **/
-
- /* Sort by hits */
- if (entry_a->hits != entry_b->hits)
- return entry_a->hits - entry_b->hits;
-
- /* Sort by freshness_lifetime */
- if (entry_a->freshness_lifetime != entry_b->freshness_lifetime)
- return entry_a->freshness_lifetime - entry_b->freshness_lifetime;
-
- /* Sort by size */
- return entry_a->length - entry_b->length;
-}
-
-static gboolean
-cache_accepts_entries_of_size (WebKitSoupCache *cache, guint length_to_add)
-{
- /* We could add here some more heuristics. TODO: review how
- this is done by other HTTP caches */
-
- return length_to_add <= cache->priv->max_entry_data_size;
-}
-
-static void
-make_room_for_new_entry (WebKitSoupCache *cache, guint length_to_add)
-{
- GList *lru_entry = cache->priv->lru_start;
-
- /* Check that there is enough room for the new entry. This is
- an approximation as we're not working out the size of the
- cache file or the size of the headers for performance
- reasons. TODO: check if that would be really that expensive */
-
- while (lru_entry &&
- (length_to_add + cache->priv->size > cache->priv->max_size)) {
- WebKitSoupCacheEntry *old_entry = (WebKitSoupCacheEntry *)lru_entry->data;
-
- /* Discard entries. Once cancelled resources will be
- * freed in close_ready_cb
- */
- if (webkit_soup_cache_entry_remove (cache, old_entry)) {
- webkit_soup_cache_entry_free (old_entry, TRUE);
- lru_entry = cache->priv->lru_start;
- } else
- lru_entry = g_list_next (lru_entry);
- }
-}
-
-static gboolean
-webkit_soup_cache_entry_insert_by_key (WebKitSoupCache *cache,
- const char *key,
- WebKitSoupCacheEntry *entry,
- gboolean sort)
-{
- guint length_to_add = 0;
-
- if (soup_message_headers_get_encoding (entry->headers) != SOUP_ENCODING_CHUNKED)
- length_to_add = soup_message_headers_get_content_length (entry->headers);
-
- /* Check if we are going to store the resource depending on its size */
- if (length_to_add) {
- if (!cache_accepts_entries_of_size (cache, length_to_add))
- return FALSE;
-
- /* Make room for new entry if needed */
- make_room_for_new_entry (cache, length_to_add);
- }
-
- g_hash_table_insert (cache->priv->cache, g_strdup (key), entry);
-
- /* Compute new cache size */
- cache->priv->size += length_to_add;
-
- /* Update LRU */
- if (sort)
- cache->priv->lru_start = g_list_insert_sorted (cache->priv->lru_start, entry, lru_compare_func);
- else
- cache->priv->lru_start = g_list_prepend (cache->priv->lru_start, entry);
-
- g_assert (g_list_length (cache->priv->lru_start) == g_hash_table_size (cache->priv->cache));
-
- return TRUE;
-}
-
-static void
-msg_restarted_cb (SoupMessage *msg, WebKitSoupCacheEntry *entry)
-{
- /* FIXME: What should we do here exactly? */
-}
-
-static void
-append_to_ready_cb (GObject *source, GAsyncResult *result, WebKitSoupCacheWritingFixture *fixture)
-{
- GFile *file = (GFile *)source;
- GOutputStream *stream;
- WebKitSoupCacheEntry *entry = fixture->entry;
-
- stream = (GOutputStream *)g_file_append_to_finish (file, result, &entry->error);
-
- if (g_cancellable_is_cancelled (entry->cancellable) || entry->error) {
- fixture->cache->priv->n_pending--;
- entry->dirty = FALSE;
- webkit_soup_cache_entry_remove (fixture->cache, entry);
- webkit_soup_cache_entry_free (entry, TRUE);
- webkit_soup_cache_writing_fixture_free (fixture);
- return;
- }
-
- entry->stream = g_object_ref (stream);
- g_object_unref (file);
-
- /* If we already got all the data we have to initiate the
- writing here, since we won't get more 'got-chunk'
- signals */
- if (entry->got_body) {
- GString *data = entry->data;
-
- /* It could happen that reading the data from server
- was completed before this happens. In that case
- there is no data */
- if (data) {
- entry->writing = TRUE;
- g_output_stream_write_async (entry->stream,
- data->str + entry->pos,
- data->len - entry->pos,
- G_PRIORITY_LOW,
- entry->cancellable,
- (GAsyncReadyCallback)write_ready_cb,
- fixture);
- }
- }
-}
-
-typedef struct {
- time_t request_time;
- SoupSessionFeature *feature;
- gulong got_headers_handler;
-} RequestHelper;
-
-static void
-msg_got_headers_cb (SoupMessage *msg, gpointer user_data)
-{
- WebKitSoupCache *cache;
- WebKitSoupCacheability cacheable;
- RequestHelper *helper;
- time_t request_time, response_time;
-
- response_time = time (NULL);
-
- helper = (RequestHelper *)user_data;
- cache = WEBKIT_SOUP_CACHE (helper->feature);
- request_time = helper->request_time;
- g_signal_handlers_disconnect_by_func (msg, msg_got_headers_cb, user_data);
- g_slice_free (RequestHelper, helper);
-
- cacheable = webkit_soup_cache_get_cacheability (cache, msg);
-
- if (cacheable & WEBKIT_SOUP_CACHE_CACHEABLE) {
- WebKitSoupCacheEntry *entry;
- char *key;
- GFile *file;
- WebKitSoupCacheWritingFixture *fixture;
-
- /* Check if we are already caching this resource */
- key = soup_message_get_cache_key (msg);
- entry = g_hash_table_lookup (cache->priv->cache, key);
- g_free (key);
-
- if (entry && entry->dirty)
- return;
-
- /* Create a new entry, deleting any old one if present */
- if (entry) {
- webkit_soup_cache_entry_remove (cache, entry);
- webkit_soup_cache_entry_free (entry, TRUE);
- }
-
- entry = webkit_soup_cache_entry_new (cache, msg, request_time, response_time);
- entry->hits = 1;
-
- /* Do not continue if it can not be stored */
- if (!webkit_soup_cache_entry_insert_by_key (cache, (const gchar *)entry->key, entry, TRUE)) {
- webkit_soup_cache_entry_free (entry, TRUE);
- return;
- }
-
- fixture = g_slice_new0 (WebKitSoupCacheWritingFixture);
- fixture->cache = g_object_ref (cache);
- fixture->entry = entry;
- fixture->msg = g_object_ref (msg);
-
- /* We connect now to these signals and buffer the data
- if it comes before the file is ready for writing */
- fixture->got_chunk_handler =
- g_signal_connect (msg, "got-chunk", G_CALLBACK (msg_got_chunk_cb), fixture);
- fixture->got_body_handler =
- g_signal_connect (msg, "got-body", G_CALLBACK (msg_got_body_cb), fixture);
- fixture->restarted_handler =
- g_signal_connect (msg, "restarted", G_CALLBACK (msg_restarted_cb), entry);
-
- /* Prepare entry */
- file = g_file_new_for_path (entry->filename);
- cache->priv->n_pending++;
-
- entry->dirty = TRUE;
- entry->cancellable = g_cancellable_new ();
- g_file_append_to_async (file, 0,
- G_PRIORITY_LOW, entry->cancellable,
- (GAsyncReadyCallback)append_to_ready_cb,
- fixture);
- } else if (cacheable & WEBKIT_SOUP_CACHE_INVALIDATES) {
- char *key;
- WebKitSoupCacheEntry *entry;
-
- key = soup_message_get_cache_key (msg);
- entry = g_hash_table_lookup (cache->priv->cache, key);
- g_free (key);
-
- if (entry) {
- if (webkit_soup_cache_entry_remove (cache, entry))
- webkit_soup_cache_entry_free (entry, TRUE);
- }
- } else if (cacheable & WEBKIT_SOUP_CACHE_VALIDATES) {
- char *key;
- WebKitSoupCacheEntry *entry;
-
- key = soup_message_get_cache_key (msg);
- entry = g_hash_table_lookup (cache->priv->cache, key);
- g_free (key);
-
- /* It's possible to get a CACHE_VALIDATES with no
- * entry in the hash table. This could happen if for
- * example the soup client is the one creating the
- * conditional request.
- */
- if (entry) {
- entry->being_validated = FALSE;
-
- /* We update the headers of the existing cache item,
- plus its age */
- soup_message_headers_foreach (msg->response_headers,
- (SoupMessageHeadersForeachFunc)update_headers,
- entry->headers);
- webkit_soup_cache_entry_set_freshness (entry, msg, cache);
- }
- }
-}
-
-GInputStream *
-webkit_soup_cache_send_response (WebKitSoupCache *cache, SoupMessage *msg)
-{
- char *key;
- WebKitSoupCacheEntry *entry;
- char *current_age;
- GInputStream *stream = NULL;
- GFile *file;
-
- g_return_val_if_fail (WEBKIT_IS_SOUP_CACHE (cache), NULL);
- g_return_val_if_fail (SOUP_IS_MESSAGE (msg), NULL);
-
- key = soup_message_get_cache_key (msg);
- entry = g_hash_table_lookup (cache->priv->cache, key);
- g_free (key);
- g_return_val_if_fail (entry, NULL);
-
- /* If we are told to send a response from cache any validation
- in course is over by now */
- entry->being_validated = FALSE;
-
- /* Headers */
- soup_message_headers_foreach (entry->headers,
- (SoupMessageHeadersForeachFunc)update_headers,
- msg->response_headers);
-
- /* Add 'Age' header with the current age */
- current_age = g_strdup_printf ("%d", webkit_soup_cache_entry_get_current_age (entry));
- soup_message_headers_replace (msg->response_headers,
- "Age",
- current_age);
- g_free (current_age);
-
- /* TODO: the original idea was to save reads, but current code
- assumes that a stream is always returned. Need to reach
- some agreement here. Also we have to handle the situation
- were the file was no longer there (for example files
- removed without notifying the cache */
- file = g_file_new_for_path (entry->filename);
- stream = (GInputStream *)g_file_read (file, NULL, NULL);
-
- return stream;
-}
-
-static void
-request_started (SoupSessionFeature *feature, SoupSession *session,
- SoupMessage *msg, SoupSocket *socket)
-{
- RequestHelper *helper = g_slice_new0 (RequestHelper);
- helper->request_time = time (NULL);
- helper->feature = feature;
- helper->got_headers_handler = g_signal_connect (msg, "got-headers",
- G_CALLBACK (msg_got_headers_cb),
- helper);
-}
-
-static void
-attach (SoupSessionFeature *feature, SoupSession *session)
-{
- WebKitSoupCache *cache = WEBKIT_SOUP_CACHE (feature);
- cache->priv->session = session;
-
- webkit_soup_cache_default_feature_interface->attach (feature, session);
-}
-
-static void
-webkit_soup_cache_session_feature_init (SoupSessionFeatureInterface *feature_interface,
- gpointer interface_data)
-{
- webkit_soup_cache_default_feature_interface =
- g_type_default_interface_peek (SOUP_TYPE_SESSION_FEATURE);
-
- feature_interface->attach = attach;
- feature_interface->request_started = request_started;
-}
-
-static void
-webkit_soup_cache_init (WebKitSoupCache *cache)
-{
- WebKitSoupCachePrivate *priv;
-
- priv = cache->priv = WEBKIT_SOUP_CACHE_GET_PRIVATE (cache);
-
- priv->cache = g_hash_table_new_full (g_str_hash,
- g_str_equal,
- (GDestroyNotify)g_free,
- NULL);
-
- /* LRU */
- priv->lru_start = NULL;
-
- /* */
- priv->n_pending = 0;
-
- /* Cache size */
- priv->max_size = DEFAULT_MAX_SIZE;
- priv->max_entry_data_size = priv->max_size / MAX_ENTRY_DATA_PERCENTAGE;
- priv->size = 0;
-}
-
-static void
-remove_cache_item (gpointer data,
- gpointer user_data)
-{
- WebKitSoupCache *cache = (WebKitSoupCache *) user_data;
- WebKitSoupCacheEntry *entry = (WebKitSoupCacheEntry *) data;
-
- if (webkit_soup_cache_entry_remove (cache, entry))
- webkit_soup_cache_entry_free (entry, FALSE);
-}
-
-static void
-webkit_soup_cache_finalize (GObject *object)
-{
- WebKitSoupCachePrivate *priv;
- GList *entries;
-
- priv = WEBKIT_SOUP_CACHE (object)->priv;
-
- // Cannot use g_hash_table_foreach as callbacks must not modify the hash table
- entries = g_hash_table_get_values (priv->cache);
- g_list_foreach (entries, remove_cache_item, object);
- g_list_free (entries);
-
- g_hash_table_destroy (priv->cache);
- g_free (priv->cache_dir);
-
- g_list_free (priv->lru_start);
- priv->lru_start = NULL;
-
- G_OBJECT_CLASS (webkit_soup_cache_parent_class)->finalize (object);
-}
-
-static void
-webkit_soup_cache_set_property (GObject *object, guint prop_id,
- const GValue *value, GParamSpec *pspec)
-{
- WebKitSoupCachePrivate *priv = WEBKIT_SOUP_CACHE (object)->priv;
-
- switch (prop_id) {
- case PROP_CACHE_DIR:
- priv->cache_dir = g_value_dup_string (value);
- /* Create directory if it does not exist (FIXME: should we?) */
- if (!g_file_test (priv->cache_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
- g_mkdir_with_parents (priv->cache_dir, 0700);
- break;
- case PROP_CACHE_TYPE:
- priv->cache_type = g_value_get_enum (value);
- /* TODO: clear private entries and issue a warning if moving to shared? */
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-webkit_soup_cache_get_property (GObject *object, guint prop_id,
- GValue *value, GParamSpec *pspec)
-{
- WebKitSoupCachePrivate *priv = WEBKIT_SOUP_CACHE (object)->priv;
-
- switch (prop_id) {
- case PROP_CACHE_DIR:
- g_value_set_string (value, priv->cache_dir);
- break;
- case PROP_CACHE_TYPE:
- g_value_set_enum (value, priv->cache_type);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-webkit_soup_cache_constructed (GObject *object)
-{
- WebKitSoupCachePrivate *priv;
-
- priv = WEBKIT_SOUP_CACHE (object)->priv;
-
- if (!priv->cache_dir) {
- /* Set a default cache dir, different for each user */
- priv->cache_dir = g_build_filename (g_get_user_cache_dir (),
- "httpcache",
- NULL);
- if (!g_file_test (priv->cache_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
- g_mkdir_with_parents (priv->cache_dir, 0700);
- }
-
- if (G_OBJECT_CLASS (webkit_soup_cache_parent_class)->constructed)
- G_OBJECT_CLASS (webkit_soup_cache_parent_class)->constructed (object);
-}
-
-#define WEBKIT_SOUP_CACHE_TYPE_TYPE (webkit_soup_cache_type_get_type ())
-static GType
-webkit_soup_cache_type_get_type (void)
-{
- static GType cache_type = 0;
-
- static const GEnumValue cache_types[] = {
- { WEBKIT_SOUP_CACHE_SINGLE_USER, "Single user cache", "user" },
- { WEBKIT_SOUP_CACHE_SHARED, "Shared cache", "shared" },
- { 0, NULL, NULL }
- };
-
- if (!cache_type) {
- cache_type = g_enum_register_static ("WebKitSoupCacheTypeType", cache_types);
- }
- return cache_type;
-}
-
-static void
-webkit_soup_cache_class_init (WebKitSoupCacheClass *cache_class)
-{
- GObjectClass *gobject_class = (GObjectClass *)cache_class;
-
- gobject_class->finalize = webkit_soup_cache_finalize;
- gobject_class->constructed = webkit_soup_cache_constructed;
- gobject_class->set_property = webkit_soup_cache_set_property;
- gobject_class->get_property = webkit_soup_cache_get_property;
-
- cache_class->get_cacheability = get_cacheability;
-
- g_object_class_install_property (gobject_class, PROP_CACHE_DIR,
- g_param_spec_string ("cache-dir",
- "Cache directory",
- "The directory to store the cache files",
- NULL,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
- g_object_class_install_property (gobject_class, PROP_CACHE_TYPE,
- g_param_spec_enum ("cache-type",
- "Cache type",
- "Whether the cache is private or shared",
- WEBKIT_SOUP_CACHE_TYPE_TYPE,
- WEBKIT_SOUP_CACHE_SINGLE_USER,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
-
- g_type_class_add_private (cache_class, sizeof (WebKitSoupCachePrivate));
-}
-
-/**
- * webkit_soup_cache_new:
- * @cache_dir: the directory to store the cached data, or %NULL to use the default one
- * @cache_type: the #WebKitSoupCacheType of the cache
- *
- * Creates a new #WebKitSoupCache.
- *
- * Returns: a new #WebKitSoupCache
- *
- * Since: 2.28
- **/
-WebKitSoupCache *
-webkit_soup_cache_new (const char *cache_dir, WebKitSoupCacheType cache_type)
-{
- return g_object_new (WEBKIT_TYPE_SOUP_CACHE,
- "cache-dir", cache_dir,
- "cache-type", cache_type,
- NULL);
-}
-
-/**
- * webkit_soup_cache_has_response:
- * @cache: a #WebKitSoupCache
- * @msg: a #SoupMessage
- *
- * This function calculates whether the @cache object has a proper
- * response for the request @msg given the flags both in the request
- * and the cached reply and the time ellapsed since it was cached.
- *
- * Returns: whether or not the @cache has a valid response for @msg
- **/
-WebKitSoupCacheResponse
-webkit_soup_cache_has_response (WebKitSoupCache *cache, SoupMessage *msg)
-{
- char *key;
- WebKitSoupCacheEntry *entry;
- const char *cache_control;
- gpointer value;
- gboolean must_revalidate;
- int max_age, max_stale, min_fresh;
- GList *lru_item, *item;
-
- key = soup_message_get_cache_key (msg);
- entry = g_hash_table_lookup (cache->priv->cache, key);
- g_free (key);
-
- /* 1. The presented Request-URI and that of stored response
- * match
- */
- if (!entry)
- return WEBKIT_SOUP_CACHE_RESPONSE_STALE;
-
- /* Increase hit count. Take sorting into account */
- entry->hits++;
- lru_item = g_list_find (cache->priv->lru_start, entry);
- item = lru_item;
- while (item->next && lru_compare_func (item->data, item->next->data) > 0)
- item = g_list_next (item);
-
- if (item != lru_item) {
- cache->priv->lru_start = g_list_remove_link (cache->priv->lru_start, lru_item);
- item = g_list_insert_sorted (item, lru_item->data, lru_compare_func);
- g_list_free (lru_item);
- }
-
- if (entry->dirty || entry->being_validated)
- return WEBKIT_SOUP_CACHE_RESPONSE_STALE;
-
- /* 2. The request method associated with the stored response
- * allows it to be used for the presented request
- */
-
- /* In practice this means we only return our resource for GET,
- * cacheability for other methods is a TODO in the RFC
- * (TODO: although we could return the headers for HEAD
- * probably).
- */
- if (msg->method != SOUP_METHOD_GET)
- return WEBKIT_SOUP_CACHE_RESPONSE_STALE;
-
- /* 3. Selecting request-headers nominated by the stored
- * response (if any) match those presented.
- */
-
- /* TODO */
-
- /* 4. The request is a conditional request issued by the client.
- */
- if (soup_message_headers_get (msg->request_headers, "If-Modified-Since") ||
- soup_message_headers_get (msg->request_headers, "If-None-Match"))
- return WEBKIT_SOUP_CACHE_RESPONSE_STALE;
-
- /* 5. The presented request and stored response are free from
- * directives that would prevent its use.
- */
-
- must_revalidate = FALSE;
- max_age = max_stale = min_fresh = -1;
-
- cache_control = soup_message_headers_get (msg->request_headers, "Cache-Control");
- if (cache_control) {
- GHashTable *hash = soup_header_parse_param_list (cache_control);
-
- if (g_hash_table_lookup_extended (hash, "no-store", NULL, NULL)) {
- soup_header_free_param_list (hash);
- return WEBKIT_SOUP_CACHE_RESPONSE_STALE;
- }
-
- if (g_hash_table_lookup_extended (hash, "no-cache", NULL, NULL)) {
- entry->must_revalidate = TRUE;
- }
-
- if (g_hash_table_lookup_extended (hash, "max-age", NULL, &value)) {
- max_age = (int)MIN (g_ascii_strtoll (value, NULL, 10), G_MAXINT32);
- }
-
- /* max-stale can have no value set, we need to use _extended */
- if (g_hash_table_lookup_extended (hash, "max-stale", NULL, &value)) {
- if (value)
- max_stale = (int)MIN (g_ascii_strtoll (value, NULL, 10), G_MAXINT32);
- else
- max_stale = G_MAXINT32;
- }
-
- value = g_hash_table_lookup (hash, "min-fresh");
- if (value)
- min_fresh = (int)MIN (g_ascii_strtoll (value, NULL, 10), G_MAXINT32);
-
- soup_header_free_param_list (hash);
-
- if (max_age != -1) {
- guint current_age = webkit_soup_cache_entry_get_current_age (entry);
-
- /* If we are over max-age and max-stale is not
- set, do not use the value from the cache
- without validation */
- if ((guint) max_age <= current_age && max_stale == -1)
- return WEBKIT_SOUP_CACHE_RESPONSE_NEEDS_VALIDATION;
- }
- }
-
- /* 6. The stored response is either: fresh, allowed to be
- * served stale or succesfully validated
- */
- /* TODO consider also proxy-revalidate & s-maxage */
- if (entry->must_revalidate)
- return WEBKIT_SOUP_CACHE_RESPONSE_NEEDS_VALIDATION;
-
- if (!webkit_soup_cache_entry_is_fresh_enough (entry, min_fresh)) {
- /* Not fresh, can it be served stale? */
- if (max_stale != -1) {
- /* G_MAXINT32 means we accept any staleness */
- if (max_stale == G_MAXINT32)
- return WEBKIT_SOUP_CACHE_RESPONSE_FRESH;
-
- if ((webkit_soup_cache_entry_get_current_age (entry) - entry->freshness_lifetime) <= (guint) max_stale)
- return WEBKIT_SOUP_CACHE_RESPONSE_FRESH;
- }
-
- return WEBKIT_SOUP_CACHE_RESPONSE_NEEDS_VALIDATION;
- }
-
- return WEBKIT_SOUP_CACHE_RESPONSE_FRESH;
-}
-
-/**
- * webkit_soup_cache_get_cacheability:
- * @cache: a #WebKitSoupCache
- * @msg: a #SoupMessage
- *
- * Calculates whether the @msg can be cached or not.
- *
- * Returns: a #WebKitSoupCacheability value indicating whether the @msg can be cached or not.
- **/
-WebKitSoupCacheability
-webkit_soup_cache_get_cacheability (WebKitSoupCache *cache, SoupMessage *msg)
-{
- g_return_val_if_fail (WEBKIT_IS_SOUP_CACHE (cache), WEBKIT_SOUP_CACHE_UNCACHEABLE);
- g_return_val_if_fail (SOUP_IS_MESSAGE (msg), WEBKIT_SOUP_CACHE_UNCACHEABLE);
-
- return WEBKIT_SOUP_CACHE_GET_CLASS (cache)->get_cacheability (cache, msg);
-}
-
-static gboolean
-force_flush_timeout (gpointer data)
-{
- gboolean *forced = (gboolean *)data;
- *forced = TRUE;
-
- return FALSE;
-}
-
-/**
- * webkit_soup_cache_flush:
- * @cache: a #WebKitSoupCache
- * @session: the #SoupSession associated with the @cache
- *
- * This function will force all pending writes in the @cache to be
- * committed to disk. For doing so it will iterate the #GMainContext
- * associated with the @session (which can be the default one) as long
- * as needed.
- **/
-void
-webkit_soup_cache_flush (WebKitSoupCache *cache)
-{
- GMainContext *async_context;
- SoupSession *session;
- guint timeout_id;
- gboolean forced = FALSE;
-
- g_return_if_fail (WEBKIT_IS_SOUP_CACHE (cache));
-
- session = cache->priv->session;
- g_return_if_fail (SOUP_IS_SESSION (session));
- async_context = soup_session_get_async_context (session);
-
- /* We give cache 10 secs to finish */
- timeout_id = g_timeout_add (10000, force_flush_timeout, &forced);
-
- while (!forced && cache->priv->n_pending > 0)
- g_main_context_iteration (async_context, FALSE);
-
- if (!forced)
- g_source_remove (timeout_id);
- else
- g_warning ("Cache flush finished despite %d pending requests", cache->priv->n_pending);
-}
-
-static void
-clear_cache_item (gpointer data,
- gpointer user_data)
-{
- WebKitSoupCache *cache = (WebKitSoupCache *) user_data;
- WebKitSoupCacheEntry *entry = (WebKitSoupCacheEntry *) data;
-
- if (webkit_soup_cache_entry_remove (cache, entry))
- webkit_soup_cache_entry_free (entry, TRUE);
-}
-
-/**
- * webkit_soup_cache_clear:
- * @cache: a #WebKitSoupCache
- *
- * Will remove all entries in the @cache plus all the cache files
- * associated with them.
- **/
-void
-webkit_soup_cache_clear (WebKitSoupCache *cache)
-{
- GHashTable *hash;
- GList *entries;
-
- g_return_if_fail (WEBKIT_IS_SOUP_CACHE (cache));
-
- hash = cache->priv->cache;
- g_return_if_fail (hash);
-
- // Cannot use g_hash_table_foreach as callbacks must not modify the hash table
- entries = g_hash_table_get_values (hash);
- g_list_foreach (entries, clear_cache_item, cache);
- g_list_free (entries);
-}
-
-SoupMessage *
-webkit_soup_cache_generate_conditional_request (WebKitSoupCache *cache, SoupMessage *original)
-{
- SoupMessage *msg;
- SoupURI *uri;
- WebKitSoupCacheEntry *entry;
- char *key;
- const char *value;
-
- g_return_val_if_fail (WEBKIT_IS_SOUP_CACHE (cache), NULL);
- g_return_val_if_fail (SOUP_IS_MESSAGE (original), NULL);
-
- /* First copy the data we need from the original message */
- uri = soup_message_get_uri (original);
- msg = soup_message_new_from_uri (original->method, uri);
-
- soup_message_headers_foreach (original->request_headers,
- (SoupMessageHeadersForeachFunc)copy_headers,
- msg->request_headers);
-
- /* Now add the validator entries in the header from the cached
- data */
- key = soup_message_get_cache_key (original);
- entry = g_hash_table_lookup (cache->priv->cache, key);
- g_free (key);
-
- g_return_val_if_fail (entry, NULL);
-
- entry->being_validated = TRUE;
-
- value = soup_message_headers_get (entry->headers, "Last-Modified");
- if (value)
- soup_message_headers_append (msg->request_headers,
- "If-Modified-Since",
- value);
- value = soup_message_headers_get (entry->headers, "ETag");
- if (value)
- soup_message_headers_append (msg->request_headers,
- "If-None-Match",
- value);
- return msg;
-}
-
-#define WEBKIT_SOUP_CACHE_FILE "soup.cache"
-
-#define WEBKIT_SOUP_CACHE_HEADERS_FORMAT "{ss}"
-#define WEBKIT_SOUP_CACHE_PHEADERS_FORMAT "(ssbuuuuua" WEBKIT_SOUP_CACHE_HEADERS_FORMAT ")"
-#define WEBKIT_SOUP_CACHE_ENTRIES_FORMAT "a" WEBKIT_SOUP_CACHE_PHEADERS_FORMAT
-
-/* Basically the same format than above except that some strings are
- prepended with &. This way the GVariant returns a pointer to the
- data instead of duplicating the string */
-#define WEBKIT_SOUP_CACHE_DECODE_HEADERS_FORMAT "{&s&s}"
-
-static void
-pack_entry (gpointer data,
- gpointer user_data)
-{
- WebKitSoupCacheEntry *entry = (WebKitSoupCacheEntry *) data;
- SoupMessageHeadersIter iter;
- const gchar *header_key, *header_value;
- GVariantBuilder *headers_builder;
- GVariantBuilder *entries_builder = (GVariantBuilder *)user_data;
-
- /* Do not store non-consolidated entries */
- if (entry->dirty || entry->writing || !entry->key)
- return;
-
- /* Pack headers */
- headers_builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
- soup_message_headers_iter_init (&iter, entry->headers);
- while (soup_message_headers_iter_next (&iter, &header_key, &header_value)) {
- if (g_utf8_validate (header_value, -1, NULL))
- g_variant_builder_add (headers_builder, WEBKIT_SOUP_CACHE_HEADERS_FORMAT,
- header_key, header_value);
- }
-
- /* Entry data */
- g_variant_builder_add (entries_builder, WEBKIT_SOUP_CACHE_PHEADERS_FORMAT,
- entry->key, entry->filename, entry->must_revalidate,
- entry->freshness_lifetime, entry->corrected_initial_age,
- entry->response_time, entry->hits, entry->length, headers_builder);
-
- g_variant_builder_unref (headers_builder);
-}
-
-void
-webkit_soup_cache_dump (WebKitSoupCache *cache)
-{
- WebKitSoupCachePrivate *priv = WEBKIT_SOUP_CACHE_GET_PRIVATE (cache);
- gchar *filename;
- GVariantBuilder *entries_builder;
- GVariant *cache_variant;
-
- if (!g_list_length (cache->priv->lru_start))
- return;
-
- /* Create the builder and iterate over all entries */
- entries_builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
- g_list_foreach (cache->priv->lru_start, pack_entry, entries_builder);
-
- /* Serialize and dump */
- cache_variant = g_variant_new (WEBKIT_SOUP_CACHE_ENTRIES_FORMAT, entries_builder);
- g_variant_builder_unref (entries_builder);
-
- filename = g_build_filename (priv->cache_dir, WEBKIT_SOUP_CACHE_FILE, NULL);
- g_file_set_contents (filename, (const gchar *)g_variant_get_data (cache_variant),
- g_variant_get_size (cache_variant), NULL);
- g_free (filename);
- g_variant_unref (cache_variant);
-}
-
-void
-webkit_soup_cache_load (WebKitSoupCache *cache)
-{
- gchar *filename = NULL, *contents = NULL;
- GVariant *cache_variant;
- GVariantIter *entries_iter, *headers_iter;
- GVariantType *variant_format;
- gsize length;
- WebKitSoupCacheEntry *entry;
- WebKitSoupCachePrivate *priv = cache->priv;
-
- filename = g_build_filename (priv->cache_dir, WEBKIT_SOUP_CACHE_FILE, NULL);
- if (!g_file_get_contents (filename, &contents, &length, NULL)) {
- g_free (filename);
- g_free (contents);
- return;
- }
- g_free (filename);
-
- variant_format = g_variant_type_new (WEBKIT_SOUP_CACHE_ENTRIES_FORMAT);
- cache_variant = g_variant_new_from_data (variant_format, (const gchar *)contents, length, FALSE, g_free, contents);
- g_variant_type_free (variant_format);
-
- g_variant_get (cache_variant, WEBKIT_SOUP_CACHE_ENTRIES_FORMAT, &entries_iter);
- entry = g_slice_new0 (WebKitSoupCacheEntry);
-
- while (g_variant_iter_loop (entries_iter, WEBKIT_SOUP_CACHE_PHEADERS_FORMAT,
- &entry->key, &entry->filename, &entry->must_revalidate,
- &entry->freshness_lifetime, &entry->corrected_initial_age,
- &entry->response_time, &entry->hits, &entry->length,
- &headers_iter)) {
- const gchar *header_key, *header_value;
-
- /* SoupMessage Headers */
- entry->headers = soup_message_headers_new (SOUP_MESSAGE_HEADERS_RESPONSE);
- while (g_variant_iter_loop (headers_iter, WEBKIT_SOUP_CACHE_DECODE_HEADERS_FORMAT, &header_key, &header_value))
- soup_message_headers_append (entry->headers, header_key, header_value);
-
- /* Insert in cache */
- if (!webkit_soup_cache_entry_insert_by_key (cache, (const gchar *)entry->key, entry, FALSE))
- webkit_soup_cache_entry_free (entry, TRUE);
-
- /* New entry for the next iteration. This creates an
- extra object the last iteration but it's worth it
- as we save several if's */
- entry = g_slice_new0 (WebKitSoupCacheEntry);
- }
- /* Remove last created entry */
- g_slice_free (WebKitSoupCacheEntry, entry);
-
- /* Sort LRU (shouldn't be needed). First reverse as elements
- * are always prepended when inserting
- */
- cache->priv->lru_start = g_list_reverse (cache->priv->lru_start);
- cache->priv->lru_start = g_list_sort (cache->priv->lru_start, lru_compare_func);
-
- /* frees */
- g_variant_iter_free (entries_iter);
- g_variant_unref (cache_variant);
-}
-
-void
-webkit_soup_cache_set_max_size (WebKitSoupCache *cache,
- guint max_size)
-{
- cache->priv->max_size = max_size;
- cache->priv->max_entry_data_size = cache->priv->max_size / MAX_ENTRY_DATA_PERCENTAGE;
-}
-
-guint
-webkit_soup_cache_get_max_size (WebKitSoupCache *cache)
-{
- return cache->priv->max_size;
-}
diff --git a/Source/WebCore/platform/network/soup/cache/webkit/soup-cache.h b/Source/WebCore/platform/network/soup/cache/webkit/soup-cache.h
deleted file mode 100644
index a926f98..0000000
--- a/Source/WebCore/platform/network/soup/cache/webkit/soup-cache.h
+++ /dev/null
@@ -1,106 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * soup-cache.h:
- *
- * Copyright (C) 2009, 2010 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
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB. If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- */
-
-#ifndef WEBKIT_SOUP_CACHE_H
-#define WEBKIT_SOUP_CACHE_H 1
-
-#ifdef G_OS_WIN32
- #ifdef BUILDING_WEBKIT
- #define WEBKIT_API __declspec(dllexport)
- #else
- #define WEBKIT_API __declspec(dllimport)
- #endif
- #define WEBKIT_OBSOLETE_API WEBKIT_API
-#else
- #define WEBKIT_API __attribute__((visibility("default")))
- #define WEBKIT_OBSOLETE_API WEBKIT_API __attribute__((deprecated))
-#endif
-
-#include <libsoup/soup-types.h>
-#include <gio/gio.h>
-
-G_BEGIN_DECLS
-
-#define WEBKIT_TYPE_SOUP_CACHE (webkit_soup_cache_get_type ())
-#define WEBKIT_SOUP_CACHE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), WEBKIT_TYPE_SOUP_CACHE, WebKitSoupCache))
-#define WEBKIT_SOUP_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), WEBKIT_TYPE_SOUP_CACHE, WebKitSoupCacheClass))
-#define WEBKIT_IS_SOUP_CACHE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), WEBKIT_TYPE_SOUP_CACHE))
-#define WEBKIT_IS_SOUP_CACHE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), WEBKIT_TYPE_SOUP_CACHE))
-#define WEBKIT_SOUP_CACHE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), WEBKIT_TYPE_SOUP_CACHE, WebKitSoupCacheClass))
-
-typedef struct _WebKitSoupCache WebKitSoupCache;
-typedef struct _WebKitSoupCachePrivate WebKitSoupCachePrivate;
-
-typedef enum {
- WEBKIT_SOUP_CACHE_CACHEABLE = (1 << 0),
- WEBKIT_SOUP_CACHE_UNCACHEABLE = (1 << 1),
- WEBKIT_SOUP_CACHE_INVALIDATES = (1 << 2),
- WEBKIT_SOUP_CACHE_VALIDATES = (1 << 3)
-} WebKitSoupCacheability;
-
-typedef enum {
- WEBKIT_SOUP_CACHE_RESPONSE_FRESH,
- WEBKIT_SOUP_CACHE_RESPONSE_NEEDS_VALIDATION,
- WEBKIT_SOUP_CACHE_RESPONSE_STALE
-} WebKitSoupCacheResponse;
-
-typedef enum {
- WEBKIT_SOUP_CACHE_SINGLE_USER,
- WEBKIT_SOUP_CACHE_SHARED
-} WebKitSoupCacheType;
-
-struct _WebKitSoupCache {
- GObject parent_instance;
-
- WebKitSoupCachePrivate *priv;
-};
-
-typedef struct {
- GObjectClass parent_class;
-
- /* methods */
- WebKitSoupCacheability (*get_cacheability)(WebKitSoupCache *cache, SoupMessage *msg);
-
- /* Padding for future expansion */
- void (*_libsoup_reserved1)(void);
- void (*_libsoup_reserved2)(void);
- void (*_libsoup_reserved3)(void);
-} WebKitSoupCacheClass;
-
-WEBKIT_API GType webkit_soup_cache_get_type (void);
-WEBKIT_API WebKitSoupCache *webkit_soup_cache_new (const char *cache_dir,
- WebKitSoupCacheType cache_type);
-WEBKIT_API void webkit_soup_cache_flush (WebKitSoupCache *cache);
-WEBKIT_API void webkit_soup_cache_clear (WebKitSoupCache *cache);
-
-WEBKIT_API void webkit_soup_cache_dump (WebKitSoupCache *cache);
-WEBKIT_API void webkit_soup_cache_load (WebKitSoupCache *cache);
-
-WEBKIT_API void webkit_soup_cache_set_max_size (WebKitSoupCache *cache,
- guint max_size);
-WEBKIT_API guint webkit_soup_cache_get_max_size (WebKitSoupCache *cache);
-
-G_END_DECLS
-
-
-#endif /* WEBKIT_SOUP_CACHE_H */
-
diff --git a/Source/WebCore/platform/network/win/DownloadBundleWin.cpp b/Source/WebCore/platform/network/win/DownloadBundleWin.cpp
new file mode 100644
index 0000000..f0f3027
--- /dev/null
+++ b/Source/WebCore/platform/network/win/DownloadBundleWin.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "DownloadBundle.h"
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <io.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+namespace DownloadBundle {
+
+static UInt32 magicNumber()
+{
+ return 0xDECAF4EA;
+}
+
+const String& fileExtension()
+{
+ DEFINE_STATIC_LOCAL(const String, extension, (".download"));
+ return extension;
+}
+
+bool appendResumeData(CFDataRef resumeData, const String& bundlePath)
+{
+ if (!resumeData) {
+ LOG_ERROR("Invalid resume data to write to bundle path");
+ return false;
+ }
+ if (bundlePath.isEmpty()) {
+ LOG_ERROR("Cannot write resume data to empty download bundle path");
+ return false;
+ }
+
+ String nullifiedPath = bundlePath;
+ FILE* bundle = 0;
+ if (_wfopen_s(&bundle, nullifiedPath.charactersWithNullTermination(), TEXT("ab")) || !bundle) {
+ LOG_ERROR("Failed to open file %s to append resume data", bundlePath.ascii().data());
+ return false;
+ }
+
+ bool result = false;
+
+ const UInt8* resumeBytes = CFDataGetBytePtr(resumeData);
+ ASSERT(resumeBytes);
+ if (!resumeBytes)
+ goto exit;
+
+ CFIndex resumeLength = CFDataGetLength(resumeData);
+ ASSERT(resumeLength > 0);
+ if (resumeLength < 1)
+ goto exit;
+
+ if (fwrite(resumeBytes, 1, resumeLength, bundle) != resumeLength) {
+ LOG_ERROR("Failed to write resume data to the bundle - errno(%i)", errno);
+ goto exit;
+ }
+
+ if (fwrite(&resumeLength, 4, 1, bundle) != 1) {
+ LOG_ERROR("Failed to write footer length to the bundle - errno(%i)", errno);
+ goto exit;
+ }
+
+ const UInt32& magic = magicNumber();
+ if (fwrite(&magic, 4, 1, bundle) != 1) {
+ LOG_ERROR("Failed to write footer magic number to the bundle - errno(%i)", errno);
+ goto exit;
+ }
+
+ result = true;
+exit:
+ fclose(bundle);
+ return result;
+}
+
+CFDataRef extractResumeData(const String& bundlePath)
+{
+ if (bundlePath.isEmpty()) {
+ LOG_ERROR("Cannot create resume data from empty download bundle path");
+ return 0;
+ }
+
+ // Open a handle to the bundle file
+ String nullifiedPath = bundlePath;
+ FILE* bundle = 0;
+ if (_wfopen_s(&bundle, nullifiedPath.charactersWithNullTermination(), TEXT("r+b")) || !bundle) {
+ LOG_ERROR("Failed to open file %s to get resume data", bundlePath.ascii().data());
+ return 0;
+ }
+
+ CFDataRef result = 0;
+ Vector<UInt8> footerBuffer;
+
+ // Stat the file to get its size
+ struct _stat64 fileStat;
+ if (_fstat64(_fileno(bundle), &fileStat))
+ goto exit;
+
+ // Check for the bundle magic number at the end of the file
+ fpos_t footerMagicNumberPosition = fileStat.st_size - 4;
+ ASSERT(footerMagicNumberPosition >= 0);
+ if (footerMagicNumberPosition < 0)
+ goto exit;
+ if (fsetpos(bundle, &footerMagicNumberPosition))
+ goto exit;
+
+ UInt32 footerMagicNumber = 0;
+ if (fread(&footerMagicNumber, 4, 1, bundle) != 1) {
+ LOG_ERROR("Failed to read footer magic number from the bundle - errno(%i)", errno);
+ goto exit;
+ }
+
+ if (footerMagicNumber != magicNumber()) {
+ LOG_ERROR("Footer's magic number does not match 0x%X - errno(%i)", magicNumber(), errno);
+ goto exit;
+ }
+
+ // Now we're *reasonably* sure this is a .download bundle we actually wrote.
+ // Get the length of the resume data
+ fpos_t footerLengthPosition = fileStat.st_size - 8;
+ ASSERT(footerLengthPosition >= 0);
+ if (footerLengthPosition < 0)
+ goto exit;
+
+ if (fsetpos(bundle, &footerLengthPosition))
+ goto exit;
+
+ UInt32 footerLength = 0;
+ if (fread(&footerLength, 4, 1, bundle) != 1) {
+ LOG_ERROR("Failed to read ResumeData length from the bundle - errno(%i)", errno);
+ goto exit;
+ }
+
+ // Make sure theres enough bytes to read in for the resume data, and perform the read
+ fpos_t footerStartPosition = fileStat.st_size - 8 - footerLength;
+ ASSERT(footerStartPosition >= 0);
+ if (footerStartPosition < 0)
+ goto exit;
+ if (fsetpos(bundle, &footerStartPosition))
+ goto exit;
+
+ footerBuffer.resize(footerLength);
+ if (fread(footerBuffer.data(), 1, footerLength, bundle) != footerLength) {
+ LOG_ERROR("Failed to read ResumeData from the bundle - errno(%i)", errno);
+ goto exit;
+ }
+
+ // CFURLDownload will seek to the appropriate place in the file (before our footer) and start overwriting from there
+ // However, say we were within a few hundred bytes of the end of a download when it was paused -
+ // The additional footer extended the length of the file beyond its final length, and there will be junk data leftover
+ // at the end. Therefore, now that we've retrieved the footer data, we need to truncate it.
+ if (errno_t resizeError = _chsize_s(_fileno(bundle), footerStartPosition)) {
+ LOG_ERROR("Failed to truncate the resume footer off the end of the file - errno(%i)", resizeError);
+ goto exit;
+ }
+
+ // Finally, make the resume data. Now, it is possible by some twist of fate the bundle magic number
+ // was naturally at the end of the file and its not actually a valid bundle. That, or someone engineered
+ // it that way to try to attack us. In that cause, this CFData will successfully create but when we
+ // actually try to start the CFURLDownload using this bogus data, it will fail and we will handle that gracefully
+ result = CFDataCreate(0, footerBuffer.data(), footerLength);
+exit:
+ fclose(bundle);
+ return result;
+}
+
+} // namespace DownloadBundle
+
+} // namespace WebCore