Reviewed by Maciej.
Implement the callback responsible for handling HTTP headers. This
callback gets called for every header.
We will add these headers to our ResourceResponse and on the 'end-of-header'
indicator we will update the ResourceResponse and dispatch it.
This patch adds various set methods to ResourceResponse. This improves
the readability of the headerCallback and avoids storing a CURL handle inside
the ResourceResponse which would be needed to implement ResourceResponse::doUpdateResourceResponse
Add a destructor for ResourceHandleManager which would free the resources and remove
a unused variable.
* platform/network/ResourceHandleInternal.h:
(WebCore::ResourceHandleInternal::ResourceHandleInternal):
* platform/network/ResourceResponse.cpp:
(WebCore::ResourceResponse::setUrl):
(WebCore::ResourceResponse::setMimeType):
(WebCore::ResourceResponse::setExpectedContentLength):
(WebCore::ResourceResponse::setTextEncodingName):
(WebCore::ResourceResponse::setSuggestedFilename):
* platform/network/ResourceResponse.h:
* platform/network/curl/ResourceHandleCurl.cpp:
(WebCore::ResourceHandleInternal::~ResourceHandleInternal):
* platform/network/curl/ResourceHandleManager.cpp:
(WebCore::ResourceHandleManager::~ResourceHandleManager):
(WebCore::ResourceHandleManager::sharedInstance):
(WebCore::headerCallback):
* platform/network/curl/ResourceHandleManager.h:
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@24372
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2007-07-17 Holger Hans Peter Freyther <zecke@selfish.org>
+
+ Reviewed by Maciej.
+
+ Implement the callback responsible for handling HTTP headers. This
+ callback gets called for every header.
+ We will add these headers to our ResourceResponse and on the 'end-of-header'
+ indicator we will update the ResourceResponse and dispatch it.
+
+ This patch adds various set methods to ResourceResponse. This improves
+ the readability of the headerCallback and avoids storing a CURL handle inside
+ the ResourceResponse which would be needed to implement ResourceResponse::doUpdateResourceResponse
+
+ Add a destructor for ResourceHandleManager which would free the resources and remove
+ a unused variable.
+
+ * platform/network/ResourceHandleInternal.h:
+ (WebCore::ResourceHandleInternal::ResourceHandleInternal):
+ * platform/network/ResourceResponse.cpp:
+ (WebCore::ResourceResponse::setUrl):
+ (WebCore::ResourceResponse::setMimeType):
+ (WebCore::ResourceResponse::setExpectedContentLength):
+ (WebCore::ResourceResponse::setTextEncodingName):
+ (WebCore::ResourceResponse::setSuggestedFilename):
+ * platform/network/ResourceResponse.h:
+ * platform/network/curl/ResourceHandleCurl.cpp:
+ (WebCore::ResourceHandleInternal::~ResourceHandleInternal):
+ * platform/network/curl/ResourceHandleManager.cpp:
+ (WebCore::ResourceHandleManager::~ResourceHandleManager):
+ (WebCore::ResourceHandleManager::sharedInstance):
+ (WebCore::headerCallback):
+ * platform/network/curl/ResourceHandleManager.h:
+
2007-07-17 Sam Weinig <sam@webkit.org>
Reviewed by Adam Roben.
, m_url(0)
, m_fileName(0)
, m_customHeaders(0)
- , m_customPostHeader(0)
#endif
#if PLATFORM(QT)
, m_job(0)
char* m_url;
char* m_fileName;
struct curl_slist* m_customHeaders;
- struct curl_slist* m_customPostHeader;
Vector<char> m_postBytes;
+ ResourceResponse m_response;
#endif
#if PLATFORM(QT)
QWebNetworkJob *m_job;
return m_url;
}
+void ResourceResponse::setUrl(const KURL& url)
+{
+ updateResourceResponse();
+ m_isNull = false;
+
+ m_url = url;
+}
+
const String& ResourceResponse::mimeType() const
{
updateResourceResponse();
return m_mimeType;
}
+void ResourceResponse::setMimeType(const String& mimeType)
+{
+ updateResourceResponse();
+ m_isNull = false;
+
+ m_mimeType = mimeType;
+}
+
long long ResourceResponse::expectedContentLength() const
{
updateResourceResponse();
return m_expectedContentLength;
}
+void ResourceResponse::setExpectedContentLength(long long expectedContentLength)
+{
+ updateResourceResponse();
+ m_isNull = false;
+
+ m_expectedContentLength = expectedContentLength;
+}
+
const String& ResourceResponse::textEncodingName() const
{
updateResourceResponse();
return m_textEncodingName;
}
+void ResourceResponse::setTextEncodingName(const String& encodingName)
+{
+ updateResourceResponse();
+ m_isNull = false;
+
+ m_textEncodingName = encodingName;
+}
+
// FIXME should compute this on the fly
const String& ResourceResponse::suggestedFilename() const
{
return m_suggestedFilename;
}
+void ResourceResponse::setSuggestedFilename(const String& suggestedName)
+{
+ updateResourceResponse();
+ m_isNull = false;
+
+ m_suggestedFilename = suggestedName;
+}
+
int ResourceResponse::httpStatusCode() const
{
updateResourceResponse();
bool isHTTP() const;
const KURL& url() const;
+ void setUrl(const KURL& url);
+
const String& mimeType() const;
+ void setMimeType(const String& mimeType);
+
long long expectedContentLength() const;
+ void setExpectedContentLength(long long expectedContentLength);
+
const String& textEncodingName() const;
+ void setTextEncodingName(const String& name);
// FIXME should compute this on the fly
const String& suggestedFilename() const;
+ void setSuggestedFilename(const String&);
int httpStatusCode() const;
void setHTTPStatusCode(int);
free(m_fileName);
if (m_customHeaders)
curl_slist_free_all(m_customHeaders);
- if (m_customPostHeader)
- curl_slist_free_all(m_customPostHeader);
}
ResourceHandle::~ResourceHandle()
/*
* Copyright (C) 2004, 2006 Apple Computer, Inc. All rights reserved.
* Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * Copyright (C) 2007 Alp Toker <alp.toker@collabora.co.uk>
+ * Copyright (C) 2007 Holger Hans Peter Freyther
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
#include "NotImplemented.h"
#include "ResourceHandle.h"
#include "ResourceHandleInternal.h"
+#include "HTTPParsers.h"
+
#include <wtf/Vector.h>
namespace WebCore {
curl_share_setopt(m_curlShareHandle, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
}
+ResourceHandleManager::~ResourceHandleManager()
+{
+ curl_multi_cleanup(m_curlMultiHandle);
+ curl_share_cleanup(m_curlShareHandle);
+ if (m_cookieJarFileName)
+ free(m_cookieJarFileName);
+}
+
void ResourceHandleManager::setCookieJarFileName(const char* cookieJarFileName)
{
m_cookieJarFileName = strdup(cookieJarFileName);
ResourceHandleManager* ResourceHandleManager::sharedInstance()
{
- static ResourceHandleManager* sharedInstance;
+ static ResourceHandleManager* sharedInstance = 0;
if (!sharedInstance)
sharedInstance = new ResourceHandleManager();
return sharedInstance;
return totalSize;
}
-// This is being called for each HTTP header in the response so it'll be called
-// multiple times for a given response.
+/*
+ * This is being called for each HTTP header in the response. This includes '\r\n'
+ * for the last line of the header.
+ *
+ * We will add each HTTP Header to the ResourceResponse and on the termination
+ * of the header (\r\n) we will parse Content-Type and Content-Disposition and
+ * update the ResourceResponse and then send it away.
+ *
+ */
static size_t headerCallback(char* ptr, size_t size, size_t nmemb, void* data)
{
- int totalSize = size * nmemb;
+ ResourceHandle* job = static_cast<ResourceHandle*>(data);
+ ResourceHandleInternal* d = job->getInternal();
+
+ unsigned int totalSize = size * nmemb;
+ ResourceHandleClient* client = d->client();
+ if (!client) {
+ return totalSize;
+ }
+
+
+ String header(static_cast<const char*>(ptr), totalSize);
+
+ /*
+ * a) We can finish and send the ResourceResponse
+ * b) We will add the current header to the HTTPHeaderMap of the ResourceResponse
+ */
+ if (header == String("\r\n")) {
+ CURL* h = d->m_handle;
+ CURLcode err;
+
+ double contentLength = 0;
+ err = curl_easy_getinfo(h, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &contentLength);
+ d->m_response.setExpectedContentLength(static_cast<long long int>(contentLength));
+
+ const char* hdr;
+ err = curl_easy_getinfo(h, CURLINFO_EFFECTIVE_URL, &hdr);
+ d->m_response.setUrl(KURL(hdr));
+
+ long httpCode = 0;
+ err = curl_easy_getinfo(h, CURLINFO_RESPONSE_CODE, &httpCode);
+ d->m_response.setHTTPStatusCode(httpCode);
+
+ d->m_response.setMimeType(extractMIMETypeFromMediaType(d->m_response.httpHeaderField("Content-Type")));
+ d->m_response.setTextEncodingName(extractCharsetFromMediaType(d->m_response.httpHeaderField("Content-Type")));
+ d->m_response.setSuggestedFilename(filenameFromHTTPContentDisposition(d->m_response.httpHeaderField("Content-Disposition")));
+
+ client->didReceiveResponse(job, d->m_response);
+ } else {
+ int splitPos = header.find(":");
+ if (splitPos != -1)
+ d->m_response.setHTTPHeaderField(header.left(splitPos), header.substring(splitPos+1).stripWhiteSpace());
+ }
+
return totalSize;
}
private:
ResourceHandleManager();
+ ~ResourceHandleManager();
void downloadTimerCallback(Timer<ResourceHandleManager>*);
void removeFromCurl(ResourceHandle*);
bool removeScheduledJob(ResourceHandle*);
bool startScheduledJobs();
Timer<ResourceHandleManager> m_downloadTimer;
- CURLM* m_curlMultiHandle; // FIXME: never freed
- CURLSH* m_curlShareHandle; // FIXME: never freed
- char* m_cookieJarFileName; // FIXME: never freed
+ CURLM* m_curlMultiHandle;
+ CURLSH* m_curlShareHandle;
+ char* m_cookieJarFileName;
char m_curlErrorBuffer[CURL_ERROR_SIZE];
ResourceHandleList* m_resourceHandleListHead;
};