diff options
author | darin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-30 21:16:51 +0000 |
---|---|---|
committer | darin@chromium.org <darin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-30 21:16:51 +0000 |
commit | 35cb9e1d4ad928a981a305a8f1d1d805c65e0cd5 (patch) | |
tree | ff56ff6e26a5a926bfaeb080c6c5bea124c2a87a /webkit | |
parent | 335fb4f3221673af83ecae7414b666bfecf42e2b (diff) | |
download | chromium_src-35cb9e1d4ad928a981a305a8f1d1d805c65e0cd5.zip chromium_src-35cb9e1d4ad928a981a305a8f1d1d805c65e0cd5.tar.gz chromium_src-35cb9e1d4ad928a981a305a8f1d1d805c65e0cd5.tar.bz2 |
Start using WebURLLoader, et. al. from the WebKit API.
Moves our ResourceHandle to webkit/api/src/ResourceHandle.cpp
from webkit/glue/resource_handle_impl.cc. A portion of
resource_handle_impl.cc was moved into weburlloader_impl.{h,cc},
which now contains our implementation of WebURLLoader.
The annoying parts of this CL involve WebPluginImpl. I had to
convert it over to using WebURLLoader instead of ResourceHandle
so that MultipartResourceDelegate can be shared.
There is some complexity in WebURLRequest / WebURLResponse to
make it cheap to wrap a ResourceRequest / ResourceResponse. I
think this is worth it since there is a lot of conversion between
the two types.
BUG=10038
TEST=covered by existing tests
R=dglazkov
Review URL: http://codereview.chromium.org/113928
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@17290 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
33 files changed, 2726 insertions, 1301 deletions
diff --git a/webkit/api/public/WebHTTPBody.h b/webkit/api/public/WebHTTPBody.h index 1a4f49c..06d37fe 100644 --- a/webkit/api/public/WebHTTPBody.h +++ b/webkit/api/public/WebHTTPBody.h @@ -31,23 +31,62 @@ #ifndef WebHTTPBody_h #define WebHTTPBody_h -#error "This header file is still a work in progress; do not include!" - #include "WebData.h" +#include "WebNonCopyable.h" #include "WebString.h" -#include "WebVector.h" + +#if WEBKIT_IMPLEMENTATION +namespace WebCore { class FormData; } +namespace WTF { template <typename T> class PassRefPtr; } +#endif namespace WebKit { + class WebHTTPBodyPrivate; - struct WebHTTPBody { + class WebHTTPBody : public WebNonCopyable { + public: struct Element { enum { TypeData, TypeFile } type; WebData data; - WebString fileName; + WebString filePath; }; - WebVector<Element> elements; + + ~WebHTTPBody() { reset(); } + + WebHTTPBody() : m_private(0) { } + + bool isNull() const { return m_private == 0; } + + WEBKIT_API void initialize(); + WEBKIT_API void reset(); + + // Returns the number of elements comprising the http body. + WEBKIT_API size_t elementCount() const; + + // Sets the values of the element at the given index. Returns false if + // index is out of bounds. + WEBKIT_API bool elementAt(size_t index, Element&) const; + + // Append to the list of elements. + WEBKIT_API void appendData(const WebData&); + WEBKIT_API void appendFile(const WebString&); + + // Identifies a particular form submission instance. A value of 0 is + // used to indicate an unspecified identifier. + WEBKIT_API long long identifier() const; + WEBKIT_API void setIdentifier(long long); + +#if WEBKIT_IMPLEMENTATION + void rebind(WTF::PassRefPtr<WebCore::FormData>); + operator WTF::PassRefPtr<WebCore::FormData>() const; +#endif + + private: + void assign(WebHTTPBodyPrivate*); + WebHTTPBodyPrivate* m_private; }; + } // namespace WebKit #endif diff --git a/webkit/api/public/WebHTTPHeaderVisitor.h b/webkit/api/public/WebHTTPHeaderVisitor.h new file mode 100644 index 0000000..b61d3da --- /dev/null +++ b/webkit/api/public/WebHTTPHeaderVisitor.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER 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 WebHTTPHeaderVisitor_h +#define WebHTTPHeaderVisitor_h + +namespace WebKit { + class WebString; + + class WebHTTPHeaderVisitor { + public: + virtual void visitHeader(const WebString& name, const WebString& value) = 0; + }; + +} // namespace WebKit + +#endif diff --git a/webkit/api/public/WebKitClient.h b/webkit/api/public/WebKitClient.h index 5b136d5..87ff7b7e 100644 --- a/webkit/api/public/WebKitClient.h +++ b/webkit/api/public/WebKitClient.h @@ -42,6 +42,7 @@ namespace WebKit { class WebString; class WebThemeEngine; class WebURL; + class WebURLLoader; struct WebPluginInfo; template <typename T> class WebVector; @@ -81,6 +82,9 @@ namespace WebKit { // A suggestion to prefetch IP information for the given hostname. virtual void prefetchHostName(const WebString&) = 0; + // Returns a new WebURLLoader instance. + virtual WebURLLoader* createURLLoader() = 0; + // Plugins ------------------------------------------------------------- diff --git a/webkit/api/public/WebNonCopyable.h b/webkit/api/public/WebNonCopyable.h new file mode 100644 index 0000000..df4b482 --- /dev/null +++ b/webkit/api/public/WebNonCopyable.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER 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 WebNonCopyable_h +#define WebNonCopyable_h + +namespace WebKit { + + // A base class to extend from if you do not support copying. + class WebNonCopyable { + protected: + WebNonCopyable() { } + ~WebNonCopyable() { } + + private: + WebNonCopyable(const WebNonCopyable&); + WebNonCopyable& operator=(const WebNonCopyable&); + }; + +} // namespace WebKit + +#endif diff --git a/webkit/api/public/WebURLError.h b/webkit/api/public/WebURLError.h index 6332b5e..c4cfe46 100644 --- a/webkit/api/public/WebURLError.h +++ b/webkit/api/public/WebURLError.h @@ -31,8 +31,6 @@ #ifndef WebURLError_h #define WebURLError_h -#error "This header file is still a work in progress; do not include!" - #include "WebString.h" #include "WebURL.h" @@ -48,9 +46,10 @@ namespace WebKit { // string as it will just be passed via callbacks to the consumer. WebString domain; - // A numeric reason for the error. WebKit does not care about the - // value of this field as it will just be passed via callbacks to the - // consumer. + // A numeric error code detailing the reason for this error. A value + // of 0 means no error. WebKit does not interpret the meaning of other + // values and normally just forwards this error information back to the + // embedder (see for example WebFrameClient). int reason; // The url that failed to load. diff --git a/webkit/api/public/WebURLLoader.h b/webkit/api/public/WebURLLoader.h index 721fe60..8bc8a94 100644 --- a/webkit/api/public/WebURLLoader.h +++ b/webkit/api/public/WebURLLoader.h @@ -31,16 +31,14 @@ #ifndef WebURLLoader_h #define WebURLLoader_h -#error "This header file is still a work in progress; do not include!" - #include "WebCommon.h" namespace WebKit { - class WebCString; - class WebURLError; + class WebData; class WebURLLoaderClient; class WebURLRequest; class WebURLResponse; + struct WebURLError; class WebURLLoader { public: @@ -50,7 +48,7 @@ namespace WebKit { // caller upon completion. There is no mechanism to interrupt a // synchronous load!! virtual void loadSynchronously(const WebURLRequest&, - WebURLResponse&, WebURLError&, WebCString& data) = 0; + WebURLResponse&, WebURLError&, WebData& data) = 0; // Load the request asynchronously, sending notifications to the given // client. The client will receive no further notifications if the diff --git a/webkit/api/public/WebURLLoaderClient.h b/webkit/api/public/WebURLLoaderClient.h index 3a0a761..16ea87e 100644 --- a/webkit/api/public/WebURLLoaderClient.h +++ b/webkit/api/public/WebURLLoaderClient.h @@ -31,33 +31,35 @@ #ifndef WebURLLoaderClient_h #define WebURLLoaderClient_h -#error "This header file is still a work in progress; do not include!" - namespace WebKit { + class WebURLLoader; + class WebURLRequest; + class WebURLResponse; + struct WebURLError; class WebURLLoaderClient { public: // Called when following a redirect. |newRequest| contains the request // generated by the redirect. The client may modify |newRequest|. virtual void willSendRequest( - WebURLRequest& newRequest, const WebURLResponse& redirectResponse) = 0; + WebURLLoader*, WebURLRequest& newRequest, const WebURLResponse& redirectResponse) = 0; // Called to report upload progress. The bytes reported correspond to // the HTTP message body. virtual void didSendData( - unsigned long long bytesSent, unsigned long long totalBytesToBeSent) = 0; + WebURLLoader*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent) = 0; // Called when response headers are received. - virtual void didReceiveResponse(const WebURLResponse&) = 0; + virtual void didReceiveResponse(WebURLLoader*, const WebURLResponse&) = 0; // Called when a chunk of response data is received. - virtual void didReceiveData(const char* data, int dataLength, int totalDataLength) = 0; + virtual void didReceiveData(WebURLLoader*, const char* data, int dataLength, long long totalDataLength) = 0; // Called when the load completes successfully. - virtual void didFinishLoading() = 0; + virtual void didFinishLoading(WebURLLoader*) = 0; // Called when the load completes with an error. - virtual void didFail(const WebURLError&) = 0; + virtual void didFail(WebURLLoader*, const WebURLError&) = 0; }; } // namespace WebKit diff --git a/webkit/api/public/WebURLRequest.h b/webkit/api/public/WebURLRequest.h index c7b9bec..8399624 100644 --- a/webkit/api/public/WebURLRequest.h +++ b/webkit/api/public/WebURLRequest.h @@ -31,14 +31,17 @@ #ifndef WebURLRequest_h #define WebURLRequest_h -#error "This header file is still a work in progress; do not include!" - #include "WebCommon.h" #include "WebHTTPBody.h" +#if defined(WEBKIT_IMPLEMENTATION) +namespace WebCore { struct ResourceRequest; } +#endif + namespace WebKit { class WebCString; class WebHTTPBody; + class WebHTTPHeaderVisitor; class WebString; class WebURL; class WebURLRequestPrivate; @@ -66,58 +69,75 @@ namespace WebKit { WebURLRequest(const WebURLRequest& r) : m_private(0) { assign(r); } WebURLRequest& operator=(const WebURLRequest& r) { assign(r); return *this; } + explicit WebURLRequest(const WebURL& url) : m_private(0) + { + initialize(); + setURL(url); + } + WEBKIT_API void initialize(); WEBKIT_API void reset(); WEBKIT_API void assign(const WebURLRequest&); bool isNull() const { return m_private == 0; } - WEBKIT_API WebURL url() const = 0; - WEBKIT_API void setURL(const WebURL&) = 0; + WEBKIT_API WebURL url() const; + WEBKIT_API void setURL(const WebURL&); // Used to implement third-party cookie blocking. - WEBKIT_API WebURL firstPartyForCookies() const = 0; - WEBKIT_API void setFirstPartyForCookies(const WebURL&) = 0; + WEBKIT_API WebURL firstPartyForCookies() const; + WEBKIT_API void setFirstPartyForCookies(const WebURL&); + + WEBKIT_API CachePolicy cachePolicy() const; + WEBKIT_API void setCachePolicy(CachePolicy); - WEBKIT_API CachePolicy cachePolicy() const = 0; - WEBKIT_API void setCachePolicy(CachePolicy) = 0; + WEBKIT_API WebString httpMethod() const; + WEBKIT_API void setHTTPMethod(const WebString&); - WEBKIT_API WebString httpMethod() const = 0; - WEBKIT_API void setHTTPMethod(const WebString&) = 0; + WEBKIT_API WebString httpHeaderField(const WebString& name) const; + WEBKIT_API void setHTTPHeaderField(const WebString& name, const WebString& value); + WEBKIT_API void addHTTPHeaderField(const WebString& name, const WebString& value); + WEBKIT_API void clearHTTPHeaderField(const WebString& name); + WEBKIT_API void visitHTTPHeaderFields(WebHTTPHeaderVisitor*) const; - WEBKIT_API WebString httpHeaderField(const WebString& name) const = 0; - WEBKIT_API void setHTTPHeaderField(const WebString& name, const WebString& value) = 0; - WEBKIT_API void addHTTPHeaderField(const WebString& name, const WebString& value) = 0; - WEBKIT_API void clearHTTPHeaderField(const WebString& name) = 0; + WEBKIT_API const WebHTTPBody& httpBody() const; + WEBKIT_API void setHTTPBody(const WebHTTPBody&); - WEBKIT_API bool hasHTTPBody() const = 0; - WEBKIT_API void httpBody(WebHTTPBody&) const = 0; - WEBKIT_API void setHTTPBody(const WebHTTPBody&) = 0; - WEBKIT_API void appendToHTTPBody(const WebHTTPBody::Element&) = 0; - // Controls whether upload progress events are generated when a request // has a body. - WEBKIT_API bool reportUploadProgress() const = 0; - WEBKIT_API void setReportUploadProgress(bool) = 0; + WEBKIT_API bool reportUploadProgress() const; + WEBKIT_API void setReportUploadProgress(bool); - WEBKIT_API TargetType targetType() const = 0; - WEBKIT_API void setTargetType(const TargetType&) = 0; + WEBKIT_API TargetType targetType() const; + WEBKIT_API void setTargetType(TargetType); // A consumer controlled value intended to be used to identify the // requestor. - WEBKIT_API int requestorID() const = 0; - WEBKIT_API void setRequestorID(int) = 0; + WEBKIT_API int requestorID() const; + WEBKIT_API void setRequestorID(int); // A consumer controlled value intended to be used to identify the // process of the requestor. - WEBKIT_API int requestorProcessID() const = 0; - WEBKIT_API void setRequestorProcessID(int) = 0; + WEBKIT_API int requestorProcessID() const; + WEBKIT_API void setRequestorProcessID(int); + + // Allows the request to be matched up with its app cache context. + WEBKIT_API int appCacheContextID() const; + WEBKIT_API void setAppCacheContextID(int id); // A consumer controlled value intended to be used to record opaque // security info related to this request. // FIXME: This really doesn't belong here! - WEBKIT_API WebCString securityInfo() const = 0; - WEBKIT_API void setSecurityInfo(const WebCString&) = 0; + WEBKIT_API WebCString securityInfo() const; + WEBKIT_API void setSecurityInfo(const WebCString&); + +#if defined(WEBKIT_IMPLEMENTATION) + WebCore::ResourceRequest& toMutableResourceRequest(); + const WebCore::ResourceRequest& toResourceRequest() const; +#endif + + protected: + void assign(WebURLRequestPrivate*); private: WebURLRequestPrivate* m_private; diff --git a/webkit/api/public/WebURLResponse.h b/webkit/api/public/WebURLResponse.h index 30d2641..c26f213 100644 --- a/webkit/api/public/WebURLResponse.h +++ b/webkit/api/public/WebURLResponse.h @@ -31,12 +31,15 @@ #ifndef WebURLResponse_h #define WebURLResponse_h -#error "This header file is still a work in progress; do not include!" - #include "WebCommon.h" +#if defined(WEBKIT_IMPLEMENTATION) +namespace WebCore { class ResourceResponse; } +#endif + namespace WebKit { class WebCString; + class WebHTTPHeaderVisitor; class WebString; class WebURL; class WebURLResponsePrivate; @@ -49,51 +52,69 @@ namespace WebKit { WebURLResponse(const WebURLResponse& r) : m_private(0) { assign(r); } WebURLResponse& operator=(const WebURLResponse& r) { assign(r); return *this; } + explicit WebURLResponse(const WebURL& url) : m_private(0) + { + initialize(); + setURL(url); + } + WEBKIT_API void initialize(); WEBKIT_API void reset(); WEBKIT_API void assign(const WebURLResponse&); bool isNull() const { return m_private == 0; } - WEBKIT_API WebURL url() const = 0; - WEBKIT_API void setURL(const WebURL&) = 0; + WEBKIT_API WebURL url() const; + WEBKIT_API void setURL(const WebURL&); - WEBKIT_API WebString mimeType() const = 0; - WEBKIT_API void setMIMEType(const WebString&) = 0; + WEBKIT_API WebString mimeType() const; + WEBKIT_API void setMIMEType(const WebString&); - WEBKIT_API long long expectedContentLength() const = 0; - WEBKIT_API void setExpectedContentLength(long long) = 0; + WEBKIT_API long long expectedContentLength() const; + WEBKIT_API void setExpectedContentLength(long long); - WEBKIT_API WebString textEncodingName() const = 0; - WEBKIT_API void setTextEncodingName(const WebString&) = 0; + WEBKIT_API WebString textEncodingName() const; + WEBKIT_API void setTextEncodingName(const WebString&); - WEBKIT_API WebString suggestedFileName() const = 0; - WEBKIT_API void setSuggestedFileName(const WebString&) = 0; + WEBKIT_API WebString suggestedFileName() const; + WEBKIT_API void setSuggestedFileName(const WebString&); - WEBKIT_API int httpStatusCode() const = 0; - WEBKIT_API void setHTTPStatusCode(int) = 0; + WEBKIT_API int httpStatusCode() const; + WEBKIT_API void setHTTPStatusCode(int); - WEBKIT_API WebString httpStatusText() const = 0; - WEBKIT_API void setHTTPStatusText(const WebString&) = 0; + WEBKIT_API WebString httpStatusText() const; + WEBKIT_API void setHTTPStatusText(const WebString&); - WEBKIT_API WebString httpHeaderField(const WebString& name) const = 0; - WEBKIT_API void setHTTPHeaderField(const WebString& name, const WebString& value) = 0; - WEBKIT_API void addHTTPHeaderField(const WebString& name, const WebString& value) = 0; - WEBKIT_API void clearHTTPHeaderField(const WebString& name) = 0; + WEBKIT_API WebString httpHeaderField(const WebString& name) const; + WEBKIT_API void setHTTPHeaderField(const WebString& name, const WebString& value); + WEBKIT_API void addHTTPHeaderField(const WebString& name, const WebString& value); + WEBKIT_API void clearHTTPHeaderField(const WebString& name); + WEBKIT_API void visitHTTPHeaderFields(WebHTTPHeaderVisitor*) const; - WEBKIT_API double expirationDate() const = 0; - WEBKIT_API void setExpirationDate(double) = 0; + WEBKIT_API double expirationDate() const; + WEBKIT_API void setExpirationDate(double); - WEBKIT_API double lastModifiedDate() const = 0; - WEBKIT_API void setLastModifiedDate(double) = 0; + WEBKIT_API double lastModifiedDate() const; + WEBKIT_API void setLastModifiedDate(double); - WEBKIT_API bool isContentFiltered() const = 0; - WEBKIT_API void setIsContentFiltered(bool) = 0; + WEBKIT_API bool isContentFiltered() const; + WEBKIT_API void setIsContentFiltered(bool); + + WEBKIT_API long long appCacheID() const; + WEBKIT_API void setAppCacheID(long long); // A consumer controlled value intended to be used to record opaque // security info related to this request. - WEBKIT_API WebCString securityInfo() const = 0; - WEBKIT_API void setSecurityInfo(const WebCString&) = 0; + WEBKIT_API WebCString securityInfo() const; + WEBKIT_API void setSecurityInfo(const WebCString&); + +#if defined(WEBKIT_IMPLEMENTATION) + WebCore::ResourceResponse& toMutableResourceResponse(); + const WebCore::ResourceResponse& toResourceResponse() const; +#endif + + protected: + void assign(WebURLResponsePrivate*); private: WebURLResponsePrivate* m_private; diff --git a/webkit/api/src/ResourceHandle.cpp b/webkit/api/src/ResourceHandle.cpp new file mode 100644 index 0000000..b7def8d --- /dev/null +++ b/webkit/api/src/ResourceHandle.cpp @@ -0,0 +1,279 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER 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 "ResourceHandle.h" + +#include "WebKit.h" +#include "WebKitClient.h" +#include "WebURLError.h" +#include "WebURLLoader.h" +#include "WebURLLoaderClient.h" +#include "WebURLRequest.h" +#include "WebURLResponse.h" +#include "WrappedResourceRequest.h" +#include "WrappedResourceResponse.h" + +#include "ResourceHandleClient.h" +#include "ResourceRequest.h" + +using namespace WebKit; + +namespace WebCore { + +// ResourceHandleInternal ----------------------------------------------------- + +class ResourceHandleInternal : public WebURLLoaderClient { +public: + ResourceHandleInternal(const ResourceRequest& request, ResourceHandleClient* client) + : m_request(request) + , m_owner(0) + , m_client(client) + { + } + + void start(); + void cancel(); + void setDefersLoading(bool); + + // WebURLLoaderClient methods: + virtual void willSendRequest(WebURLLoader*, WebURLRequest&, const WebURLResponse&); + virtual void didSendData( + WebURLLoader*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent); + virtual void didReceiveResponse(WebURLLoader*, const WebURLResponse&); + virtual void didReceiveData( + WebURLLoader*, const char* data, int dataLength, long long totalDataLength); + virtual void didFinishLoading(WebURLLoader*); + virtual void didFail(WebURLLoader*, const WebURLError&); + + ResourceRequest m_request; + ResourceHandle* m_owner; + ResourceHandleClient* m_client; + OwnPtr<WebURLLoader> m_loader; +}; + +void ResourceHandleInternal::start() +{ + m_loader.set(webKitClient()->createURLLoader()); + ASSERT(m_loader.get()); + + WrappedResourceRequest wrappedRequest(m_request); + m_loader->loadAsynchronously(wrappedRequest, this); +} + +void ResourceHandleInternal::cancel() +{ + m_loader->cancel(); + + // Do not make any further calls to the client. + m_client = 0; +} + +void ResourceHandleInternal::setDefersLoading(bool value) +{ + m_loader->setDefersLoading(value); +} + +void ResourceHandleInternal::willSendRequest( + WebURLLoader*, WebURLRequest& request, const WebURLResponse& response) +{ + ASSERT(m_client); + ASSERT(!request.isNull()); + ASSERT(!response.isNull()); + m_client->willSendRequest(m_owner, request.toMutableResourceRequest(), response.toResourceResponse()); +} + +void ResourceHandleInternal::didSendData( + WebURLLoader*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent) +{ + ASSERT(m_client); + m_client->didSendData(m_owner, bytesSent, totalBytesToBeSent); +} + +void ResourceHandleInternal::didReceiveResponse(WebURLLoader*, const WebURLResponse& response) +{ + ASSERT(m_client); + ASSERT(!response.isNull()); + m_client->didReceiveResponse(m_owner, response.toResourceResponse()); +} + +void ResourceHandleInternal::didReceiveData( + WebURLLoader*, const char* data, int dataLength, long long totalDataLength) +{ + ASSERT(m_client); + + // FIXME: ResourceHandleClient::didReceiveData should take a 'long long' + int lengthReceived = static_cast<int>(totalDataLength); + if (lengthReceived != totalDataLength) // overflow occurred + lengthReceived = -1; + + m_client->didReceiveData(m_owner, data, dataLength, lengthReceived); +} + +void ResourceHandleInternal::didFinishLoading(WebURLLoader*) +{ + ASSERT(m_client); + m_client->didFinishLoading(m_owner); +} + +void ResourceHandleInternal::didFail(WebURLLoader*, const WebURLError& error) +{ + ASSERT(m_client); + m_client->didFail(m_owner, error); +} + +// ResourceHandle ------------------------------------------------------------- + +ResourceHandle::ResourceHandle(const ResourceRequest& request, + ResourceHandleClient* client, + bool defersLoading, + bool shouldContentSniff, + bool mightDownloadFromHandle) + : d(new ResourceHandleInternal(request, client)) +{ + d->m_owner = this; + + // FIXME: Figure out what to do with the bool params. +} + +PassRefPtr<ResourceHandle> ResourceHandle::create(const ResourceRequest& request, + ResourceHandleClient* client, + Frame* deprecated, + bool defersLoading, + bool shouldContentSniff, + bool mightDownloadFromHandle) +{ + RefPtr<ResourceHandle> newHandle = adoptRef(new ResourceHandle( + request, client, defersLoading, shouldContentSniff, mightDownloadFromHandle)); + + if (newHandle->start(deprecated)) + return newHandle.release(); + + return 0; +} + +const ResourceRequest& ResourceHandle::request() const +{ + return d->m_request; +} + +ResourceHandleClient* ResourceHandle::client() const +{ + return d->m_client; +} + +void ResourceHandle::setClient(ResourceHandleClient* client) +{ + d->m_client = client; +} + +void ResourceHandle::setDefersLoading(bool value) +{ + d->setDefersLoading(value); +} + +bool ResourceHandle::start(Frame* deprecated) +{ + d->start(); + return true; +} + +void ResourceHandle::clearAuthentication() +{ +} + +void ResourceHandle::cancel() +{ + d->cancel(); +} + +ResourceHandle::~ResourceHandle() +{ + d->m_owner = 0; +} + +PassRefPtr<SharedBuffer> ResourceHandle::bufferedData() +{ + return 0; +} + +bool ResourceHandle::loadsBlocked() +{ + return false; // This seems to be related to sync XMLHttpRequest... +} + +// static +bool ResourceHandle::supportsBufferedData() +{ + return false; // The loader will buffer manually if it needs to. +} + +// static +void ResourceHandle::loadResourceSynchronously(const ResourceRequest& request, + StoredCredentials unused, + ResourceError& error, + ResourceResponse& response, + Vector<char>& data, + Frame* deprecated) +{ + OwnPtr<WebURLLoader> loader(webKitClient()->createURLLoader()); + ASSERT(loader.get()); + + WrappedResourceRequest requestIn(request); + WrappedResourceResponse responseOut(response); + WebURLError errorOut; + WebData dataOut; + + loader->loadSynchronously(requestIn, responseOut, errorOut, dataOut); + + error = errorOut; + data.clear(); + data.append(dataOut.data(), dataOut.size()); +} + +// static +bool ResourceHandle::willLoadFromCache(ResourceRequest& request) +{ + // This method is used to determine if a POST request can be repeated from + // cache, but you cannot really know until you actually try to read from the + // cache. Even if we checked now, something else could come along and wipe + // out the cache entry by the time we fetch it. + // + // So, we always say yes here, which allows us to generate an ERR_CACHE_MISS + // if the request cannot be serviced from cache. We force the 'DontLoad' + // cache policy at this point to ensure that we never hit the network for + // this request. + // + ASSERT(request.httpMethod() == "POST"); + request.setCachePolicy(ReturnCacheDataDontLoad); + return true; +} + +} // namespace WebCore diff --git a/webkit/api/src/WebDragData.cpp b/webkit/api/src/WebDragData.cpp index 426ceea..a8210ac 100644 --- a/webkit/api/src/WebDragData.cpp +++ b/webkit/api/src/WebDragData.cpp @@ -53,10 +53,7 @@ void WebDragData::initialize() void WebDragData::reset() { - if (m_private) { - m_private->deref(); - m_private = 0; - } + assign(0); } void WebDragData::assign(const WebDragData& other) diff --git a/webkit/api/src/WebHTTPBody.cpp b/webkit/api/src/WebHTTPBody.cpp new file mode 100644 index 0000000..69875e7 --- /dev/null +++ b/webkit/api/src/WebHTTPBody.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER 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 "WebHTTPBody.h" + +#include "FormData.h" + +using namespace WebCore; + +namespace WebKit { + +class WebHTTPBodyPrivate : public FormData { +}; + +void WebHTTPBody::initialize() +{ + assign(static_cast<WebHTTPBodyPrivate*>(FormData::create().releaseRef())); +} + +void WebHTTPBody::reset() +{ + assign(0); +} + +size_t WebHTTPBody::elementCount() const +{ + return m_private->elements().size(); +} + +bool WebHTTPBody::elementAt(size_t index, Element& result) const +{ + if (index >= m_private->elements().size()) + return false; + + const FormDataElement& element = m_private->elements()[index]; + + switch (element.m_type) { + case FormDataElement::data: + result.type = Element::TypeData; + result.data.assign(element.m_data.data(), element.m_data.size()); + result.filePath.reset(); + break; + case FormDataElement::encodedFile: + result.type = Element::TypeFile; + result.data.reset(); + result.filePath = element.m_filename; + break; + default: + ASSERT_NOT_REACHED(); + return false; + } + + return true; +} + +void WebHTTPBody::appendData(const WebData& data) +{ + // FIXME: FormDataElement::m_data should be a SharedBuffer<char>. Then we + // could avoid this buffer copy. + m_private->appendData(data.data(), data.size()); +} + +void WebHTTPBody::appendFile(const WebString& filePath) +{ + m_private->appendFile(filePath); +} + +long long WebHTTPBody::identifier() const +{ + return m_private->identifier(); +} + +void WebHTTPBody::setIdentifier(long long identifier) +{ + return m_private->setIdentifier(identifier); +} + +void WebHTTPBody::rebind(PassRefPtr<FormData> formData) +{ + assign(static_cast<WebHTTPBodyPrivate*>(formData.releaseRef())); +} + +WebHTTPBody::operator PassRefPtr<FormData>() const +{ + return m_private; +} + +void WebHTTPBody::assign(WebHTTPBodyPrivate* p) +{ + // p is already ref'd for us by the caller + if (m_private) + m_private->deref(); + m_private = p; +} + +} // namespace WebKit diff --git a/webkit/api/src/WebURLError.cpp b/webkit/api/src/WebURLError.cpp new file mode 100644 index 0000000..cd7d72d --- /dev/null +++ b/webkit/api/src/WebURLError.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER 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 "WebURLError.h" + +#include "CString.h" +#include "KURL.h" +#include "ResourceError.h" + +using namespace WebCore; + +namespace WebKit { + +WebURLError::WebURLError(const ResourceError& error) +{ + *this = error; +} + +WebURLError& WebURLError::operator=(const ResourceError& error) +{ + if (error.isNull()) + *this = WebURLError(); + else { + domain = error.domain(); + reason = error.errorCode(); + unreachableURL = KURL(error.failingURL()); + } + return *this; +} + +WebURLError::operator ResourceError() const +{ + if (reason == 0) + return ResourceError(); + CString spec = unreachableURL.spec(); + return ResourceError(domain, reason, + String::fromUTF8(spec.data(), spec.length()), + String()); +} + +} // namespace WebKit diff --git a/webkit/api/src/WebURLRequest.cpp b/webkit/api/src/WebURLRequest.cpp new file mode 100644 index 0000000..66483f9 --- /dev/null +++ b/webkit/api/src/WebURLRequest.cpp @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER 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 "WebURLRequest.h" + +#include "WebHTTPHeaderVisitor.h" +#include "WebURL.h" +#include "WebURLRequestPrivate.h" + +#include "ResourceRequest.h" + +using namespace WebCore; + +namespace WebKit { + +// The standard implementation of WebURLRequestPrivate, which maintains +// ownership of a ResourceRequest instance. +class WebURLRequestPrivateImpl : public WebURLRequestPrivate { +public: + WebURLRequestPrivateImpl() + { + m_resourceRequest = &m_resourceRequestAllocation; + } + + WebURLRequestPrivateImpl(const WebURLRequestPrivate* p) + : m_resourceRequestAllocation(*p->m_resourceRequest) + { + m_resourceRequest = &m_resourceRequestAllocation; + } + + virtual void dispose() { delete this; } + + ResourceRequest m_resourceRequestAllocation; +}; + +void WebURLRequest::initialize() +{ + assign(new WebURLRequestPrivateImpl()); +} + +void WebURLRequest::reset() +{ + assign(0); +} + +void WebURLRequest::assign(const WebURLRequest& r) +{ + assign(r.m_private ? new WebURLRequestPrivateImpl(r.m_private) : 0); +} + +WebURL WebURLRequest::url() const +{ + return m_private->m_resourceRequest->url(); +} + +void WebURLRequest::setURL(const WebURL& url) +{ + m_private->m_resourceRequest->setURL(url); +} + +WebURL WebURLRequest::firstPartyForCookies() const +{ + return m_private->m_resourceRequest->firstPartyForCookies(); +} + +void WebURLRequest::setFirstPartyForCookies(const WebURL& firstPartyForCookies) +{ + m_private->m_resourceRequest->setFirstPartyForCookies(firstPartyForCookies); +} + +WebURLRequest::CachePolicy WebURLRequest::cachePolicy() const +{ + return static_cast<WebURLRequest::CachePolicy>( + m_private->m_resourceRequest->cachePolicy()); +} + +void WebURLRequest::setCachePolicy(CachePolicy cachePolicy) +{ + m_private->m_resourceRequest->setCachePolicy( + static_cast<ResourceRequestCachePolicy>(cachePolicy)); +} + +WebString WebURLRequest::httpMethod() const +{ + return m_private->m_resourceRequest->httpMethod(); +} + +void WebURLRequest::setHTTPMethod(const WebString& httpMethod) +{ + m_private->m_resourceRequest->setHTTPMethod(httpMethod); +} + +WebString WebURLRequest::httpHeaderField(const WebString& name) const +{ + return m_private->m_resourceRequest->httpHeaderField(String(name)); +} + +void WebURLRequest::setHTTPHeaderField(const WebString& name, const WebString& value) +{ + m_private->m_resourceRequest->setHTTPHeaderField(String(name), value); +} + +void WebURLRequest::addHTTPHeaderField(const WebString& name, const WebString& value) +{ + m_private->m_resourceRequest->addHTTPHeaderField(String(name), value); +} + +void WebURLRequest::clearHTTPHeaderField(const WebString& name) +{ + // FIXME: Add a clearHTTPHeaderField method to ResourceRequest. + const HTTPHeaderMap& map = m_private->m_resourceRequest->httpHeaderFields(); + const_cast<HTTPHeaderMap*>(&map)->remove(String(name)); +} + +void WebURLRequest::visitHTTPHeaderFields(WebHTTPHeaderVisitor* visitor) const +{ + const HTTPHeaderMap& map = m_private->m_resourceRequest->httpHeaderFields(); + for (HTTPHeaderMap::const_iterator it = map.begin(); it != map.end(); ++it) + visitor->visitHeader(String(it->first), it->second); +} + +const WebHTTPBody& WebURLRequest::httpBody() const +{ + m_private->m_httpBody.rebind(m_private->m_resourceRequest->httpBody()); + return m_private->m_httpBody; +} + +void WebURLRequest::setHTTPBody(const WebHTTPBody& httpBody) +{ + m_private->m_resourceRequest->setHTTPBody(httpBody); + m_private->m_httpBody.rebind(0); // Free memory of the old body +} + +bool WebURLRequest::reportUploadProgress() const +{ + return m_private->m_resourceRequest->reportUploadProgress(); +} + +void WebURLRequest::setReportUploadProgress(bool reportUploadProgress) +{ + m_private->m_resourceRequest->setReportUploadProgress(reportUploadProgress); +} + +WebURLRequest::TargetType WebURLRequest::targetType() const +{ + return static_cast<TargetType>(m_private->m_resourceRequest->targetType()); +} + +void WebURLRequest::setTargetType(TargetType targetType) +{ + m_private->m_resourceRequest->setTargetType( + static_cast<ResourceRequest::TargetType>(targetType)); +} + +int WebURLRequest::requestorID() const +{ + return m_private->m_resourceRequest->requestorID(); +} + +void WebURLRequest::setRequestorID(int requestorID) +{ + m_private->m_resourceRequest->setRequestorID(requestorID); +} + +int WebURLRequest::requestorProcessID() const +{ + return m_private->m_resourceRequest->requestorProcessID(); +} + +void WebURLRequest::setRequestorProcessID(int requestorProcessID) +{ + m_private->m_resourceRequest->setRequestorProcessID(requestorProcessID); +} + +int WebURLRequest::appCacheContextID() const +{ + return m_private->m_resourceRequest->appCacheContextID(); +} + +void WebURLRequest::setAppCacheContextID(int appCacheContextID) +{ + m_private->m_resourceRequest->setAppCacheContextID(appCacheContextID); +} + +WebCString WebURLRequest::securityInfo() const +{ + return m_private->m_resourceRequest->securityInfo(); +} + +void WebURLRequest::setSecurityInfo(const WebCString& securityInfo) +{ + m_private->m_resourceRequest->setSecurityInfo(securityInfo); +} + +ResourceRequest& WebURLRequest::toMutableResourceRequest() +{ + ASSERT(m_private); + ASSERT(m_private->m_resourceRequest); + + return *m_private->m_resourceRequest; +} + +const ResourceRequest& WebURLRequest::toResourceRequest() const +{ + ASSERT(m_private); + ASSERT(m_private->m_resourceRequest); + + return *m_private->m_resourceRequest; +} + +void WebURLRequest::assign(WebURLRequestPrivate* p) +{ + if (m_private) + m_private->dispose(); + m_private = p; +} + +} // namespace WebKit diff --git a/webkit/api/src/WebURLRequestPrivate.h b/webkit/api/src/WebURLRequestPrivate.h new file mode 100644 index 0000000..57ef3d1 --- /dev/null +++ b/webkit/api/src/WebURLRequestPrivate.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER 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 WebURLRequestPrivate_h +#define WebURLRequestPrivate_h + +#include "WebHTTPBody.h" + +namespace WebCore { struct ResourceRequest; } + +namespace WebKit { + + class WebURLRequestPrivate { + public: + WebURLRequestPrivate() : m_resourceRequest(0) { } + + // Called by WebURLRequest when it no longer needs this object. + virtual void dispose() = 0; + + WebCore::ResourceRequest* m_resourceRequest; + WebHTTPBody m_httpBody; + }; + +} // namespace WebKit + +#endif diff --git a/webkit/api/src/WebURLResponse.cpp b/webkit/api/src/WebURLResponse.cpp new file mode 100644 index 0000000..52e193f --- /dev/null +++ b/webkit/api/src/WebURLResponse.cpp @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER 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 "WebURLResponse.h" + +#include "WebHTTPHeaderVisitor.h" +#include "WebString.h" +#include "WebURL.h" +#include "WebURLResponsePrivate.h" + +#include "ResourceResponse.h" + +using namespace WebCore; + +namespace WebKit { + +// The standard implementation of WebURLResponsePrivate, which maintains +// ownership of a ResourceResponse instance. +class WebURLResponsePrivateImpl : public WebURLResponsePrivate { +public: + WebURLResponsePrivateImpl() + { + m_resourceResponse = &m_resourceResponseAllocation; + } + + WebURLResponsePrivateImpl(const WebURLResponsePrivate* p) + : m_resourceResponseAllocation(*p->m_resourceResponse) + { + m_resourceResponse = &m_resourceResponseAllocation; + } + + virtual void dispose() { delete this; } + + ResourceResponse m_resourceResponseAllocation; +}; + +void WebURLResponse::initialize() +{ + assign(new WebURLResponsePrivateImpl()); +} + +void WebURLResponse::reset() +{ + assign(0); +} + +void WebURLResponse::assign(const WebURLResponse& r) +{ + assign(r.m_private ? new WebURLResponsePrivateImpl(r.m_private) : 0); +} + +WebURL WebURLResponse::url() const +{ + return m_private->m_resourceResponse->url(); +} + +void WebURLResponse::setURL(const WebURL& url) +{ + m_private->m_resourceResponse->setURL(url); +} + +WebString WebURLResponse::mimeType() const +{ + return m_private->m_resourceResponse->mimeType(); +} + +void WebURLResponse::setMIMEType(const WebString& mimeType) +{ + m_private->m_resourceResponse->setMimeType(mimeType); +} + +long long WebURLResponse::expectedContentLength() const +{ + return m_private->m_resourceResponse->expectedContentLength(); +} + +void WebURLResponse::setExpectedContentLength(long long expectedContentLength) +{ + m_private->m_resourceResponse->setExpectedContentLength(expectedContentLength); +} + +WebString WebURLResponse::textEncodingName() const +{ + return m_private->m_resourceResponse->textEncodingName(); +} + +void WebURLResponse::setTextEncodingName(const WebString& textEncodingName) +{ + m_private->m_resourceResponse->setTextEncodingName(textEncodingName); +} + +WebString WebURLResponse::suggestedFileName() const +{ + return m_private->m_resourceResponse->suggestedFilename(); +} + +void WebURLResponse::setSuggestedFileName(const WebString& suggestedFileName) +{ + m_private->m_resourceResponse->setSuggestedFilename(suggestedFileName); +} + +int WebURLResponse::httpStatusCode() const +{ + return m_private->m_resourceResponse->httpStatusCode(); +} + +void WebURLResponse::setHTTPStatusCode(int httpStatusCode) +{ + m_private->m_resourceResponse->setHTTPStatusCode(httpStatusCode); +} + +WebString WebURLResponse::httpStatusText() const +{ + return m_private->m_resourceResponse->httpStatusText(); +} + +void WebURLResponse::setHTTPStatusText(const WebString& httpStatusText) +{ + m_private->m_resourceResponse->setHTTPStatusText(httpStatusText); +} + +WebString WebURLResponse::httpHeaderField(const WebString& name) const +{ + return m_private->m_resourceResponse->httpHeaderField(String(name)); +} + +void WebURLResponse::setHTTPHeaderField(const WebString& name, const WebString& value) +{ + m_private->m_resourceResponse->setHTTPHeaderField(String(name), value); +} + +void WebURLResponse::addHTTPHeaderField(const WebString& name, const WebString& value) +{ + // FIXME: Add an addHTTPHeaderField method to ResourceResponse. + const HTTPHeaderMap& map = m_private->m_resourceResponse->httpHeaderFields(); + String valueStr(value); + pair<HTTPHeaderMap::iterator, bool> result = + const_cast<HTTPHeaderMap*>(&map)->add(String(name), valueStr); + if (!result.second) + result.first->second += "," + valueStr; +} + +void WebURLResponse::clearHTTPHeaderField(const WebString& name) +{ + // FIXME: Add a clearHTTPHeaderField method to ResourceResponse. + const HTTPHeaderMap& map = m_private->m_resourceResponse->httpHeaderFields(); + const_cast<HTTPHeaderMap*>(&map)->remove(String(name)); +} + +void WebURLResponse::visitHTTPHeaderFields(WebHTTPHeaderVisitor* visitor) const +{ + const HTTPHeaderMap& map = m_private->m_resourceResponse->httpHeaderFields(); + for (HTTPHeaderMap::const_iterator it = map.begin(); it != map.end(); ++it) + visitor->visitHeader(String(it->first), it->second); +} + +double WebURLResponse::expirationDate() const +{ + return static_cast<double>(m_private->m_resourceResponse->expirationDate()); +} + +void WebURLResponse::setExpirationDate(double expirationDate) +{ + m_private->m_resourceResponse->setExpirationDate(static_cast<time_t>(expirationDate)); +} + +double WebURLResponse::lastModifiedDate() const +{ + return static_cast<double>(m_private->m_resourceResponse->lastModifiedDate()); +} + +void WebURLResponse::setLastModifiedDate(double lastModifiedDate) +{ + m_private->m_resourceResponse->setLastModifiedDate(static_cast<time_t>(lastModifiedDate)); +} + +bool WebURLResponse::isContentFiltered() const +{ + return m_private->m_resourceResponse->isContentFiltered(); +} + +void WebURLResponse::setIsContentFiltered(bool isContentFiltered) +{ + m_private->m_resourceResponse->setIsContentFiltered(isContentFiltered); +} + +long long WebURLResponse::appCacheID() const +{ + return m_private->m_resourceResponse->getAppCacheID(); +} + +void WebURLResponse::setAppCacheID(long long appCacheID) +{ + m_private->m_resourceResponse->setAppCacheID(appCacheID); +} + +WebCString WebURLResponse::securityInfo() const +{ + // FIXME: getSecurityInfo is misnamed. + return m_private->m_resourceResponse->getSecurityInfo(); +} + +void WebURLResponse::setSecurityInfo(const WebCString& securityInfo) +{ + m_private->m_resourceResponse->setSecurityInfo(securityInfo); +} + +ResourceResponse& WebURLResponse::toMutableResourceResponse() +{ + ASSERT(m_private); + ASSERT(m_private->m_resourceResponse); + + return *m_private->m_resourceResponse; +} + +const ResourceResponse& WebURLResponse::toResourceResponse() const +{ + ASSERT(m_private); + ASSERT(m_private->m_resourceResponse); + + return *m_private->m_resourceResponse; +} + +void WebURLResponse::assign(WebURLResponsePrivate* p) +{ + if (m_private) + m_private->dispose(); + m_private = p; +} + +} // namespace WebKit diff --git a/webkit/api/src/WebURLResponsePrivate.h b/webkit/api/src/WebURLResponsePrivate.h new file mode 100644 index 0000000..d421c1a --- /dev/null +++ b/webkit/api/src/WebURLResponsePrivate.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER 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 WebURLResponsePrivate_h +#define WebURLResponsePrivate_h + +namespace WebCore { class ResourceResponse; } + +namespace WebKit { + + class WebURLResponsePrivate { + public: + WebURLResponsePrivate() : m_resourceResponse(0) { } + + // Called by WebURLResponse when it no longer needs this object. + virtual void dispose() = 0; + + WebCore::ResourceResponse* m_resourceResponse; + }; + +} // namespace WebKit + +#endif diff --git a/webkit/api/src/WrappedResourceRequest.h b/webkit/api/src/WrappedResourceRequest.h new file mode 100644 index 0000000..58188c1 --- /dev/null +++ b/webkit/api/src/WrappedResourceRequest.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER 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 "WebURLRequestPrivate.h" + +namespace WebKit { + + class WrappedResourceRequest : public WebURLRequest { + public: + ~WrappedResourceRequest() + { + reset(); // Need to drop reference to m_handle + } + + WrappedResourceRequest(WebCore::ResourceRequest& resourceRequest) + { + bind(&resourceRequest); + } + + WrappedResourceRequest(const WebCore::ResourceRequest& resourceRequest) + { + bind(const_cast<WebCore::ResourceRequest*>(&resourceRequest)); + } + + private: + void bind(WebCore::ResourceRequest* resourceRequest) + { + m_handle.m_resourceRequest = resourceRequest; + assign(&m_handle); + } + + class Handle : public WebURLRequestPrivate { + public: + virtual void dispose() { m_resourceRequest = 0; } + }; + + Handle m_handle; + }; + +} // namespace WebKit diff --git a/webkit/api/src/WrappedResourceResponse.h b/webkit/api/src/WrappedResourceResponse.h new file mode 100644 index 0000000..fe7bb99 --- /dev/null +++ b/webkit/api/src/WrappedResourceResponse.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2009 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * 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. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER 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 "WebURLResponse.h" +#include "WebURLResponsePrivate.h" + +namespace WebKit { + + class WrappedResourceResponse : public WebURLResponse { + public: + ~WrappedResourceResponse() + { + reset(); // Need to drop reference to m_handle + } + + WrappedResourceResponse(WebCore::ResourceResponse& resourceResponse) + { + bind(&resourceResponse); + } + + WrappedResourceResponse(const WebCore::ResourceResponse& resourceResponse) + { + bind(const_cast<WebCore::ResourceResponse*>(&resourceResponse)); + } + + private: + void bind(WebCore::ResourceResponse* resourceResponse) + { + m_handle.m_resourceResponse = resourceResponse; + assign(&m_handle); + } + + class Handle : public WebURLResponsePrivate { + public: + virtual void dispose() { m_resourceResponse = 0; } + }; + + Handle m_handle; + }; + +} // namespace WebKit diff --git a/webkit/glue/glue_util.cc b/webkit/glue/glue_util.cc index 5f7228f..b85ad71 100644 --- a/webkit/glue/glue_util.cc +++ b/webkit/glue/glue_util.cc @@ -35,6 +35,8 @@ #include "webkit/api/public/WebSize.h" #include "webkit/api/public/WebString.h" #include "webkit/api/public/WebURL.h" +#include "webkit/api/public/WebURLRequest.h" +#include "webkit/api/public/WebURLResponse.h" namespace webkit_glue { @@ -71,10 +73,9 @@ WebCore::String String16ToString(const string16& str) { } std::string StringToStdString(const WebCore::String& str) { - if (str.length() == 0) - return std::string(); std::string ret; - UTF16ToUTF8(str.characters(), str.length(), &ret); + if (!str.isNull()) + UTF16ToUTF8(str.characters(), str.length(), &ret); return ret; } @@ -108,6 +109,17 @@ WebCore::CString WebCStringToCString(const WebKit::WebCString& str) { return str; } +WebKit::WebString StdStringToWebString(const std::string& str) { + return WebKit::WebString::fromUTF8(str.data(), str.size()); +} + +std::string WebStringToStdString(const WebKit::WebString& str) { + std::string ret; + if (!str.isNull()) + UTF16ToUTF8(str.data(), str.length(), &ret); + return ret; +} + FilePath::StringType StringToFilePathString(const WebCore::String& str) { #if defined(OS_WIN) return StringToStdWString(str); @@ -214,4 +226,28 @@ PassRefPtr<WebCore::ChromiumDataObject> WebDragDataToChromiumDataObject( return data; } +// WebURLRequest conversions --------------------------------------------------- + +WebCore::ResourceRequest* WebURLRequestToMutableResourceRequest( + WebKit::WebURLRequest* request) { + return &request->toMutableResourceRequest(); +} + +const WebCore::ResourceRequest* WebURLRequestToResourceRequest( + const WebKit::WebURLRequest* request) { + return &request->toResourceRequest(); +} + +// WebURLResponse conversions -------------------------------------------------- + +WebCore::ResourceResponse* WebURLResponseToMutableResourceResponse( + WebKit::WebURLResponse* response) { + return &response->toMutableResourceResponse(); +} + +const WebCore::ResourceResponse* WebURLResponseToResourceResponse( + const WebKit::WebURLResponse* response) { + return &response->toResourceResponse(); +} + } // namespace webkit_glue diff --git a/webkit/glue/glue_util.h b/webkit/glue/glue_util.h index 4bcebad..553802c 100644 --- a/webkit/glue/glue_util.h +++ b/webkit/glue/glue_util.h @@ -17,7 +17,9 @@ class IntPoint; class IntRect; class IntSize; class KURL; +class ResourceResponse; class String; +struct ResourceRequest; } namespace WebKit { @@ -25,6 +27,8 @@ class WebCString; class WebDragData; class WebString; class WebURL; +class WebURLRequest; +class WebURLResponse; struct WebPoint; struct WebRect; struct WebSize; @@ -68,6 +72,10 @@ WebCore::String WebStringToString(const WebKit::WebString& str); WebKit::WebCString CStringToWebCString(const WebCore::CString& str); WebCore::CString WebCStringToCString(const WebKit::WebCString& str); +// std::string <-> WebString. Conversion to/from UTF-8. +WebKit::WebString StdStringToWebString(const std::string& str); +std::string WebStringToStdString(const WebKit::WebString& str); + FilePath::StringType StringToFilePathString(const WebCore::String& str); WebCore::String FilePathStringToString(const FilePath::StringType& str); @@ -99,6 +107,18 @@ WebKit::WebDragData ChromiumDataObjectToWebDragData( WTF::PassRefPtr<WebCore::ChromiumDataObject> WebDragDataToChromiumDataObject( const WebKit::WebDragData&); +// Exposes the ResourceRequest contained by a WebURLRequest +WebCore::ResourceRequest* WebURLRequestToMutableResourceRequest( + WebKit::WebURLRequest* req); +const WebCore::ResourceRequest* WebURLRequestToResourceRequest( + const WebKit::WebURLRequest* req); + +// Exposes the ResourceResponse contained by a WebURLResponse +WebCore::ResourceResponse* WebURLResponseToMutableResourceResponse( + WebKit::WebURLResponse* resp); +const WebCore::ResourceResponse* WebURLResponseToResourceResponse( + const WebKit::WebURLResponse* resp); + } // namespace webkit_glue #endif // #ifndef WEBKIT_GLUE_GLUE_UTIL_H_ diff --git a/webkit/glue/multipart_response_delegate.cc b/webkit/glue/multipart_response_delegate.cc index 9e8e67d..2000b61 100644 --- a/webkit/glue/multipart_response_delegate.cc +++ b/webkit/glue/multipart_response_delegate.cc @@ -2,32 +2,64 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "config.h" -#include <string> - -#include "base/compiler_specific.h" - -MSVC_PUSH_WARNING_LEVEL(0); -#include "HTTPHeaderMap.h" -#include "ResourceHandle.h" -#include "ResourceHandleClient.h" -#include "PlatformString.h" -MSVC_POP_WARNING(); +#include "webkit/glue/multipart_response_delegate.h" -#undef LOG #include "base/logging.h" #include "base/string_util.h" -#include "webkit/glue/multipart_response_delegate.h" -#include "webkit/glue/glue_util.h" #include "net/base/net_util.h" +#include "webkit/api/public/WebHTTPHeaderVisitor.h" +#include "webkit/api/public/WebString.h" +#include "webkit/api/public/WebURL.h" +#include "webkit/api/public/WebURLLoaderClient.h" +#include "webkit/glue/glue_util.h" + +using WebKit::WebHTTPHeaderVisitor; +using WebKit::WebString; +using WebKit::WebURLLoader; +using WebKit::WebURLLoaderClient; +using WebKit::WebURLResponse; + +namespace webkit_glue { + +namespace { + +// The list of response headers that we do not copy from the original +// response when generating a WebURLResponse for a MIME payload. +const char* kReplaceHeaders[] = { + "content-type", + "content-length", + "content-disposition", + "content-range", + "range", + "set-cookie" +}; + +class HeaderCopier : public WebHTTPHeaderVisitor { + public: + HeaderCopier(WebURLResponse* response) + : response_(response) { + } + virtual void visitHeader(const WebString& name, const WebString& value) { + const std::string& name_utf8 = WebStringToStdString(name); + for (size_t i = 0; i < arraysize(kReplaceHeaders); ++i) { + if (LowerCaseEqualsASCII(name_utf8, kReplaceHeaders[i])) + return; + } + response_->setHTTPHeaderField(name, value); + } + private: + WebURLResponse* response_; +}; + +} // namespace MultipartResponseDelegate::MultipartResponseDelegate( - WebCore::ResourceHandleClient* client, - WebCore::ResourceHandle* job, - const WebCore::ResourceResponse& response, + WebURLLoaderClient* client, + WebURLLoader* loader, + const WebURLResponse& response, const std::string& boundary) : client_(client), - job_(job), + loader_(loader), original_response_(response), boundary_("--"), first_received_data_(true), @@ -41,7 +73,8 @@ MultipartResponseDelegate::MultipartResponseDelegate( } } -void MultipartResponseDelegate::OnReceivedData(const char* data, int data_len) { +void MultipartResponseDelegate::OnReceivedData(const char* data, + int data_len) { // stop_sending_ means that we've already received the final boundary token. // The server should stop sending us data at this point, but if it does, we // just throw it away. @@ -49,8 +82,7 @@ void MultipartResponseDelegate::OnReceivedData(const char* data, int data_len) { return; // TODO(tc): Figure out what to use for length_received. Maybe we can just - // pass the value on from our caller. See note in - // resource_handle_win.cc:ResourceHandleInternal::OnReceivedData. + // pass the value on from our caller. int length_received = -1; data_.append(data, data_len); @@ -98,8 +130,10 @@ void MultipartResponseDelegate::OnReceivedData(const char* data, int data_len) { while ((boundary_pos = FindBoundary()) != std::string::npos) { if (boundary_pos > 0) { // Send the last data chunk. - client_->didReceiveData(job_, data_.substr(0, boundary_pos).data(), - static_cast<int>(boundary_pos), length_received); + client_->didReceiveData(loader_, + data_.substr(0, boundary_pos).data(), + static_cast<int>(boundary_pos), + length_received); } size_t boundary_end_pos = boundary_pos + boundary_.length(); if (boundary_end_pos < data_.length() && '-' == data_[boundary_end_pos]) { @@ -128,12 +162,15 @@ void MultipartResponseDelegate::OnCompletedRequest() { // TODO(tc): Figure out what to use for length_received. Maybe we can just // pass the value on from our caller. int length_received = -1; - client_->didReceiveData(job_, data_.data(), - static_cast<int>(data_.length()), length_received); + client_->didReceiveData(loader_, + data_.data(), + static_cast<int>(data_.length()), + length_received); } } -int MultipartResponseDelegate::PushOverLine(const std::string& data, size_t pos) { +int MultipartResponseDelegate::PushOverLine(const std::string& data, + size_t pos) { int offset = 0; if (pos < data.length() && (data[pos] == '\r' || data[pos] == '\n')) { ++offset; @@ -175,47 +212,28 @@ bool MultipartResponseDelegate::ParseHeaders() { headers.append(data_.substr(0, line_end_pos)); data_ = data_.substr(line_end_pos); - // Create a ResourceResponse based on the original set of headers + the + // Create a WebURLResponse based on the original set of headers + the // replacement headers. We only replace the same few headers that gecko // does. See netwerk/streamconv/converters/nsMultiMixedConv.cpp. std::string mime_type = net::GetSpecificHeader(headers, "content-type"); std::string charset = net::GetHeaderParamValue(mime_type, "charset"); - WebCore::ResourceResponse response(original_response_.url(), - webkit_glue::StdStringToString(mime_type.c_str()), - -1, - charset.c_str(), - WebCore::String()); - const WebCore::HTTPHeaderMap& orig_headers = - original_response_.httpHeaderFields(); - for (WebCore::HTTPHeaderMap::const_iterator it = orig_headers.begin(); - it != orig_headers.end(); ++it) { - if (!(equalIgnoringCase("content-type", it->first) || - equalIgnoringCase("content-length", it->first) || - equalIgnoringCase("content-disposition", it->first) || - equalIgnoringCase("content-range", it->first) || - equalIgnoringCase("range", it->first) || - equalIgnoringCase("set-cookie", it->first))) { - response.setHTTPHeaderField(it->first, it->second); - } - } - static const char* replace_headers[] = { - "Content-Type", - "Content-Length", - "Content-Disposition", - "Content-Range", - "Range", - "Set-Cookie" - }; - for (size_t i = 0; i < arraysize(replace_headers); ++i) { - std::string name(replace_headers[i]); + WebURLResponse response(original_response_.url()); + response.setMIMEType(StdStringToWebString(mime_type)); + response.setTextEncodingName(StdStringToWebString(charset)); + + HeaderCopier copier(&response); + original_response_.visitHTTPHeaderFields(&copier); + + for (size_t i = 0; i < arraysize(kReplaceHeaders); ++i) { + std::string name(kReplaceHeaders[i]); std::string value = net::GetSpecificHeader(headers, name); if (!value.empty()) { - response.setHTTPHeaderField(webkit_glue::StdStringToString(name.c_str()), - webkit_glue::StdStringToString(value.c_str())); + response.setHTTPHeaderField(StdStringToWebString(name), + StdStringToWebString(value)); } } // Send the response! - client_->didReceiveResponse(job_, response); + client_->didReceiveResponse(loader_, response); return true; } @@ -239,29 +257,27 @@ size_t MultipartResponseDelegate::FindBoundary() { } bool MultipartResponseDelegate::ReadMultipartBoundary( - const WebCore::ResourceResponse& response, + const WebURLResponse& response, std::string* multipart_boundary) { - WebCore::String content_type = response.httpHeaderField("Content-Type"); - std::string content_type_as_string = - webkit_glue::StringToStdString(content_type); + std::string content_type = WebStringToStdString( + response.httpHeaderField(WebString::fromUTF8("Content-Type"))); - size_t boundary_start_offset = content_type_as_string.find("boundary="); + size_t boundary_start_offset = content_type.find("boundary="); if (boundary_start_offset == std::wstring::npos) { return false; } boundary_start_offset += strlen("boundary="); - size_t boundary_end_offset = - content_type_as_string.find(';', boundary_start_offset); + size_t boundary_end_offset = content_type.find(';', boundary_start_offset); if (boundary_end_offset == std::string::npos) - boundary_end_offset = content_type_as_string.length(); + boundary_end_offset = content_type.length(); size_t boundary_length = boundary_end_offset - boundary_start_offset; *multipart_boundary = - content_type_as_string.substr(boundary_start_offset, boundary_length); + content_type.substr(boundary_start_offset, boundary_length); // The byte range response can have quoted boundary strings. This is legal // as per MIME specifications. Individual data fragements however don't // contain quoted boundary strings. @@ -270,16 +286,14 @@ bool MultipartResponseDelegate::ReadMultipartBoundary( } bool MultipartResponseDelegate::ReadContentRanges( - const WebCore::ResourceResponse& response, + const WebURLResponse& response, int* content_range_lower_bound, int* content_range_upper_bound) { - std::string content_range = - webkit_glue::StringToStdString( - response.httpHeaderField("Content-Range")); + std::string content_range = WebStringToStdString( + response.httpHeaderField(WebString::fromUTF8("Content-Range"))); - size_t byte_range_lower_bound_start_offset = - content_range.find(" "); + size_t byte_range_lower_bound_start_offset = content_range.find(" "); if (byte_range_lower_bound_start_offset == std::string::npos) { return false; } @@ -321,3 +335,5 @@ bool MultipartResponseDelegate::ReadContentRanges( return false; return true; } + +} // namespace webkit_glue diff --git a/webkit/glue/multipart_response_delegate.h b/webkit/glue/multipart_response_delegate.h index 41d09c2..3676a78 100644 --- a/webkit/glue/multipart_response_delegate.h +++ b/webkit/glue/multipart_response_delegate.h @@ -1,11 +1,10 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// A delegate class of ResourceHandleInternal (resource_handle_win) that -// handles multipart/x-mixed-replace data. We special case -// multipart/x-mixed-replace because WebCore expects a separate -// didReceiveResponse for each new message part. +// A delegate class of WebURLLoaderImpl that handles multipart/x-mixed-replace +// data. We special case multipart/x-mixed-replace because WebCore expects a +// separate didReceiveResponse for each new message part. // // Most of the logic and edge case handling are based on the Mozilla's // implementation in netwerk/streamconv/converters/nsMultiMixedConv.cpp. @@ -47,28 +46,28 @@ * * ***** END LICENSE BLOCK ***** */ +#ifndef WEBKIT_GLUE_MULTIPART_RESPONSE_DELEGATE_H_ +#define WEBKIT_GLUE_MULTIPART_RESPONSE_DELEGATE_H_ + #include <string> -#include "config.h" +#include "webkit/api/public/WebURLResponse.h" -#include "base/compiler_specific.h" +namespace WebKit { +class WebURLLoader; +class WebURLLoaderClient; +} -MSVC_PUSH_WARNING_LEVEL(0); -#include "ResourceResponse.h" -MSVC_POP_WARNING(); +namespace webkit_glue { -namespace WebCore { - class ResourceHandle; - class ResourceHandleClient; -} +// Used by unit tests to access private members. +class MultipartResponseDelegateTester; class MultipartResponseDelegate { - friend class MultipartResponseTest_Functions_Test; // For unittests. - public: - MultipartResponseDelegate(WebCore::ResourceHandleClient* client, - WebCore::ResourceHandle* job, - const WebCore::ResourceResponse& response, + MultipartResponseDelegate(WebKit::WebURLLoaderClient* client, + WebKit::WebURLLoader* loader, + const WebKit::WebURLResponse& response, const std::string& boundary); // Passed through from ResourceHandleInternal @@ -78,25 +77,27 @@ class MultipartResponseDelegate { // Returns the multi part boundary string from the Content-type header // in the response. // Returns true on success. - static bool ReadMultipartBoundary(const WebCore::ResourceResponse& response, + static bool ReadMultipartBoundary(const WebKit::WebURLResponse& response, std::string* multipart_boundary); // Returns the lower and higher content ranges from an individual multipart // in a multipart response. // Returns true on success. - static bool ReadContentRanges(const WebCore::ResourceResponse& response, + static bool ReadContentRanges(const WebKit::WebURLResponse& response, int* content_range_lower_bound, int* content_range_upper_bound); private: - // Pointers back to our owning object so we can make callbacks as we parse - // pieces of data. - WebCore::ResourceHandleClient* client_; - WebCore::ResourceHandle* job_; + friend class MultipartResponseDelegateTester; // For unittests. + + // Pointers to the client and associated loader so we can make callbacks as + // we parse pieces of data. + WebKit::WebURLLoaderClient* client_; + WebKit::WebURLLoader* loader_; // The original resource response for this request. We use this as a // starting point for each parts response. - WebCore::ResourceResponse original_response_; + WebKit::WebURLResponse original_response_; // Checks to see if data[pos] character is a line break; handles crlf, lflf, // lf, or cr. Returns the number of characters to skip over (0, 1 or 2). @@ -128,3 +129,7 @@ class MultipartResponseDelegate { // processing AddData requests. bool stop_sending_; }; + +} // namespace webkit_glue + +#endif diff --git a/webkit/glue/multipart_response_delegate_unittest.cc b/webkit/glue/multipart_response_delegate_unittest.cc index e05879d..3cafba2 100644 --- a/webkit/glue/multipart_response_delegate_unittest.cc +++ b/webkit/glue/multipart_response_delegate_unittest.cc @@ -4,71 +4,104 @@ #include <vector> -#include "config.h" - -#include "base/compiler_specific.h" - -MSVC_PUSH_WARNING_LEVEL(0); -#include "KURL.h" -#include "ResourceResponse.h" -#include "ResourceHandle.h" -#include "ResourceHandleClient.h" -MSVC_POP_WARNING(); - #include "base/basictypes.h" +#include "webkit/api/public/WebString.h" +#include "webkit/api/public/WebURL.h" +#include "webkit/api/public/WebURLLoaderClient.h" +#include "webkit/api/public/WebURLResponse.h" #include "webkit/glue/glue_util.h" #include "webkit/glue/multipart_response_delegate.h" #include "testing/gtest/include/gtest/gtest.h" -using namespace WebCore; -using namespace std; +using std::string; +using WebKit::WebString; +using WebKit::WebURL; +using WebKit::WebURLError; +using WebKit::WebURLLoader; +using WebKit::WebURLLoaderClient; +using WebKit::WebURLRequest; +using WebKit::WebURLResponse; +using webkit_glue::MultipartResponseDelegate; +using webkit_glue::MultipartResponseDelegateTester; + +namespace webkit_glue { + +class MultipartResponseDelegateTester { + public: + MultipartResponseDelegateTester(MultipartResponseDelegate* delegate) + : delegate_(delegate) { + } + + int PushOverLine(const std::string& data, size_t pos) { + return delegate_->PushOverLine(data, pos); + } + bool ParseHeaders() { return delegate_->ParseHeaders(); } + size_t FindBoundary() { return delegate_->FindBoundary(); } + std::string& boundary() { return delegate_->boundary_; } + std::string& data() { return delegate_->data_; } + + private: + MultipartResponseDelegate* delegate_; +}; + +} // namespace webkit_glue namespace { class MultipartResponseTest : public testing::Test { }; -class MockResourceHandleClient : public ResourceHandleClient { +class MockWebURLLoaderClient : public WebURLLoaderClient { public: - MockResourceHandleClient() { Reset(); } + MockWebURLLoaderClient() { Reset(); } - virtual void didReceiveResponse(ResourceHandle* handle, - const ResourceResponse& response) { + virtual void willSendRequest( + WebURLLoader*, WebURLRequest&, const WebURLResponse&) {} + virtual void didSendData( + WebURLLoader*, unsigned long long, unsigned long long) {} + + virtual void didReceiveResponse(WebURLLoader* loader, + const WebURLResponse& response) { ++received_response_; - resource_response_ = response; + response_ = response; data_.clear(); } - virtual void didReceiveData(ResourceHandle* handle, + virtual void didReceiveData(WebURLLoader* loader, const char* data, int data_length, - int length_received) { + long long length_received) { ++received_data_; data_.append(data, data_length); } + virtual void didFinishLoading(WebURLLoader*) {} + virtual void didFail(WebURLLoader*, const WebURLError&) {} + void Reset() { received_response_ = received_data_ = 0; data_.clear(); - resource_response_ = ResourceResponse(); + response_.reset(); } int received_response_, received_data_; string data_; - ResourceResponse resource_response_; + WebURLResponse response_; }; -} // namespace - // We can't put this in an anonymous function because it's a friend class for // access to private members. TEST(MultipartResponseTest, Functions) { // PushOverLine tests - ResourceResponse response(KURL(), "multipart/x-mixed-replace", 0, "en-US", - String()); - response.setHTTPHeaderField(String("Foo"), String("Bar")); - response.setHTTPHeaderField(String("Content-type"), String("text/plain")); - MockResourceHandleClient client; + WebURLResponse response; + response.initialize(); + response.setMIMEType(WebString::fromUTF8("multipart/x-mixed-replace")); + response.setHTTPHeaderField(WebString::fromUTF8("Foo"), + WebString::fromUTF8("Bar")); + response.setHTTPHeaderField(WebString::fromUTF8("Content-type"), + WebString::fromUTF8("text/plain")); + MockWebURLLoaderClient client; MultipartResponseDelegate delegate(&client, NULL, response, "bound"); + MultipartResponseDelegateTester delegate_tester(&delegate); struct { const char* input; @@ -90,8 +123,8 @@ TEST(MultipartResponseTest, Functions) { }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(line_tests); ++i) { EXPECT_EQ(line_tests[i].expected, - delegate.PushOverLine(line_tests[i].input, - line_tests[i].position)); + delegate_tester.PushOverLine(line_tests[i].input, + line_tests[i].position)); } // ParseHeaders tests @@ -112,33 +145,33 @@ TEST(MultipartResponseTest, Functions) { }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(header_tests); ++i) { client.Reset(); - delegate.data_.assign(header_tests[i].data); + delegate_tester.data().assign(header_tests[i].data); EXPECT_EQ(header_tests[i].rv, - delegate.ParseHeaders()); + delegate_tester.ParseHeaders()); EXPECT_EQ(header_tests[i].received_response_calls, client.received_response_); EXPECT_EQ(string(header_tests[i].newdata), - delegate.data_); + delegate_tester.data()); } // Test that the resource response is filled in correctly when parsing // headers. client.Reset(); string test_header("content-type: image/png\ncontent-length: 10\n\n"); - delegate.data_.assign(test_header); - EXPECT_TRUE(delegate.ParseHeaders()); - EXPECT_TRUE(delegate.data_.length() == 0); - EXPECT_EQ(webkit_glue::StringToStdWString( - client.resource_response_.httpHeaderField( - String("Content-Type"))), - wstring(L"image/png")); - EXPECT_EQ(webkit_glue::StringToStdWString( - client.resource_response_.httpHeaderField( - String("content-length"))), - wstring(L"10")); + delegate_tester.data().assign(test_header); + EXPECT_TRUE(delegate_tester.ParseHeaders()); + EXPECT_TRUE(delegate_tester.data().length() == 0); + EXPECT_EQ(webkit_glue::WebStringToStdString( + client.response_.httpHeaderField( + WebString::fromUTF8("Content-Type"))), + string("image/png")); + EXPECT_EQ(webkit_glue::WebStringToStdString( + client.response_.httpHeaderField( + WebString::fromUTF8("content-length"))), + string("10")); // This header is passed from the original request. - EXPECT_EQ(webkit_glue::StringToStdWString( - client.resource_response_.httpHeaderField(String("foo"))), - wstring(L"Bar")); + EXPECT_EQ(webkit_glue::WebStringToStdString( + client.response_.httpHeaderField(WebString::fromUTF8("foo"))), + string("Bar")); // FindBoundary tests struct { @@ -154,21 +187,22 @@ TEST(MultipartResponseTest, Functions) { { "bound", "--boundbound", 0 }, }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(boundary_tests); ++i) { - delegate.boundary_.assign(boundary_tests[i].boundary); - delegate.data_.assign(boundary_tests[i].data); + delegate_tester.boundary().assign(boundary_tests[i].boundary); + delegate_tester.data().assign(boundary_tests[i].data); EXPECT_EQ(boundary_tests[i].position, - delegate.FindBoundary()); + delegate_tester.FindBoundary()); } } -namespace { - TEST(MultipartResponseTest, MissingBoundaries) { - ResourceResponse response(KURL(), "multipart/x-mixed-replace", 0, "en-US", - String()); - response.setHTTPHeaderField(String("Foo"), String("Bar")); - response.setHTTPHeaderField(String("Content-type"), String("text/plain")); - MockResourceHandleClient client; + WebURLResponse response; + response.initialize(); + response.setMIMEType(WebString::fromUTF8("multipart/x-mixed-replace")); + response.setHTTPHeaderField(WebString::fromUTF8("Foo"), + WebString::fromUTF8("Bar")); + response.setHTTPHeaderField(WebString::fromUTF8("Content-type"), + WebString::fromUTF8("text/plain")); + MockWebURLLoaderClient client; MultipartResponseDelegate delegate(&client, NULL, response, "bound"); // No start boundary @@ -228,11 +262,14 @@ TEST(MultipartResponseTest, MissingBoundaries) { TEST(MultipartResponseTest, MalformedBoundary) { // Some servers send a boundary that is prefixed by "--". See bug 5786. - ResourceResponse response(KURL(), "multipart/x-mixed-replace", 0, "en-US", - String()); - response.setHTTPHeaderField(String("Foo"), String("Bar")); - response.setHTTPHeaderField(String("Content-type"), String("text/plain")); - MockResourceHandleClient client; + WebURLResponse response; + response.initialize(); + response.setMIMEType(WebString::fromUTF8("multipart/x-mixed-replace")); + response.setHTTPHeaderField(WebString::fromUTF8("Foo"), + WebString::fromUTF8("Bar")); + response.setHTTPHeaderField(WebString::fromUTF8("Content-type"), + WebString::fromUTF8("text/plain")); + MockWebURLLoaderClient client; MultipartResponseDelegate delegate(&client, NULL, response, "--bound"); string data( @@ -272,13 +309,14 @@ void VariousChunkSizesTest(const TestChunk chunks[], int chunks_size, int respon "foofoofoofoofoo" // 86-100 "--bound--"); // 101-109 - ResourceResponse response(KURL(), "multipart/x-mixed-replace", 0, "en-US", - String()); - MockResourceHandleClient client; + WebURLResponse response; + response.initialize(); + response.setMIMEType(WebString::fromUTF8("multipart/x-mixed-replace")); + MockWebURLLoaderClient client; MultipartResponseDelegate delegate(&client, NULL, response, "bound"); for (int i = 0; i < chunks_size; ++i) { - ASSERT(chunks[i].start_pos < chunks[i].end_pos); + ASSERT_TRUE(chunks[i].start_pos < chunks[i].end_pos); string chunk = data.substr(chunks[i].start_pos, chunks[i].end_pos - chunks[i].start_pos); delegate.OnReceivedData(chunk.c_str(), static_cast<int>(chunk.length())); @@ -385,9 +423,10 @@ TEST(MultipartResponseTest, BreakInData) { TEST(MultipartResponseTest, MultipleBoundaries) { // Test multiple boundaries back to back - ResourceResponse response(KURL(), "multipart/x-mixed-replace", 0, "en-US", - String()); - MockResourceHandleClient client; + WebURLResponse response; + response.initialize(); + response.setMIMEType(WebString::fromUTF8("multipart/x-mixed-replace")); + MockWebURLLoaderClient client; MultipartResponseDelegate delegate(&client, NULL, response, "bound"); string data("--bound\r\n\r\n--bound\r\n\r\nfoofoo--bound--"); @@ -402,12 +441,14 @@ TEST(MultipartResponseTest, MultipleBoundaries) { TEST(MultipartResponseTest, MultipartByteRangeParsingTest) { // Test multipart/byteranges based boundary parsing. - ResourceResponse response1(KURL(), "multipart/byteranges", 0, "en-US", - String()); - response1.setHTTPHeaderField(String("Content-Length"), String("200")); + WebURLResponse response1; + response1.initialize(); + response1.setMIMEType(WebString::fromUTF8("multipart/x-mixed-replace")); + response1.setHTTPHeaderField(WebString::fromUTF8("Content-Length"), + WebString::fromUTF8("200")); response1.setHTTPHeaderField( - String("Content-type"), - String("multipart/byteranges; boundary=--bound--")); + WebString::fromUTF8("Content-type"), + WebString::fromUTF8("multipart/byteranges; boundary=--bound--")); std::string multipart_boundary; bool result = MultipartResponseDelegate::ReadMultipartBoundary( @@ -416,35 +457,39 @@ TEST(MultipartResponseTest, MultipartByteRangeParsingTest) { EXPECT_EQ(string("--bound--"), multipart_boundary); - ResourceResponse response2(KURL(), "image/png", 0, "en-US", - String()); + WebURLResponse response2; + response2.initialize(); + response2.setMIMEType(WebString::fromUTF8("image/png")); - response2.setHTTPHeaderField(String("Content-Length"), String("300")); + response2.setHTTPHeaderField(WebString::fromUTF8("Content-Length"), + WebString::fromUTF8("300")); response2.setHTTPHeaderField( - String("Last-Modified"), - String("Mon, 04 Apr 2005 20:36:01 GMT")); + WebString::fromUTF8("Last-Modified"), + WebString::fromUTF8("Mon, 04 Apr 2005 20:36:01 GMT")); response2.setHTTPHeaderField( - String("Date"), - String("Thu, 11 Sep 2008 18:21:42 GMT")); + WebString::fromUTF8("Date"), + WebString::fromUTF8("Thu, 11 Sep 2008 18:21:42 GMT")); multipart_boundary.clear(); result = MultipartResponseDelegate::ReadMultipartBoundary( response2, &multipart_boundary); EXPECT_EQ(result, false); - ResourceResponse response3(KURL(), "multipart/byteranges", 0, "en-US", - String()); + WebURLResponse response3; + response3.initialize(); + response3.setMIMEType(WebString::fromUTF8("multipart/byteranges")); - response3.setHTTPHeaderField(String("Content-Length"), String("300")); + response3.setHTTPHeaderField(WebString::fromUTF8("Content-Length"), + WebString::fromUTF8("300")); response3.setHTTPHeaderField( - String("Last-Modified"), - String("Mon, 04 Apr 2005 20:36:01 GMT")); + WebString::fromUTF8("Last-Modified"), + WebString::fromUTF8("Mon, 04 Apr 2005 20:36:01 GMT")); response3.setHTTPHeaderField( - String("Date"), - String("Thu, 11 Sep 2008 18:21:42 GMT")); + WebString::fromUTF8("Date"), + WebString::fromUTF8("Thu, 11 Sep 2008 18:21:42 GMT")); response3.setHTTPHeaderField( - String("Content-type"), - String("multipart/byteranges")); + WebString::fromUTF8("Content-type"), + WebString::fromUTF8("multipart/byteranges")); multipart_boundary.clear(); result = MultipartResponseDelegate::ReadMultipartBoundary( @@ -452,12 +497,15 @@ TEST(MultipartResponseTest, MultipartByteRangeParsingTest) { EXPECT_EQ(result, false); EXPECT_EQ(multipart_boundary.length(), 0U); - ResourceResponse response4(KURL(), "multipart/byteranges", 0, "en-US", - String()); - response4.setHTTPHeaderField(String("Content-Length"), String("200")); + WebURLResponse response4; + response4.initialize(); + response4.setMIMEType(WebString::fromUTF8("multipart/byteranges")); + response4.setHTTPHeaderField(WebString::fromUTF8("Content-Length"), + WebString::fromUTF8("200")); response4.setHTTPHeaderField( - String("Content-type"), - String("multipart/byteranges; boundary=--bound--; charSet=utf8")); + WebString::fromUTF8("Content-type"), + WebString::fromUTF8( + "multipart/byteranges; boundary=--bound--; charSet=utf8")); multipart_boundary.clear(); @@ -466,12 +514,15 @@ TEST(MultipartResponseTest, MultipartByteRangeParsingTest) { EXPECT_EQ(result, true); EXPECT_EQ(string("--bound--"), multipart_boundary); - ResourceResponse response5(KURL(), "multipart/byteranges", 0, "en-US", - String()); - response5.setHTTPHeaderField(String("Content-Length"), String("200")); + WebURLResponse response5; + response5.initialize(); + response5.setMIMEType(WebString::fromUTF8("multipart/byteranges")); + response5.setHTTPHeaderField(WebString::fromUTF8("Content-Length"), + WebString::fromUTF8("200")); response5.setHTTPHeaderField( - String("Content-type"), - String("multipart/byteranges; boundary=\"--bound--\"; charSet=utf8")); + WebString::fromUTF8("Content-type"), + WebString::fromUTF8( + "multipart/byteranges; boundary=\"--bound--\"; charSet=utf8")); multipart_boundary.clear(); @@ -482,12 +533,14 @@ TEST(MultipartResponseTest, MultipartByteRangeParsingTest) { } TEST(MultipartResponseTest, MultipartContentRangesTest) { - ResourceResponse response1(KURL(), "application/pdf", 0, "en-US", - String()); - response1.setHTTPHeaderField(String("Content-Length"), String("200")); + WebURLResponse response1; + response1.initialize(); + response1.setMIMEType(WebString::fromUTF8("application/pdf")); + response1.setHTTPHeaderField(WebString::fromUTF8("Content-Length"), + WebString::fromUTF8("200")); response1.setHTTPHeaderField( - String("Content-Range"), - String("bytes 1000-1050/5000")); + WebString::fromUTF8("Content-Range"), + WebString::fromUTF8("bytes 1000-1050/5000")); int content_range_lower_bound = 0; int content_range_upper_bound = 0; @@ -500,12 +553,14 @@ TEST(MultipartResponseTest, MultipartContentRangesTest) { EXPECT_EQ(content_range_lower_bound, 1000); EXPECT_EQ(content_range_upper_bound, 1050); - ResourceResponse response2(KURL(), "application/pdf", 0, "en-US", - String()); - response2.setHTTPHeaderField(String("Content-Length"), String("200")); + WebURLResponse response2; + response2.initialize(); + response2.setMIMEType(WebString::fromUTF8("application/pdf")); + response2.setHTTPHeaderField(WebString::fromUTF8("Content-Length"), + WebString::fromUTF8("200")); response2.setHTTPHeaderField( - String("Content-Range"), - String("bytes 1000/1050")); + WebString::fromUTF8("Content-Range"), + WebString::fromUTF8("bytes 1000/1050")); content_range_lower_bound = 0; content_range_upper_bound = 0; diff --git a/webkit/glue/resource_handle_impl.cc b/webkit/glue/resource_handle_impl.cc deleted file mode 100644 index 1912094..0000000 --- a/webkit/glue/resource_handle_impl.cc +++ /dev/null @@ -1,765 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// This file replaces WebCore/platform/network/win/ResourceHandleWin.cpp with a -// platform-neutral implementation that simply defers almost entirely to -// ResouceLoaderBridge. -// -// This uses the same ResourceHandle.h header file that the rest of WebKit -// uses, allowing us to avoid complicated changes. Our specific things are -// added on ResourceHandleInternal. The ResourceHandle owns the -// ResourceHandleInternal and passes off almost all processing to it. -// -// The WebKit version of this code keeps the ResourceHandle AddRef'd when -// there are any callbacks. This prevents the callbacks from occuring into -// destroyed objects. However, our destructors should always stop callbacks -// from happening, making this (hopefully) unnecessary. -// -// We preserve this behavior for safety. A client could count on this behavior -// and fire off a request, release it, and wait for callbacks to get the data -// as long as it doesn't care about canceling the request. Although this is -// dumb, we support it. We use pending_ to indicate this extra AddRef, which -// is done in start() and released in OnCompletedRequest. - -#include "config.h" - -#include "base/compiler_specific.h" - -MSVC_PUSH_WARNING_LEVEL(0); -#include "CString.h" -#include "DocLoader.h" -#include "FormData.h" -#include "FrameLoader.h" -#include "Page.h" -#include "ResourceError.h" -#include "ResourceHandle.h" -#include "ResourceHandleClient.h" -#include "ResourceRequest.h" -#include "ResourceResponse.h" -MSVC_POP_WARNING(); - -#undef LOG -#include "base/logging.h" -#include "base/message_loop.h" -#include "base/process_util.h" -#include "base/time.h" -#include "base/string_util.h" -#include "base/string_tokenizer.h" -#include "webkit/glue/feed_preview.h" -#include "webkit/glue/glue_util.h" -#include "webkit/glue/multipart_response_delegate.h" -#include "webkit/glue/resource_loader_bridge.h" -#include "net/base/data_url.h" -#include "net/base/net_errors.h" -#include "net/base/net_util.h" -#include "net/base/load_flags.h" -#include "net/http/http_response_headers.h" - -using webkit_glue::ResourceLoaderBridge; -using base::Time; -using base::TimeDelta; -using net::HttpResponseHeaders; - -namespace WebCore { - -static ResourceType::Type FromTargetType(ResourceRequest::TargetType type) { - switch (type) { - case ResourceRequest::TargetIsMainFrame: - return ResourceType::MAIN_FRAME; - case ResourceRequest::TargetIsSubFrame: - return ResourceType::SUB_FRAME; - case ResourceRequest::TargetIsSubResource: - return ResourceType::SUB_RESOURCE; - case ResourceRequest::TargetIsObject: - return ResourceType::OBJECT; - case ResourceRequest::TargetIsMedia: - return ResourceType::MEDIA; - default: - NOTREACHED(); - return ResourceType::SUB_RESOURCE; - } -} - -// Extracts the information from a data: url. -static bool GetInfoFromDataUrl(const GURL& url, - ResourceLoaderBridge::ResponseInfo* info, - std::string* data, URLRequestStatus* status) { - std::string mime_type; - std::string charset; - if (net::DataURL::Parse(url, &mime_type, &charset, data)) { - *status = URLRequestStatus(URLRequestStatus::SUCCESS, 0); - info->request_time = Time::Now(); - info->response_time = Time::Now(); - info->headers = NULL; - info->mime_type.swap(mime_type); - info->charset.swap(charset); - info->security_info.clear(); - info->content_length = -1; - - return true; - } - - *status = URLRequestStatus(URLRequestStatus::FAILED, net::ERR_INVALID_URL); - return false; -} - -static void ExtractInfoFromHeaders(const HttpResponseHeaders* headers, - HTTPHeaderMap* header_map, - int* status_code, - String* status_text, - long long* expected_content_length) { - *status_code = headers->response_code(); - - // Set the status text - *status_text = webkit_glue::StdStringToString(headers->GetStatusText()); - - // Set the content length. - std::string length_val; - if (headers->EnumerateHeader(NULL, "content-length", &length_val)) - *expected_content_length = StringToInt64(length_val); - - // Build up the header map. Take care with duplicate headers. - void* iter = NULL; - std::string name, value; - while (headers->EnumerateHeaderLines(&iter, &name, &value)) { - String name_str = webkit_glue::StdStringToString(name); - String value_str = webkit_glue::StdStringToString(value); - - pair<HTTPHeaderMap::iterator, bool> result = - header_map->add(name_str, value_str); - if (!result.second) - result.first->second += ", " + value_str; - } -} - -static ResourceResponse MakeResourceResponse( - const KURL& kurl, - const ResourceLoaderBridge::ResponseInfo& info) { - int status_code = 0; - long long expected_content_length = info.content_length; - String status_text; - HTTPHeaderMap header_map; - - // It's okay if there are no headers - if (info.headers) - ExtractInfoFromHeaders(info.headers, - &header_map, - &status_code, - &status_text, - &expected_content_length); - - // TODO(darin): We should leverage HttpResponseHeaders for this, and this - // should be using the same code as ResourceDispatcherHost. - // TODO(jungshik): Figure out the actual value of the referrer charset and - // pass it to GetSuggestedFilename. - std::wstring suggested_filename; - if (info.headers) { - std::string disp_val; - if (info.headers->EnumerateHeader(NULL, "content-disposition", &disp_val)) { - suggested_filename = net::GetSuggestedFilename( - webkit_glue::KURLToGURL(kurl), disp_val, "", std::wstring()); - } - } - - ResourceResponse response(kurl, - webkit_glue::StdStringToString(info.mime_type), - expected_content_length, - webkit_glue::StdStringToString(info.charset), - webkit_glue::StdWStringToString(suggested_filename)); - - if (info.headers) { - Time time_val; - if (info.headers->GetLastModifiedValue(&time_val)) - response.setLastModifiedDate(time_val.ToTimeT()); - - // Compute expiration date - TimeDelta freshness_lifetime = - info.headers->GetFreshnessLifetime(info.response_time); - if (freshness_lifetime != TimeDelta()) { - Time now = Time::Now(); - TimeDelta current_age = - info.headers->GetCurrentAge(info.request_time, info.response_time, - now); - time_val = now + freshness_lifetime - current_age; - - response.setExpirationDate(time_val.ToTimeT()); - } else { - // WebKit uses 0 as a special expiration date that means never expire. - // 1 is a small enough value to let it always expire. - response.setExpirationDate(1); - } - } - - response.setHTTPStatusCode(status_code); - response.setHTTPStatusText(status_text); - response.setSecurityInfo(webkit_glue::StdStringToCString(info.security_info)); - response.setAppCacheID(info.app_cache_id); - - // WebKit doesn't provide a way for us to set expected content length after - // calling the constructor, so we parse the headers first and then swap in - // our HTTP header map. Ideally we would like a setter for expected content - // length (perhaps by abstracting ResourceResponse interface into - // ResourceResponseBase) but that would require forking. - const_cast<HTTPHeaderMap*>(&response.httpHeaderFields())->swap(header_map); - - return response; -} - -class ResourceHandleInternal : public ResourceLoaderBridge::Peer { - public: - ResourceHandleInternal(ResourceHandle* job, const ResourceRequest& r, - ResourceHandleClient* c); - ~ResourceHandleInternal(); - - // If the response parameter is null, then an asynchronous load is started. - bool Start(ResourceLoaderBridge::SyncLoadResponse* response); - - // Used to cancel an asynchronous load. - void Cancel(); - - // Used to suspend/resume an asynchronous load. - void SetDefersLoading(bool value); - - // ResourceLoaderBridge::Peer implementation - virtual void OnUploadProgress(uint64 position, uint64 size); - virtual void OnReceivedRedirect(const GURL& new_url); - virtual void OnReceivedResponse( - const ResourceLoaderBridge::ResponseInfo& info, - bool content_filtered); - virtual void OnReceivedData(const char* data, int len); - virtual void OnCompletedRequest(const URLRequestStatus& status, - const std::string& security_info); - virtual std::string GetURLForDebugging(); - - // Handles a data: url internally instead of calling the bridge. - void HandleDataUrl(); - - // This is the bridge implemented by the embedder. - // The bridge is kept alive as long as the request is valid and we - // are ready for callbacks. - scoped_ptr<ResourceLoaderBridge> bridge_; - - // The resource loader that owns us - ResourceHandle* job_; - - // This is the object that receives various status messages (such as when the - // loader has received data). See definition for the exact messages that are - // sent to it. - ResourceHandleClient* client_; - - ResourceRequest request_; - - // Runnable Method Factory used to invoke later HandleDataUrl(). - ScopedRunnableMethodFactory<ResourceHandleInternal> data_url_factory_; - - int load_flags_; - - private: - // Set to true when we're waiting for data from the bridge, also indicating - // we have addrefed our job. - bool pending_; - - // Expected content length of the response - long long expected_content_length_; - - // NULL unless we are handling a multipart/x-mixed-replace request - scoped_ptr<MultipartResponseDelegate> multipart_delegate_; - - // NULL unless we are handling a feed:// request. - scoped_ptr<FeedClientProxy> feed_client_proxy_; -}; - -ResourceHandleInternal::ResourceHandleInternal(ResourceHandle* job, - const ResourceRequest& r, - ResourceHandleClient* c) - : job_(job), - client_(c), - request_(r), -MSVC_SUPPRESS_WARNING(4355) // can use this - data_url_factory_(this), - load_flags_(net::LOAD_NORMAL), - pending_(false), - expected_content_length_(-1), - multipart_delegate_(NULL) { -} - -ResourceHandleInternal::~ResourceHandleInternal() { - DCHECK(!pending_); -} - -void ResourceHandleInternal::HandleDataUrl() { - ResourceLoaderBridge::ResponseInfo info; - URLRequestStatus status; - std::string data; - - if (GetInfoFromDataUrl(webkit_glue::KURLToGURL(request_.url()), &info, &data, - &status)) { - OnReceivedResponse(info, false); - - if (data.size()) - OnReceivedData(data.c_str(), data.size()); - } - - OnCompletedRequest(status, info.security_info); - - // We are done using the object. ResourceHandle and ResourceHandleInternal - // might be destroyed now. - job_->deref(); -} - -bool ResourceHandleInternal::Start( - ResourceLoaderBridge::SyncLoadResponse* sync_load_response) { - DCHECK(!bridge_.get()); - - CString method = request_.httpMethod().latin1(); - GURL referrer(webkit_glue::StringToStdString(request_.httpReferrer())); - - // Compute the URL of the load. - GURL url = webkit_glue::KURLToGURL(request_.url()); - if (url.SchemeIs("feed:")) { - // Feed URLs are special, they actually mean "http". - url_canon::Replacements<char> replacements; - replacements.SetScheme("http", url_parse::Component(0, 4)); - url = url.ReplaceComponents(replacements); - - // Replace our client with a client that understands previewing feeds - // and forwards the feeds along to the original client. - feed_client_proxy_.reset(new FeedClientProxy(client_)); - client_ = feed_client_proxy_.get(); - } - - switch (request_.cachePolicy()) { - case ReloadIgnoringCacheData: - // Required by LayoutTests/http/tests/misc/refresh-headers.php - load_flags_ |= net::LOAD_VALIDATE_CACHE; - break; - case ReturnCacheDataElseLoad: - load_flags_ |= net::LOAD_PREFERRING_CACHE; - break; - case ReturnCacheDataDontLoad: - load_flags_ |= net::LOAD_ONLY_FROM_CACHE; - break; - case UseProtocolCachePolicy: - break; - } - - if (request_.reportUploadProgress()) - load_flags_ |= net::LOAD_ENABLE_UPLOAD_PROGRESS; - - // Translate the table of request headers to a formatted string blob - String headerBuf; - const HTTPHeaderMap& headerMap = request_.httpHeaderFields(); - - // In some cases, WebCore doesn't add an Accept header, but not having the - // header confuses some web servers. See bug 808613. - // Note: headerMap uses case-insenstive keys, so this will find Accept as - // as well. - if (!headerMap.contains("accept")) - request_.addHTTPHeaderField("Accept", "*/*"); - - const String crlf("\r\n"); - const String sep(": "); - for (HTTPHeaderMap::const_iterator it = headerMap.begin(); - it != headerMap.end(); ++it) { - // Skip over referrer headers found in the header map because we already - // pulled it out as a separate parameter. We likewise prune the UA since - // that will be added back by the network layer. - if (equalIgnoringCase((*it).first, "referer") || - equalIgnoringCase((*it).first, "user-agent")) - continue; - - // Skip over "Cache-Control: max-age=0" header if the corresponding - // load flag is already specified. FrameLoader sets both the flag and - // the extra header -- the extra header is redundant since our network - // implementation will add the necessary headers based on load flags. - // See http://code.google.com/p/chromium/issues/detail?id=3434. - if ((load_flags_ & net::LOAD_VALIDATE_CACHE) && - equalIgnoringCase((*it).first, "cache-control") && - (*it).second == "max-age=0") - continue; - - if (!headerBuf.isEmpty()) - headerBuf.append(crlf); - headerBuf.append((*it).first + sep + (*it).second); - } - - // TODO(jcampan): in the non out-of-process plugin case the request does not - // have a requestor_pid. Find a better place to set this. - int requestor_pid = request_.requestorProcessID(); - if (requestor_pid == 0) - requestor_pid = base::GetCurrentProcId(); - - if (url.SchemeIs("data")) { - if (sync_load_response) { - // This is a sync load. Do the work now. - sync_load_response->url = url; - std::string data; - GetInfoFromDataUrl(sync_load_response->url, sync_load_response, - &sync_load_response->data, - &sync_load_response->status); - } else { - pending_ = true; - job_->ref(); // to be released when we get a OnCompletedRequest. - job_->ref(); // to be released when HandleDataUrl is completed. - MessageLoop::current()->PostTask(FROM_HERE, - data_url_factory_.NewRunnableMethod( - &ResourceHandleInternal::HandleDataUrl)); - } - return true; - } - - // TODO(abarth): These are wrong! I need to figure out how to get the right - // strings here. See: http://crbug.com/8706 - std::string frame_origin = - webkit_glue::StringToStdString(request_.firstPartyForCookies().string()); - std::string main_frame_origin = - webkit_glue::StringToStdString(request_.firstPartyForCookies().string()); - - // TODO(darin): is latin1 really correct here? It is if the strings are - // already ASCII (i.e., if they are already escaped properly). - // TODO(brettw) this should take parameter encoding into account when - // creating the GURLs. - bridge_.reset(ResourceLoaderBridge::Create( - webkit_glue::CStringToStdString(method), - url, - webkit_glue::KURLToGURL(request_.firstPartyForCookies()), - referrer, - frame_origin, - main_frame_origin, - webkit_glue::CStringToStdString(headerBuf.latin1()), - load_flags_, - requestor_pid, - FromTargetType(request_.targetType()), - request_.appCacheContextID(), - request_.requestorID())); - if (!bridge_.get()) - return false; - - if (request_.httpBody()) { - // GET and HEAD requests shouldn't have http bodies. - DCHECK(method != "GET" && method != "HEAD"); - const Vector<FormDataElement>& elements = request_.httpBody()->elements(); - size_t n = elements.size(); - for (size_t i = 0; i < n; ++i) { - const FormDataElement& e = elements[static_cast<unsigned>(i)]; - if (e.m_type == FormDataElement::data) { - if (e.m_data.size() > 0) { - // WebKit sometimes gives up empty data to append. These aren't - // necessary so we just optimize those out here. - bridge_->AppendDataToUpload(e.m_data.data(), - static_cast<int>(e.m_data.size())); - } - } else { - bridge_->AppendFileToUpload( - FilePath(webkit_glue::StringToFilePathString(e.m_filename))); - } - } - bridge_->SetUploadIdentifier(request_.httpBody()->identifier()); - } - - if (sync_load_response) { - bridge_->SyncLoad(sync_load_response); - return true; - } - - bool rv = bridge_->Start(this); - if (rv) { - pending_ = true; - job_->ref(); // to be released when we get a OnCompletedRequest. - } else { - bridge_.reset(); - } - - return rv; -} - -void ResourceHandleInternal::Cancel() { - // The bridge will still send OnCompletedRequest, which will deref() us, - // so we don't do that here. - if (bridge_.get()) - bridge_->Cancel(); - - // Ensure that we do not notify the multipart delegate anymore as it has - // its own pointer to the client. - multipart_delegate_.reset(); - - // Do not make any further calls to the client. - client_ = NULL; -} - -void ResourceHandleInternal::SetDefersLoading(bool value) { - if (bridge_.get()) - bridge_->SetDefersLoading(value); -} - -// ResourceLoaderBridge::Peer impl -------------------------------------------- - -void ResourceHandleInternal::OnUploadProgress(uint64 position, uint64 size) { - if (client_) - client_->didSendData(job_, position, size); -} - -void ResourceHandleInternal::OnReceivedRedirect(const GURL& new_url) { - DCHECK(pending_); - - KURL url = webkit_glue::GURLToKURL(new_url); - - // TODO(darin): need a way to properly initialize a ResourceResponse - ResourceResponse response(request_.url(), String(), -1, String(), String()); - - ResourceRequest new_request(url); - - // TODO(darin): we need to setup new_request to reflect the fact that we - // for example drop the httpBody when following a POST request that is - // redirected to a GET request. - - if (client_) - client_->willSendRequest(job_, new_request, response); - - // - // TODO(darin): since new_request is sent as a mutable reference, it is - // possible that willSendRequest may expect to be able to modify it. - // - // andresca on #webkit confirms that that is intentional, so we'll need - // to rework the ResourceLoaderBridge to give us control over what URL - // is really loaded (and with what headers) when a redirect is encountered. - // - - request_ = new_request; -} - -void ResourceHandleInternal::OnReceivedResponse( - const ResourceLoaderBridge::ResponseInfo& info, - bool content_filtered) { - DCHECK(pending_); - - // TODO(darin): need a way to properly initialize a ResourceResponse - ResourceResponse response = MakeResourceResponse(request_.url(), info); - response.setIsContentFiltered(content_filtered); - - expected_content_length_ = response.expectedContentLength(); - - if (client_) - client_->didReceiveResponse(job_, response); - - // we may have been cancelled after didReceiveResponse, which would leave us - // without a client and therefore without much need to do multipart handling. - - DCHECK(!multipart_delegate_.get()); - if (client_ && info.headers && response.isMultipart()) { - std::string content_type; - info.headers->EnumerateHeader(NULL, "content-type", &content_type); - - std::string boundary = net::GetHeaderParamValue(content_type, "boundary"); - TrimString(boundary, " \"", &boundary); - // If there's no boundary, just handle the request normally. In the gecko - // code, nsMultiMixedConv::OnStartRequest throws an exception. - if (!boundary.empty()) { - multipart_delegate_.reset(new MultipartResponseDelegate(client_, job_, - response, boundary)); - } - } - - // TODO(darin): generate willCacheResponse callback. debug mac webkit to - // determine when it should be called. -} - -void ResourceHandleInternal::OnReceivedData(const char* data, int data_len) { - DCHECK(pending_); - - if (client_) { - // TODO(darin): figure out what to pass for lengthReceived. from reading - // the loader code, it looks like this is supposed to be the content-length - // value, but it seems really wacky to include that here! we have to debug - // webkit on mac to figure out what this should be. - - // TODO(jackson): didReceiveData expects an int, but an expected content - // length is an int64, so we do our best to fit it inside an int. The only - // code that cares currently about this value is the Inspector, so beware - // that the Inspector's network panel might under-represent the size of - // some resources if they're larger than a gigabyte. - int lengthReceived = static_cast<int>(expected_content_length_); - if (lengthReceived != expected_content_length_) // overflow occurred - lengthReceived = -1; - - if (!multipart_delegate_.get()) { - client_->didReceiveData(job_, data, data_len, lengthReceived); - } else { - // AddData will make the appropriate calls to client_->didReceiveData - // and client_->didReceiveResponse - multipart_delegate_->OnReceivedData(data, data_len); - } - } -} - -void ResourceHandleInternal::OnCompletedRequest( - const URLRequestStatus& status, - const std::string& security_info) { - if (multipart_delegate_.get()) { - multipart_delegate_->OnCompletedRequest(); - multipart_delegate_.reset(NULL); - } - - pending_ = false; - - if (client_) { - if (status.status() != URLRequestStatus::SUCCESS) { - int error_code; - if (status.status() == URLRequestStatus::HANDLED_EXTERNALLY) { - // By marking this request as aborted we insure that we don't navigate - // to an error page. - error_code = net::ERR_ABORTED; - } else { - error_code = status.os_error(); - } - // TODO(tc): fill in these fields properly - ResourceError error(net::kErrorDomain, - error_code, - request_.url().string(), - String() /*localized description*/); - client_->didFail(job_, error); - } else { - client_->didFinishLoading(job_); - } - } - - job_->deref(); // may destroy our owner and hence |this| -} - -std::string ResourceHandleInternal::GetURLForDebugging() { - return webkit_glue::CStringToStdString(request_.url().string().latin1()); -} - -// ResourceHandle ------------------------------------------------------------- - -ResourceHandle::ResourceHandle(const ResourceRequest& request, - ResourceHandleClient* client, - bool defersLoading, - bool shouldContentSniff, - bool mightDownloadFromHandle) -MSVC_SUPPRESS_WARNING(4355) // it's okay to pass |this| here! - : d(new ResourceHandleInternal(this, request, client)) { - // TODO(darin): figure out what to do with the two bool params -} - -PassRefPtr<ResourceHandle> ResourceHandle::create(const ResourceRequest& request, - ResourceHandleClient* client, - Frame* deprecated, - bool defersLoading, - bool shouldContentSniff, - bool mightDownloadFromHandle) { - RefPtr<ResourceHandle> newHandle = - adoptRef(new ResourceHandle(request, client, defersLoading, - shouldContentSniff, mightDownloadFromHandle)); - - if (newHandle->start(NULL)) - return newHandle.release(); - - return NULL; -} - -const ResourceRequest& ResourceHandle::request() const { - return d->request_; -} - -ResourceHandleClient* ResourceHandle::client() const { - return d->client_; -} - -void ResourceHandle::setClient(ResourceHandleClient* client) { - d->client_ = client; -} - -void ResourceHandle::setDefersLoading(bool value) { - d->SetDefersLoading(value); -} - -bool ResourceHandle::start(Frame* deprecated) { - return d->Start(NULL); -} - -void ResourceHandle::clearAuthentication() { - // TODO(darin): do something here. it looks like the ResourceLoader calls - // this method when it is canceled. i have no idea why it does this. -} - -void ResourceHandle::cancel() { - d->Cancel(); -} - -ResourceHandle::~ResourceHandle() { -} - -PassRefPtr<SharedBuffer> ResourceHandle::bufferedData() { - return NULL; -} - -/*static*/ bool ResourceHandle::loadsBlocked() { - return false; // this seems to be related to sync XMLHttpRequest... -} - -/*static*/ bool ResourceHandle::supportsBufferedData() { - return false; // the loader will buffer manually if it needs to -} - -/*static*/ void ResourceHandle::loadResourceSynchronously( - const ResourceRequest& request, StoredCredentials, ResourceError& error, - ResourceResponse& response, Vector<char>& data, Frame*) { - - RefPtr<ResourceHandle> handle = - adoptRef(new ResourceHandle(request, NULL, false, false, false)); - - ResourceLoaderBridge::SyncLoadResponse sync_load_response; - if (!handle->d->Start(&sync_load_response)) { - response = - ResourceResponse(request.url(), String(), 0, String(), String()); - // TODO(darin): what should the error code really be? - error = ResourceError(net::kErrorDomain, - net::ERR_FAILED, - request.url().string(), - String() /* localized description */); - return; - } - - KURL kurl = webkit_glue::GURLToKURL(sync_load_response.url); - - // TODO(tc): For file loads, we may want to include a more descriptive - // status code or status text. - const URLRequestStatus::Status& status = sync_load_response.status.status(); - if (status != URLRequestStatus::SUCCESS && - status != URLRequestStatus::HANDLED_EXTERNALLY) { - response = ResourceResponse(kurl, String(), 0, String(), String()); - error = ResourceError(net::kErrorDomain, - sync_load_response.status.os_error(), - kurl.string(), - String() /* localized description */); - return; - } - - response = MakeResourceResponse(kurl, sync_load_response); - - data.clear(); - data.append(sync_load_response.data.data(), - sync_load_response.data.size()); -} - -// static -bool ResourceHandle::willLoadFromCache(ResourceRequest& request) { - // - // This method is used to determine if a POST request can be repeated from - // cache, but you cannot really know until you actually try to read from the - // cache. Even if we checked now, something else could come along and wipe - // out the cache entry by the time we fetch it. - // - // So, we always say yes here, which allows us to generate an ERR_CACHE_MISS - // if the request cannot be serviced from cache. We force the 'DontLoad' - // cache policy at this point to ensure that we never hit the network for - // this request. - // - DCHECK(request.httpMethod() == "POST"); - request.setCachePolicy(ReturnCacheDataDontLoad); - return true; -} - -} // namespace WebCore diff --git a/webkit/glue/webkitclient_impl.cc b/webkit/glue/webkitclient_impl.cc index e075686..91152f4 100644 --- a/webkit/glue/webkitclient_impl.cc +++ b/webkit/glue/webkitclient_impl.cc @@ -14,10 +14,12 @@ #include "webkit/api/public/WebString.h" #include "webkit/glue/webkit_glue.h" #include "webkit/glue/webplugininfo.h" +#include "webkit/glue/weburlloader_impl.h" using WebKit::WebData; using WebKit::WebPluginListBuilder; using WebKit::WebThemeEngine; +using WebKit::WebURLLoader; namespace webkit_glue { @@ -34,6 +36,10 @@ WebThemeEngine* WebKitClientImpl::themeEngine() { #endif } +WebURLLoader* WebKitClientImpl::createURLLoader() { + return new WebURLLoaderImpl(); +} + void WebKitClientImpl::getPluginList(bool refresh, WebPluginListBuilder* builder) { std::vector<WebPluginInfo> plugins; diff --git a/webkit/glue/webkitclient_impl.h b/webkit/glue/webkitclient_impl.h index 679cb61..54f691c 100644 --- a/webkit/glue/webkitclient_impl.h +++ b/webkit/glue/webkitclient_impl.h @@ -21,6 +21,7 @@ class WebKitClientImpl : public WebKit::WebKitClient { // WebKitClient methods (partial implementation): virtual WebKit::WebThemeEngine* themeEngine(); + virtual WebKit::WebURLLoader* createURLLoader(); virtual void getPluginList(bool refresh, WebKit::WebPluginListBuilder*); virtual void decrementStatsCounter(const char* name); virtual void incrementStatsCounter(const char* name); diff --git a/webkit/glue/webplugin_impl.cc b/webkit/glue/webplugin_impl.cc index 0441000..e783c0d 100644 --- a/webkit/glue/webplugin_impl.cc +++ b/webkit/glue/webplugin_impl.cc @@ -3,7 +3,6 @@ // found in the LICENSE file. #include "config.h" -#include "webkit/glue/webplugin_impl.h" #include "Cursor.h" #include "Document.h" @@ -49,44 +48,66 @@ #include "base/string_util.h" #include "base/sys_string_conversions.h" #include "net/base/escape.h" +#include "webkit/api/public/WebData.h" +#include "webkit/api/public/WebHTTPBody.h" #include "webkit/api/public/WebInputEvent.h" #include "webkit/api/public/WebKit.h" #include "webkit/api/public/WebKitClient.h" #include "webkit/api/public/WebString.h" #include "webkit/api/public/WebURL.h" +#include "webkit/api/public/WebURLLoader.h" +#include "webkit/api/public/WebURLLoaderClient.h" +#include "webkit/api/public/WebURLResponse.h" #include "webkit/glue/chrome_client_impl.h" #include "webkit/glue/event_conversion.h" #include "webkit/glue/glue_util.h" #include "webkit/glue/multipart_response_delegate.h" #include "webkit/glue/webcursor.h" #include "webkit/glue/webkit_glue.h" +#include "webkit/glue/webplugin_impl.h" #include "webkit/glue/plugins/plugin_host.h" #include "webkit/glue/plugins/plugin_instance.h" #include "webkit/glue/stacking_order_iterator.h" #include "webkit/glue/webview_impl.h" #include "googleurl/src/gurl.h" -using WebKit::WebKeyboardEvent; +using WebKit::WebData; +using WebKit::WebHTTPBody; using WebKit::WebInputEvent; +using WebKit::WebKeyboardEvent; using WebKit::WebMouseEvent; +using WebKit::WebString; +using WebKit::WebURLError; +using WebKit::WebURLLoader; +using WebKit::WebURLLoaderClient; +using WebKit::WebURLRequest; +using WebKit::WebURLResponse; +using webkit_glue::MultipartResponseDelegate; // This class handles individual multipart responses. It is instantiated when // we receive HTTP status code 206 in the HTTP response. This indicates // that the response could have multiple parts each separated by a boundary // specified in the response header. -class MultiPartResponseClient : public WebCore::ResourceHandleClient { +class MultiPartResponseClient : public WebURLLoaderClient { public: MultiPartResponseClient(WebPluginResourceClient* resource_client) : resource_client_(resource_client) { Clear(); } + virtual void willSendRequest( + WebURLLoader*, WebURLRequest&, const WebURLResponse&) {} + virtual void didSendData( + WebURLLoader*, unsigned long long, unsigned long long) {} + // Called when the multipart parser encounters an embedded multipart // response. - virtual void didReceiveResponse(WebCore::ResourceHandle* handle, - const WebCore::ResourceResponse& response) { + virtual void didReceiveResponse( + WebURLLoader*, const WebURLResponse& response) { if (!MultipartResponseDelegate::ReadContentRanges( - response, &byte_range_lower_bound_, &byte_range_upper_bound_)) { + response, + &byte_range_lower_bound_, + &byte_range_upper_bound_)) { NOTREACHED(); return; } @@ -95,21 +116,23 @@ class MultiPartResponseClient : public WebCore::ResourceHandleClient { } // Receives individual part data from a multipart response. - virtual void didReceiveData(WebCore::ResourceHandle* handle, - const char* data, int data_size, - int reserved) { + virtual void didReceiveData( + WebURLLoader*, const char* data, int data_size, long long) { resource_client_->DidReceiveData( data, data_size, byte_range_lower_bound_); } + virtual void didFinishLoading(WebURLLoader*) {} + virtual void didFail(WebURLLoader*, const WebURLError&) {} + void Clear() { - resource_response_ = WebCore::ResourceResponse(); + resource_response_.reset(); byte_range_lower_bound_ = 0; byte_range_upper_bound_ = 0; } private: - WebCore::ResourceResponse resource_response_; + WebURLResponse resource_response_; // The lower bound of the byte range. int byte_range_lower_bound_; // The upper bound of the byte range. @@ -118,6 +141,32 @@ class MultiPartResponseClient : public WebCore::ResourceHandleClient { WebPluginResourceClient* resource_client_; }; +static std::wstring GetAllHeaders(const WebCore::ResourceResponse& response) { + std::wstring result; + const WebCore::String& status = response.httpStatusText(); + if (status.isEmpty()) + return result; + + result.append(L"HTTP "); + result.append(FormatNumber(response.httpStatusCode())); + result.append(L" "); + result.append(webkit_glue::StringToStdWString(status)); + result.append(L"\n"); + + WebCore::HTTPHeaderMap::const_iterator it = + response.httpHeaderFields().begin(); + for (; it != response.httpHeaderFields().end(); ++it) { + if (!it->first.isEmpty() && !it->second.isEmpty()) { + result.append(webkit_glue::StringToStdWString(it->first)); + result.append(L": "); + result.append(webkit_glue::StringToStdWString(it->second)); + result.append(L"\n"); + } + } + + return result; +} + WebPluginContainer::WebPluginContainer(WebPluginImpl* impl) : impl_(impl), ignore_response_error_(false) { @@ -254,7 +303,7 @@ void WebPluginContainer::didReceiveResponse( impl_->delegate_->DidReceiveManualResponse( http_response_info.url, base::SysWideToNativeMB(http_response_info.mime_type), - base::SysWideToNativeMB(impl_->GetAllHeaders(response)), + base::SysWideToNativeMB(GetAllHeaders(response)), http_response_info.expected_length, http_response_info.last_modified); } @@ -415,17 +464,16 @@ bool WebPluginImpl::ExecuteScript(const std::string& url, void WebPluginImpl::CancelResource(int id) { for (size_t i = 0; i < clients_.size(); ++i) { if (clients_[i].id == id) { - if (clients_[i].handle) { - clients_[i].handle->cancel(); + if (clients_[i].loader.get()) { + clients_[i].loader->cancel(); RemoveClient(i); } - return; } } } -bool WebPluginImpl::SetPostData(WebCore::ResourceRequest* request, +bool WebPluginImpl::SetPostData(WebURLRequest* request, const char *buf, uint32 length) { std::vector<std::string> names; @@ -433,19 +481,26 @@ bool WebPluginImpl::SetPostData(WebCore::ResourceRequest* request, std::vector<char> body; bool rv = NPAPI::PluginHost::SetPostData(buf, length, &names, &values, &body); - for (size_t i = 0; i < names.size(); ++i) - request->addHTTPHeaderField(webkit_glue::StdStringToString(names[i]), - webkit_glue::StdStringToString(values[i])); - - WebCore::String content_type = request->httpContentType(); - if (content_type.isEmpty()) - request->setHTTPContentType("application/x-www-form-urlencoded"); + for (size_t i = 0; i < names.size(); ++i) { + request->addHTTPHeaderField(webkit_glue::StdStringToWebString(names[i]), + webkit_glue::StdStringToWebString(values[i])); + } - RefPtr<WebCore::FormData> data = WebCore::FormData::create(); - if (body.size()) - data->appendData(&body.front(), body.size()); + WebString content_type_header = WebString::fromUTF8("Content-Type"); + const WebString& content_type = + request->httpHeaderField(content_type_header); + if (content_type.isEmpty()) { + request->setHTTPHeaderField( + content_type_header, + WebString::fromUTF8("application/x-www-form-urlencoded")); + } - request->setHTTPBody(data.release()); + WebHTTPBody http_body; + if (body.size()) { + http_body.initialize(); + http_body.appendData(WebData(&body[0], body.size())); + } + request->setHTTPBody(http_body); return rv; } @@ -497,8 +552,8 @@ RoutingStatus WebPluginImpl::RouteToFrame(const char *method, } *completeURL = webkit_glue::KURLToGURL(complete_url_kurl); - WebCore::ResourceRequest request(complete_url_kurl); - request.setHTTPMethod(method); + WebURLRequest request(webkit_glue::KURLToWebURL(complete_url_kurl)); + request.setHTTPMethod(WebString::fromUTF8(method)); if (len > 0) { if (!is_file_data) { if (!SetPostData(&request, buf, len)) { @@ -514,7 +569,8 @@ RoutingStatus WebPluginImpl::RouteToFrame(const char *method, return ROUTED; } } - WebCore::FrameLoadRequest load_request(request); + WebCore::FrameLoadRequest load_request( + *webkit_glue::WebURLRequestToResourceRequest(&request)); load_request.setFrameName(str_target); WebCore::FrameLoader *loader = frame()->loader(); // we actually don't know whether usergesture is true or false, @@ -829,10 +885,10 @@ NPObject* WebPluginImpl::GetPluginScriptableObject() { return delegate_->GetPluginScriptableObject(); } -WebPluginResourceClient* WebPluginImpl::GetClientFromHandle( - WebCore::ResourceHandle* handle) { +WebPluginResourceClient* WebPluginImpl::GetClientFromLoader( + WebURLLoader* loader) { for (size_t i = 0; i < clients_.size(); ++i) { - if (clients_[i].handle.get() == handle) + if (clients_[i].loader.get() == loader) return clients_[i].client; } @@ -841,54 +897,34 @@ WebPluginResourceClient* WebPluginImpl::GetClientFromHandle( } -void WebPluginImpl::willSendRequest(WebCore::ResourceHandle* handle, - WebCore::ResourceRequest& request, - const WebCore::ResourceResponse&) { - WebPluginResourceClient* client = GetClientFromHandle(handle); - if (client) { - GURL gurl(webkit_glue::KURLToGURL(request.url())); - client->WillSendRequest(gurl); - } +void WebPluginImpl::willSendRequest(WebURLLoader* loader, + WebURLRequest& request, + const WebURLResponse&) { + WebPluginResourceClient* client = GetClientFromLoader(loader); + if (client) + client->WillSendRequest(request.url()); } -std::wstring WebPluginImpl::GetAllHeaders( - const WebCore::ResourceResponse& response) { - std::wstring result; - const WebCore::String& status = response.httpStatusText(); - if (status.isEmpty()) - return result; - - result.append(L"HTTP "); - result.append(FormatNumber(response.httpStatusCode())); - result.append(L" "); - result.append(webkit_glue::StringToStdWString(status)); - result.append(L"\n"); - - WebCore::HTTPHeaderMap::const_iterator it = - response.httpHeaderFields().begin(); - for (; it != response.httpHeaderFields().end(); ++it) { - if (!it->first.isEmpty() && !it->second.isEmpty()) { - result.append(webkit_glue::StringToStdWString(it->first)); - result.append(L": "); - result.append(webkit_glue::StringToStdWString(it->second)); - result.append(L"\n"); - } - } - - return result; +void WebPluginImpl::didSendData(WebURLLoader* loader, + unsigned long long bytes_sent, + unsigned long long total_bytes_to_be_sent) { } -void WebPluginImpl::didReceiveResponse(WebCore::ResourceHandle* handle, - const WebCore::ResourceResponse& response) { +void WebPluginImpl::didReceiveResponse(WebURLLoader* loader, + const WebURLResponse& response) { static const int kHttpPartialResponseStatusCode = 206; static const int kHttpResponseSuccessStatusCode = 200; - WebPluginResourceClient* client = GetClientFromHandle(handle); + WebPluginResourceClient* client = GetClientFromLoader(loader); if (!client) return; + + const WebCore::ResourceResponse& resource_response = + *webkit_glue::WebURLResponseToResourceResponse(&response); WebPluginContainer::HttpResponseInfo http_response_info; - WebPluginContainer::ReadHttpResponseInfo(response, &http_response_info); + WebPluginContainer::ReadHttpResponseInfo(resource_response, + &http_response_info); bool cancel = false; bool request_is_seekable = true; @@ -906,7 +942,7 @@ void WebPluginImpl::didReceiveResponse(WebCore::ResourceHandle* handle, // continue to remain valid. // 2. Create a new plugin instance and notify it about the response // received here. - if (!ReinitializePluginForResponse(handle)) { + if (!ReinitializePluginForResponse(loader)) { NOTREACHED(); return; } @@ -920,7 +956,7 @@ void WebPluginImpl::didReceiveResponse(WebCore::ResourceHandle* handle, // Create a new resource client for this request. for (size_t i = 0; i < clients_.size(); ++i) { - if (clients_[i].handle.get() == handle) { + if (clients_[i].loader.get() == loader) { WebPluginResourceClient* resource_client = delegate_->CreateResourceClient(clients_[i].id, plugin_url_.spec().c_str(), @@ -937,13 +973,13 @@ void WebPluginImpl::didReceiveResponse(WebCore::ResourceHandle* handle, client->DidReceiveResponse( base::SysWideToNativeMB(http_response_info.mime_type), - base::SysWideToNativeMB(GetAllHeaders(response)), + base::SysWideToNativeMB(GetAllHeaders(resource_response)), http_response_info.expected_length, http_response_info.last_modified, request_is_seekable, &cancel); if (cancel) { - handle->cancel(); - RemoveClient(handle); + loader->cancel(); + RemoveClient(loader); return; } @@ -952,41 +988,41 @@ void WebPluginImpl::didReceiveResponse(WebCore::ResourceHandle* handle, // fate of the HTTP requests issued via NPN_GetURLNotify. Webkit and FF // destroy the stream and invoke the NPP_DestroyStream function on the // plugin if the HTTP request fails. - const WebCore::String& protocol_scheme = response.url().protocol(); - if ((protocol_scheme == "http") || (protocol_scheme == "https")) { + const GURL& url = response.url(); + if (url.SchemeIs("http") || url.SchemeIs("https")) { if (response.httpStatusCode() < 100 || response.httpStatusCode() >= 400) { // The plugin instance could be in the process of deletion here. // Verify if the WebPluginResourceClient instance still exists before // use. - WebPluginResourceClient* resource_client = GetClientFromHandle(handle); + WebPluginResourceClient* resource_client = GetClientFromLoader(loader); if (resource_client) { - handle->cancel(); + loader->cancel(); resource_client->DidFail(); - RemoveClient(handle); + RemoveClient(loader); } } } } -void WebPluginImpl::didReceiveData(WebCore::ResourceHandle* handle, +void WebPluginImpl::didReceiveData(WebURLLoader* loader, const char *buffer, - int length, int) { - WebPluginResourceClient* client = GetClientFromHandle(handle); - if (client) { - MultiPartResponseHandlerMap::iterator index = - multi_part_response_map_.find(client); - if (index != multi_part_response_map_.end()) { - MultipartResponseDelegate* multi_part_handler = (*index).second; - DCHECK(multi_part_handler != NULL); - multi_part_handler->OnReceivedData(buffer, length); - } else { - client->DidReceiveData(buffer, length, 0); - } + int length, long long) { + WebPluginResourceClient* client = GetClientFromLoader(loader); + if (!client) + return; + MultiPartResponseHandlerMap::iterator index = + multi_part_response_map_.find(client); + if (index != multi_part_response_map_.end()) { + MultipartResponseDelegate* multi_part_handler = (*index).second; + DCHECK(multi_part_handler != NULL); + multi_part_handler->OnReceivedData(buffer, length); + } else { + client->DidReceiveData(buffer, length, 0); } } -void WebPluginImpl::didFinishLoading(WebCore::ResourceHandle* handle) { - WebPluginResourceClient* client = GetClientFromHandle(handle); +void WebPluginImpl::didFinishLoading(WebURLLoader* loader) { + WebPluginResourceClient* client = GetClientFromLoader(loader); if (client) { MultiPartResponseHandlerMap::iterator index = multi_part_response_map_.find(client); @@ -1000,25 +1036,25 @@ void WebPluginImpl::didFinishLoading(WebCore::ResourceHandle* handle) { client->DidFinishLoading(); } - RemoveClient(handle); + RemoveClient(loader); } -void WebPluginImpl::didFail(WebCore::ResourceHandle* handle, - const WebCore::ResourceError&) { - WebPluginResourceClient* client = GetClientFromHandle(handle); +void WebPluginImpl::didFail(WebURLLoader* loader, + const WebURLError&) { + WebPluginResourceClient* client = GetClientFromLoader(loader); if (client) client->DidFail(); - RemoveClient(handle); + RemoveClient(loader); } void WebPluginImpl::RemoveClient(size_t i) { clients_.erase(clients_.begin() + i); } -void WebPluginImpl::RemoveClient(WebCore::ResourceHandle* handle) { +void WebPluginImpl::RemoveClient(WebURLLoader* loader) { for (size_t i = 0; i < clients_.size(); ++i) { - if (clients_[i].handle.get() == handle) { + if (clients_[i].loader.get() == loader) { RemoveClient(i); return; } @@ -1150,18 +1186,19 @@ bool WebPluginImpl::InitiateHTTPRequest(int resource_id, return false; } - WebCore::KURL kurl = webkit_glue::GURLToKURL(url); - ClientInfo info; info.id = resource_id; info.client = client; - info.request.setURL(kurl); + info.request.initialize(); + info.request.setURL(url); info.request.setRequestorProcessID(delegate_->GetProcessId()); - info.request.setTargetType(WebCore::ResourceRequest::TargetIsObject); - info.request.setHTTPMethod(method); + info.request.setTargetType(WebURLRequest::TargetIsObject); + info.request.setHTTPMethod(WebString::fromUTF8(method)); - if (range_info) - info.request.addHTTPHeaderField("Range", range_info); + if (range_info) { + info.request.addHTTPHeaderField(WebString::fromUTF8("Range"), + WebString::fromUTF8(range_info)); + } WebCore::String referrer; // GetURL/PostURL requests initiated explicitly by plugins should specify the @@ -1172,8 +1209,11 @@ bool WebPluginImpl::InitiateHTTPRequest(int resource_id, referrer = frame()->loader()->outgoingReferrer(); } - if (!WebCore::FrameLoader::shouldHideReferrer(kurl, referrer)) - info.request.setHTTPReferrer(referrer); + if (!WebCore::FrameLoader::shouldHideReferrer(webkit_glue::GURLToKURL(url), + referrer)) { + info.request.setHTTPHeaderField(WebString::fromUTF8("Referer"), + webkit_glue::StringToWebString(referrer)); + } if (strcmp(method, "POST") == 0) { // Adds headers or form data to a request. This must be called before @@ -1184,13 +1224,15 @@ bool WebPluginImpl::InitiateHTTPRequest(int resource_id, // Sets the routing id to associate the ResourceRequest with the RenderView. WebCore::ResourceResponse response; frame()->loader()->client()->dispatchWillSendRequest( - NULL, 0, info.request, response); + NULL, + 0, + *webkit_glue::WebURLRequestToMutableResourceRequest(&info.request), + response); - info.handle = WebCore::ResourceHandle::create( - info.request, this, NULL, false, false); - if (!info.handle) { + info.loader.reset(WebKit::webKitClient()->createURLLoader()); + if (!info.loader.get()) return false; - } + info.loader->loadAsynchronously(info.request, this); clients_.push_back(info); return true; @@ -1221,7 +1263,7 @@ void WebPluginImpl::InitiateHTTPRangeRequest(const char* url, } void WebPluginImpl::HandleHttpMultipartResponse( - const WebCore::ResourceResponse& response, + const WebURLResponse& response, WebPluginResourceClient* client) { std::string multipart_boundary; if (!MultipartResponseDelegate::ReadMultipartBoundary( @@ -1244,7 +1286,7 @@ void WebPluginImpl::HandleHttpMultipartResponse( } bool WebPluginImpl::ReinitializePluginForResponse( - WebCore::ResourceHandle* response_handle) { + WebURLLoader* loader) { WebFrameImpl* web_frame = WebFrameImpl::FromFrame(frame()); if (!web_frame) return false; @@ -1256,7 +1298,7 @@ bool WebPluginImpl::ReinitializePluginForResponse( WebPluginContainer* container_widget = widget_; // Destroy the current plugin instance. - TearDownPluginInstance(response_handle); + TearDownPluginInstance(loader); widget_ = container_widget; webframe_ = web_frame; @@ -1310,7 +1352,7 @@ void WebPluginImpl::ArrayToVector(int total_values, char** values, } void WebPluginImpl::TearDownPluginInstance( - WebCore::ResourceHandle* response_handle_to_ignore) { + WebURLLoader* loader_to_ignore) { // The frame maintains a list of JSObjects which are related to this // plugin. Tell the frame we're gone so that it can invalidate all // of those sub JSObjects. @@ -1332,13 +1374,13 @@ void WebPluginImpl::TearDownPluginInstance( while (client_index != clients_.end()) { ClientInfo& client_info = *client_index; - if (response_handle_to_ignore == client_info.handle) { + if (loader_to_ignore == client_info.loader) { client_index++; continue; } - if (client_info.handle) - client_info.handle->cancel(); + if (client_info.loader.get()) + client_info.loader->cancel(); WebPluginResourceClient* resource_client = client_info.client; client_index = clients_.erase(client_index); diff --git a/webkit/glue/webplugin_impl.h b/webkit/glue/webplugin_impl.h index 8d14792..1c3be91 100644 --- a/webkit/glue/webplugin_impl.h +++ b/webkit/glue/webplugin_impl.h @@ -9,41 +9,43 @@ #include <map> #include <vector> -#include "config.h" -#include "base/compiler_specific.h" -#include "base/gfx/native_widget_types.h" - -MSVC_PUSH_WARNING_LEVEL(0); -#include "ResourceHandle.h" -#include "ResourceHandleClient.h" -#include "ResourceRequest.h" #include "Widget.h" -MSVC_POP_WARNING(); #include "base/basictypes.h" +#include "base/gfx/native_widget_types.h" +#include "base/linked_ptr.h" +#include "webkit/api/public/WebURLLoaderClient.h" +#include "webkit/api/public/WebURLRequest.h" #include "webkit/glue/webframe_impl.h" #include "webkit/glue/webplugin.h" #include "webkit/glue/webplugin_delegate.h" + class WebFrameImpl; class WebPluginDelegate; class WebPluginImpl; -class MultipartResponseDelegate; namespace WebCore { - class Event; - class Frame; - class HTMLPlugInElement; - class IntRect; - class KeyboardEvent; - class KURL; - class MouseEvent; - class ResourceHandle; - class ResourceError; - class ResourceResponse; - class ScrollView; - class String; - class Widget; +class Event; +class Frame; +class HTMLPlugInElement; +class IntRect; +class KeyboardEvent; +class KURL; +class MouseEvent; +class ResourceError; +class ResourceResponse; +class ScrollView; +class String; +class Widget; +} + +namespace WebKit { +class WebURLResponse; +} + +namespace webkit_glue { +class MultipartResponseDelegate; } // Implements WebCore::Widget functions that WebPluginImpl needs. This class @@ -115,7 +117,7 @@ class WebPluginContainer : public WebCore::Widget { // after changing out of WebCore types, to a delegate. The delegate will // be in a different process. class WebPluginImpl : public WebPlugin, - public WebCore::ResourceHandleClient { + public WebKit::WebURLLoaderClient { public: // Creates a WebPlugin instance, as long as the delegate's initialization // succeeds. If it fails, the delegate is deleted and NULL is returned. @@ -134,7 +136,7 @@ class WebPluginImpl : public WebPlugin, virtual NPObject* GetPluginScriptableObject(); // Helper function for sorting post data. - static bool SetPostData(WebCore::ResourceRequest* request, + static bool SetPostData(WebKit::WebURLRequest* request, const char* buf, uint32 length); @@ -240,27 +242,28 @@ class WebPluginImpl : public WebPlugin, // Destroys the plugin instance. // The response_handle_to_ignore parameter if not NULL indicates the // resource handle to be left valid during plugin shutdown. - void TearDownPluginInstance( - WebCore::ResourceHandle* response_handle_to_ignore); + void TearDownPluginInstance(WebKit::WebURLLoader* loader_to_ignore); WebCore::ScrollView* parent() const; - // ResourceHandleClient implementation. We implement this interface in the + // WebURLLoaderClient implementation. We implement this interface in the // renderer process, and then use the simple WebPluginResourceClient interface // to relay the callbacks to the plugin. - void willSendRequest(WebCore::ResourceHandle* handle, - WebCore::ResourceRequest& request, - const WebCore::ResourceResponse&); - - void didReceiveResponse(WebCore::ResourceHandle* handle, - const WebCore::ResourceResponse& response); - void didReceiveData(WebCore::ResourceHandle* handle, const char *buffer, - int length, int); - void didFinishLoading(WebCore::ResourceHandle* handle); - void didFail(WebCore::ResourceHandle* handle, const WebCore::ResourceError&); + virtual void willSendRequest(WebKit::WebURLLoader* loader, + WebKit::WebURLRequest& request, + const WebKit::WebURLResponse&); + virtual void didSendData(WebKit::WebURLLoader* loader, + unsigned long long bytes_sent, + unsigned long long total_bytes_to_be_sent); + virtual void didReceiveResponse(WebKit::WebURLLoader* loader, + const WebKit::WebURLResponse& response); + virtual void didReceiveData(WebKit::WebURLLoader* loader, const char *buffer, + int length, long long total_length); + virtual void didFinishLoading(WebKit::WebURLLoader* loader); + virtual void didFail(WebKit::WebURLLoader* loader, const WebKit::WebURLError&); // Helper function - WebPluginResourceClient* GetClientFromHandle(WebCore::ResourceHandle* handle); + WebPluginResourceClient* GetClientFromLoader(WebKit::WebURLLoader* loader); // Helper function to remove the stored information about a resource // request given its index in m_clients. @@ -268,10 +271,7 @@ class WebPluginImpl : public WebPlugin, // Helper function to remove the stored information about a resource // request given a handle. - void RemoveClient(WebCore::ResourceHandle* handle); - - // Returns all the response headers in one string, including the status code. - std::wstring GetAllHeaders(const WebCore::ResourceResponse& response); + void RemoveClient(WebKit::WebURLLoader* loader); WebCore::Frame* frame() { return webframe_ ? webframe_->frame() : NULL; } @@ -300,7 +300,7 @@ class WebPluginImpl : public WebPlugin, // Handles HTTP multipart responses, i.e. responses received with a HTTP // status code of 206. - void HandleHttpMultipartResponse(const WebCore::ResourceResponse& response, + void HandleHttpMultipartResponse(const WebKit::WebURLResponse& response, WebPluginResourceClient* client); void HandleURLRequestInternal(const char *method, bool is_javascript_url, @@ -311,8 +311,8 @@ class WebPluginImpl : public WebPlugin, bool use_plugin_src_as_referrer); // Tears down the existing plugin instance and creates a new plugin instance - // to handle the response identified by the response_handle parameter. - bool ReinitializePluginForResponse(WebCore::ResourceHandle* response_handle); + // to handle the response identified by the loader parameter. + bool ReinitializePluginForResponse(WebKit::WebURLLoader* loader); // Helper functions to convert an array of names/values to a vector. static void ArrayToVector(int total_values, char** values, @@ -321,8 +321,8 @@ class WebPluginImpl : public WebPlugin, struct ClientInfo { int id; WebPluginResourceClient* client; - WebCore::ResourceRequest request; - RefPtr<WebCore::ResourceHandle> handle; + WebKit::WebURLRequest request; + linked_ptr<WebKit::WebURLLoader> loader; }; std::vector<ClientInfo> clients_; @@ -336,7 +336,8 @@ class WebPluginImpl : public WebPlugin, WebPluginContainer* widget_; - typedef std::map<WebPluginResourceClient*, MultipartResponseDelegate*> + typedef std::map<WebPluginResourceClient*, + webkit_glue::MultipartResponseDelegate*> MultiPartResponseHandlerMap; // Tracks HTTP multipart response handlers instantiated for // a WebPluginResourceClient instance. diff --git a/webkit/glue/webplugin_impl_unittest.cc b/webkit/glue/webplugin_impl_unittest.cc index b518361..b6c62f6 100644 --- a/webkit/glue/webplugin_impl_unittest.cc +++ b/webkit/glue/webplugin_impl_unittest.cc @@ -4,18 +4,21 @@ #include "config.h" -#include "testing/gtest/include/gtest/gtest.h" - -#include "base/compiler_specific.h" - -MSVC_PUSH_WARNING_LEVEL(0); -#include "ResourceRequest.h" -#include "CString.h" -MSVC_POP_WARNING(); +// Avoid collisions with the LOG macro +#include <wtf/Assertions.h> #undef LOG +#include "base/string_util.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "webkit/api/public/WebString.h" +#include "webkit/api/public/WebURLRequest.h" +#include "webkit/glue/glue_util.h" #include "webkit/glue/webplugin_impl.h" +using WebKit::WebHTTPBody; +using WebKit::WebString; +using WebKit::WebURLRequest; + namespace { class WebPluginImplTest : public testing::Test { @@ -30,6 +33,34 @@ std::ostream& operator<<(std::ostream& out, const WebCore::String& str) return out << str.latin1().data(); } +static std::string GetHeader(const WebURLRequest& request, const char* name) { + std::string result; + TrimWhitespace( + webkit_glue::WebStringToStdString( + request.httpHeaderField(WebString::fromUTF8(name))), + TRIM_ALL, + &result); + return result; +} + +static std::string GetBodyText(const WebURLRequest& request) { + const WebHTTPBody& body = request.httpBody(); + if (body.isNull()) + return std::string(); + + std::string result; + size_t i = 0; + WebHTTPBody::Element element; + while (body.elementAt(i++, element)) { + if (element.type == WebHTTPBody::Element::TypeData) { + result.append(element.data.data(), element.data.size()); + } else { + NOTREACHED() << "unexpected element type encountered!"; + } + } + return result; +} + // The Host functions for NPN_PostURL and NPN_PostURLNotify // need to parse out some HTTP headers. Make sure it works // with the following tests @@ -37,46 +68,47 @@ std::ostream& operator<<(std::ostream& out, const WebCore::String& str) TEST(WebPluginImplTest, PostParserSimple) { // Test a simple case with headers & data const char *ex1 = "foo: bar\nContent-length: 10\n\nabcdefghij"; - WebCore::ResourceRequest request; + WebURLRequest request; + request.initialize(); bool rv = WebPluginImpl::SetPostData(&request, ex1, static_cast<uint32>(strlen(ex1))); EXPECT_EQ(true, rv); - EXPECT_EQ("bar", request.httpHeaderField("foo").stripWhiteSpace()); - EXPECT_EQ(0U, request.httpHeaderField("bar").length()); - EXPECT_EQ(0U, request.httpHeaderField("Content-length").length()); - EXPECT_EQ("abcdefghij", request.httpBody()->flattenToString()); + EXPECT_EQ("bar", GetHeader(request, "foo")); + EXPECT_EQ(0U, GetHeader(request, "bar").length()); + EXPECT_EQ(0U, GetHeader(request, "Content-length").length()); + EXPECT_EQ("abcdefghij", GetBodyText(request)); } TEST(WebPluginImplTest, PostParserLongHeader) { // Test a simple case with long headers const char *ex1 = "foo: 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\n\nabcdefghij"; - WebCore::ResourceRequest request; + WebURLRequest request; + request.initialize(); bool rv = WebPluginImpl::SetPostData(&request, ex1, static_cast<uint32>(strlen(ex1))); EXPECT_EQ(true, rv); - EXPECT_EQ(100U, request.httpHeaderField("foo").stripWhiteSpace().length()); + EXPECT_EQ(100U, GetHeader(request, "foo").length()); } TEST(WebPluginImplTest, PostParserManyHeaders) { // Test a simple case with long headers const char *ex1 = "h1:h1\nh2:h2\nh3:h3\nh4:h4\nh5:h5\nh6:h6\nh7:h7\nh8:h8\nh9:h9\nh10:h10\n\nbody"; - WebCore::ResourceRequest request; + WebURLRequest request; + request.initialize(); bool rv = WebPluginImpl::SetPostData(&request, ex1, static_cast<uint32>(strlen(ex1))); EXPECT_EQ(true, rv); - EXPECT_EQ("h1", request.httpHeaderField("h1").stripWhiteSpace()); - EXPECT_EQ("h2", request.httpHeaderField("h2").stripWhiteSpace()); - EXPECT_EQ("h3", request.httpHeaderField("h3").stripWhiteSpace()); - EXPECT_EQ("h4", request.httpHeaderField("h4").stripWhiteSpace()); - EXPECT_EQ("h5", request.httpHeaderField("h5").stripWhiteSpace()); - EXPECT_EQ("h6", request.httpHeaderField("h6").stripWhiteSpace()); - EXPECT_EQ("h7", request.httpHeaderField("h7").stripWhiteSpace()); - EXPECT_EQ("h8", request.httpHeaderField("h8").stripWhiteSpace()); - EXPECT_EQ("h9", request.httpHeaderField("h9").stripWhiteSpace()); - EXPECT_EQ("h10", request.httpHeaderField("h10").stripWhiteSpace()); - WebCore::FormData *form_data = request.httpBody(); - WebCore::String string_data = form_data->flattenToString(); - EXPECT_EQ(string_data, "body"); + EXPECT_EQ("h1", GetHeader(request, "h1")); + EXPECT_EQ("h2", GetHeader(request, "h2")); + EXPECT_EQ("h3", GetHeader(request, "h3")); + EXPECT_EQ("h4", GetHeader(request, "h4")); + EXPECT_EQ("h5", GetHeader(request, "h5")); + EXPECT_EQ("h6", GetHeader(request, "h6")); + EXPECT_EQ("h7", GetHeader(request, "h7")); + EXPECT_EQ("h8", GetHeader(request, "h8")); + EXPECT_EQ("h9", GetHeader(request, "h9")); + EXPECT_EQ("h10", GetHeader(request, "h10")); + EXPECT_EQ("body", GetBodyText(request)); } TEST(WebPluginImplTest, PostParserDuplicateHeaders) { @@ -84,7 +116,8 @@ TEST(WebPluginImplTest, PostParserDuplicateHeaders) { // What value gets returned doesn't really matter. It shouldn't error // out. const char *ex1 = "h1:h1\nh1:h2\n\nbody"; - WebCore::ResourceRequest request; + WebURLRequest request; + request.initialize(); bool rv = WebPluginImpl::SetPostData(&request, ex1, static_cast<uint32>(strlen(ex1))); EXPECT_EQ(true, rv); @@ -93,43 +126,47 @@ TEST(WebPluginImplTest, PostParserDuplicateHeaders) { TEST(WebPluginImplTest, PostParserNoHeaders) { // Test a simple case with no headers but with data const char *ex1 = "\nabcdefghij"; - WebCore::ResourceRequest request; + WebURLRequest request; + request.initialize(); bool rv = WebPluginImpl::SetPostData(&request, ex1, static_cast<uint32>(strlen(ex1))); EXPECT_EQ(true, rv); - EXPECT_EQ(0U, request.httpHeaderField("foo").length()); - EXPECT_EQ(0U, request.httpHeaderField("bar").length()); - EXPECT_EQ(0U, request.httpHeaderField("Content-length").length()); - EXPECT_EQ("abcdefghij", request.httpBody()->flattenToString()); + EXPECT_EQ(0U, GetHeader(request, "foo").length()); + EXPECT_EQ(0U, GetHeader(request, "bar").length()); + EXPECT_EQ(0U, GetHeader(request, "Content-length").length()); + EXPECT_EQ("abcdefghij", GetBodyText(request)); } TEST(WebPluginImplTest, PostParserNoBody) { // Test a simple case with headers and no body const char *ex1 = "Foo:bar\n\n"; - WebCore::ResourceRequest request; + WebURLRequest request; + request.initialize(); bool rv = WebPluginImpl::SetPostData(&request, ex1, static_cast<uint32>(strlen(ex1))); EXPECT_EQ(true, rv); - EXPECT_EQ("bar", request.httpHeaderField("foo").stripWhiteSpace()); - EXPECT_EQ(0U, request.httpHeaderField("bar").length()); - EXPECT_EQ(0U, request.httpHeaderField("Content-length").length()); - EXPECT_EQ(0U, request.httpBody()->flattenToString().length()); + EXPECT_EQ("bar", GetHeader(request, "foo")); + EXPECT_EQ(0U, GetHeader(request, "bar").length()); + EXPECT_EQ(0U, GetHeader(request, "Content-length").length()); + EXPECT_EQ(0U, GetBodyText(request).length()); } TEST(WebPluginImplTest, PostParserBodyWithNewLines) { // Test a simple case with headers and no body const char *ex1 = "Foo:bar\n\n\n\nabcdefg\n\nabcdefg"; - WebCore::ResourceRequest request; + WebURLRequest request; + request.initialize(); bool rv = WebPluginImpl::SetPostData(&request, ex1, static_cast<uint32>(strlen(ex1))); EXPECT_EQ(true, rv); - EXPECT_EQ(request.httpBody()->flattenToString(), "\n\nabcdefg\n\nabcdefg"); + EXPECT_EQ(GetBodyText(request), "\n\nabcdefg\n\nabcdefg"); } TEST(WebPluginImplTest, PostParserErrorNoBody) { // Test with headers and no body const char *ex1 = "Foo:bar\n"; - WebCore::ResourceRequest request; + WebURLRequest request; + request.initialize(); bool rv = WebPluginImpl::SetPostData(&request, ex1, static_cast<uint32>(strlen(ex1))); EXPECT_EQ(true, rv); @@ -138,7 +175,8 @@ TEST(WebPluginImplTest, PostParserErrorNoBody) { TEST(WebPluginImplTest, PostParserErrorEmpty) { // Test with an empty string const char *ex1 = ""; - WebCore::ResourceRequest request; + WebURLRequest request; + request.initialize(); bool rv = WebPluginImpl::SetPostData(&request, ex1, static_cast<uint32>(strlen(ex1))); EXPECT_EQ(true, rv); @@ -147,36 +185,39 @@ TEST(WebPluginImplTest, PostParserErrorEmpty) { TEST(WebPluginImplTest, PostParserEmptyName) { // Test an error case with an empty header name field const char *ex1 = "foo:bar\n:blat\n\nbody"; - WebCore::ResourceRequest request; + WebURLRequest request; + request.initialize(); bool rv = WebPluginImpl::SetPostData(&request, ex1, static_cast<uint32>(strlen(ex1))); EXPECT_EQ(true, rv); - EXPECT_EQ("bar", request.httpHeaderField("foo").stripWhiteSpace()); - EXPECT_EQ("body", request.httpBody()->flattenToString()); + EXPECT_EQ("bar", GetHeader(request, "foo")); + EXPECT_EQ("body", GetBodyText(request)); } TEST(WebPluginImplTest, PostParserEmptyValue) { // Test an error case with an empty value field const char *ex1 = "foo:bar\nbar:\n\nbody"; - WebCore::ResourceRequest request; + WebURLRequest request; + request.initialize(); bool rv = WebPluginImpl::SetPostData(&request, ex1, static_cast<uint32>(strlen(ex1))); EXPECT_EQ(true, rv); - EXPECT_EQ("bar", request.httpHeaderField("foo").stripWhiteSpace()); - EXPECT_EQ(0U, request.httpHeaderField("bar").length()); - EXPECT_EQ("body", request.httpBody()->flattenToString()); + EXPECT_EQ("bar", GetHeader(request, "foo")); + EXPECT_EQ(0U, GetHeader(request, "bar").length()); + EXPECT_EQ("body", GetBodyText(request)); } TEST(WebPluginImplTest, PostParserCRLF) { // Test an error case with an empty value field const char *ex1 = "foo: bar\r\nbar:\r\n\r\nbody\r\n\r\nbody2"; - WebCore::ResourceRequest request; + WebURLRequest request; + request.initialize(); bool rv = WebPluginImpl::SetPostData(&request, ex1, static_cast<uint32>(strlen(ex1))); EXPECT_EQ(true, rv); - EXPECT_EQ("bar", request.httpHeaderField("foo").stripWhiteSpace()); - EXPECT_EQ(0U, request.httpHeaderField("bar").length()); - EXPECT_EQ("body\r\n\r\nbody2", request.httpBody()->flattenToString()); + EXPECT_EQ("bar", GetHeader(request, "foo")); + EXPECT_EQ(0U, GetHeader(request, "bar").length()); + EXPECT_EQ("body\r\n\r\nbody2", GetBodyText(request)); } TEST(WebPluginImplTest, PostParserBodyWithBinaryData) { @@ -186,19 +227,19 @@ TEST(WebPluginImplTest, PostParserBodyWithBinaryData) { memcpy(ex1 + strlen("foo: bar\nContent-length: 10\n\n"), &binary_data, sizeof(binary_data)); - WebCore::ResourceRequest request; + WebURLRequest request; + request.initialize(); bool rv = WebPluginImpl::SetPostData(&request, ex1, sizeof(ex1)/sizeof(ex1[0])); EXPECT_EQ(true, rv); - EXPECT_EQ("bar", request.httpHeaderField("foo").stripWhiteSpace()); - EXPECT_EQ(0U, request.httpHeaderField("bar").length()); - EXPECT_EQ(0U, request.httpHeaderField("Content-length").length()); + EXPECT_EQ("bar", GetHeader(request, "foo")); + EXPECT_EQ(0U, GetHeader(request, "bar").length()); + EXPECT_EQ(0U, GetHeader(request, "Content-length").length()); - Vector<char> expected_data; - request.httpBody()->flatten(expected_data); + std::string body = GetBodyText(request); - EXPECT_EQ(0xF0, (unsigned char)expected_data[0]); - EXPECT_EQ(0xFF, (unsigned char)expected_data[1]); - EXPECT_EQ(0xFF, (unsigned char)expected_data[2]); - EXPECT_EQ(0xFF, (unsigned char)expected_data[3]); + EXPECT_EQ(0xF0, (unsigned char)body[0]); + EXPECT_EQ(0xFF, (unsigned char)body[1]); + EXPECT_EQ(0xFF, (unsigned char)body[2]); + EXPECT_EQ(0xFF, (unsigned char)body[3]); } diff --git a/webkit/glue/weburlloader_impl.cc b/webkit/glue/weburlloader_impl.cc new file mode 100644 index 0000000..ceb5fc8 --- /dev/null +++ b/webkit/glue/weburlloader_impl.cc @@ -0,0 +1,501 @@ +// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// An implementation of WebURLLoader in terms of ResourceLoaderBridge. + +#include "webkit/glue/weburlloader_impl.h" + +#include "base/message_loop.h" +#include "base/process_util.h" +#include "base/string_util.h" +#include "base/time.h" +#include "net/base/data_url.h" +#include "net/base/load_flags.h" +#include "net/base/net_errors.h" +#include "net/base/net_util.h" +#include "net/http/http_response_headers.h" +#include "webkit/api/public/WebHTTPHeaderVisitor.h" +#include "webkit/api/public/WebURL.h" +#include "webkit/api/public/WebURLError.h" +#include "webkit/api/public/WebURLLoaderClient.h" +#include "webkit/api/public/WebURLRequest.h" +#include "webkit/api/public/WebURLResponse.h" +#include "webkit/glue/glue_util.h" +#include "webkit/glue/webkit_glue.h" + +using base::Time; +using base::TimeDelta; +using WebKit::WebData; +using WebKit::WebHTTPBody; +using WebKit::WebHTTPHeaderVisitor; +using WebKit::WebString; +using WebKit::WebURLError; +using WebKit::WebURLLoader; +using WebKit::WebURLLoaderClient; +using WebKit::WebURLRequest; +using WebKit::WebURLResponse; + +namespace webkit_glue { + +namespace { + +class HeaderFlattener : public WebHTTPHeaderVisitor { + public: + explicit HeaderFlattener(int load_flags) + : load_flags_(load_flags), + has_accept_header_(false) { + } + + virtual void visitHeader(const WebString& name, const WebString& value) { + // TODO(darin): is UTF-8 really correct here? It is if the strings are + // already ASCII (i.e., if they are already escaped properly). + const std::string& name_utf8 = WebStringToStdString(name); + const std::string& value_utf8 = WebStringToStdString(value); + + // Skip over referrer headers found in the header map because we already + // pulled it out as a separate parameter. We likewise prune the UA since + // that will be added back by the network layer. + if (LowerCaseEqualsASCII(name_utf8, "referer") || + LowerCaseEqualsASCII(name_utf8, "user-agent")) + return; + + // Skip over "Cache-Control: max-age=0" header if the corresponding + // load flag is already specified. FrameLoader sets both the flag and + // the extra header -- the extra header is redundant since our network + // implementation will add the necessary headers based on load flags. + // See http://code.google.com/p/chromium/issues/detail?id=3434. + if ((load_flags_ & net::LOAD_VALIDATE_CACHE) && + LowerCaseEqualsASCII(name_utf8, "cache-control") && + LowerCaseEqualsASCII(value_utf8, "max-age=0")) + return; + + if (LowerCaseEqualsASCII(name_utf8, "accept")) + has_accept_header_ = true; + + if (!buffer_.empty()) + buffer_.append("\r\n"); + buffer_.append(name_utf8 + ": " + value_utf8); + } + + const std::string& GetBuffer() { + // In some cases, WebKit doesn't add an Accept header, but not having the + // header confuses some web servers. See bug 808613. + if (!has_accept_header_) { + if (!buffer_.empty()) + buffer_.append("\r\n"); + buffer_.append("Accept: */*"); + has_accept_header_ = true; + } + return buffer_; + } + + private: + int load_flags_; + std::string buffer_; + bool has_accept_header_; +}; + +ResourceType::Type FromTargetType(WebURLRequest::TargetType type) { + switch (type) { + case WebURLRequest::TargetIsMainFrame: + return ResourceType::MAIN_FRAME; + case WebURLRequest::TargetIsSubFrame: + return ResourceType::SUB_FRAME; + case WebURLRequest::TargetIsSubResource: + return ResourceType::SUB_RESOURCE; + case WebURLRequest::TargetIsObject: + return ResourceType::OBJECT; + case WebURLRequest::TargetIsMedia: + return ResourceType::MEDIA; + default: + NOTREACHED(); + return ResourceType::SUB_RESOURCE; + } +} + +// Extracts the information from a data: url. +bool GetInfoFromDataURL(const GURL& url, + ResourceLoaderBridge::ResponseInfo* info, + std::string* data, URLRequestStatus* status) { + std::string mime_type; + std::string charset; + if (net::DataURL::Parse(url, &mime_type, &charset, data)) { + *status = URLRequestStatus(URLRequestStatus::SUCCESS, 0); + info->request_time = Time::Now(); + info->response_time = Time::Now(); + info->headers = NULL; + info->mime_type.swap(mime_type); + info->charset.swap(charset); + info->security_info.clear(); + info->content_length = -1; + + return true; + } + + *status = URLRequestStatus(URLRequestStatus::FAILED, net::ERR_INVALID_URL); + return false; +} + +void PopulateURLResponse( + const GURL& url, + const ResourceLoaderBridge::ResponseInfo& info, + WebURLResponse* response) { + response->setURL(url); + response->setMIMEType(StdStringToWebString(info.mime_type)); + response->setTextEncodingName(StdStringToWebString(info.charset)); + response->setExpectedContentLength(info.content_length); + response->setSecurityInfo(info.security_info); + response->setAppCacheID(info.app_cache_id); + + const net::HttpResponseHeaders* headers = info.headers; + if (!headers) + return; + + response->setHTTPStatusCode(headers->response_code()); + response->setHTTPStatusText(StdStringToWebString(headers->GetStatusText())); + + // TODO(darin): We should leverage HttpResponseHeaders for this, and this + // should be using the same code as ResourceDispatcherHost. + // TODO(jungshik): Figure out the actual value of the referrer charset and + // pass it to GetSuggestedFilename. + std::string value; + if (headers->EnumerateHeader(NULL, "content-disposition", &value)) { + response->setSuggestedFileName(WideToUTF16Hack( + net::GetSuggestedFilename(url, value, "", std::wstring()))); + } + + Time time_val; + if (headers->GetLastModifiedValue(&time_val)) + response->setLastModifiedDate(time_val.ToDoubleT()); + + // Compute expiration date + TimeDelta freshness_lifetime = + headers->GetFreshnessLifetime(info.response_time); + if (freshness_lifetime != TimeDelta()) { + Time now = Time::Now(); + TimeDelta current_age = + headers->GetCurrentAge(info.request_time, info.response_time, now); + time_val = now + freshness_lifetime - current_age; + + response->setExpirationDate(time_val.ToDoubleT()); + } else { + // WebKit uses 0 as a special expiration date that means never expire. + // 1 is a small enough value to let it always expire. + response->setExpirationDate(1); + } + + // Build up the header map. + void* iter = NULL; + std::string name; + while (headers->EnumerateHeaderLines(&iter, &name, &value)) { + response->addHTTPHeaderField(StdStringToWebString(name), + StdStringToWebString(value)); + } +} + +} // namespace + +WebURLLoaderImpl::WebURLLoaderImpl() + : ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)), + client_(NULL) { +} + +WebURLLoaderImpl::~WebURLLoaderImpl() { +} + +void WebURLLoaderImpl::loadSynchronously(const WebURLRequest& request, + WebURLResponse& response, + WebURLError& error, + WebData& data) { + ResourceLoaderBridge::SyncLoadResponse sync_load_response; + Start(request, &sync_load_response); + + const GURL& final_url = sync_load_response.url; + + // TODO(tc): For file loads, we may want to include a more descriptive + // status code or status text. + const URLRequestStatus::Status& status = sync_load_response.status.status(); + if (status != URLRequestStatus::SUCCESS && + status != URLRequestStatus::HANDLED_EXTERNALLY) { + response.setURL(final_url); + error.domain = WebString::fromUTF8(net::kErrorDomain); + error.reason = sync_load_response.status.os_error(); + error.unreachableURL = final_url; + return; + } + + PopulateURLResponse(final_url, sync_load_response, &response); + + data.assign(sync_load_response.data.data(), + sync_load_response.data.size()); +} + +void WebURLLoaderImpl::loadAsynchronously(const WebURLRequest& request, + WebURLLoaderClient* client) { + DCHECK(!client_); + + client_ = client; + Start(request, NULL); +} + +void WebURLLoaderImpl::cancel() { + // The bridge will still send OnCompletedRequest, which will deref() us, + // so we don't do that here. + if (bridge_.get()) + bridge_->Cancel(); + + // Ensure that we do not notify the multipart delegate anymore as it has + // its own pointer to the client. + multipart_delegate_.reset(); + + // Do not make any further calls to the client. + client_ = NULL; +} + +void WebURLLoaderImpl::setDefersLoading(bool value) { + if (bridge_.get()) + bridge_->SetDefersLoading(value); +} + +void WebURLLoaderImpl::OnUploadProgress(uint64 position, uint64 size) { + if (client_) + client_->didSendData(this, position, size); +} + +void WebURLLoaderImpl::OnReceivedRedirect(const GURL& new_url) { + if (!client_) + return; + + // TODO(darin): We lack sufficient information to construct the + // actual redirect response, so we just simulate it here. + WebURLResponse response(url_); + + // TODO(darin): We lack sufficient information to construct the + // actual request that resulted from the redirect, so we just + // report a GET navigation to the new location. + WebURLRequest new_request(new_url); + + url_ = new_url; + client_->willSendRequest(this, new_request, response); + + // TODO(darin): since new_request is sent as a mutable reference, it is + // possible that willSendRequest may have modified it. + // + // andresca on #webkit confirms that that is intentional, so we'll need + // to rework the ResourceLoaderBridge to give us control over what URL + // is really loaded (and with what headers) when a redirect is encountered. + DCHECK(GURL(new_request.url()) == new_url); +} + +void WebURLLoaderImpl::OnReceivedResponse( + const ResourceLoaderBridge::ResponseInfo& info, + bool content_filtered) { + if (!client_) + return; + + WebURLResponse response; + response.initialize(); + PopulateURLResponse(url_, info, &response); + response.setIsContentFiltered(content_filtered); + + expected_content_length_ = response.expectedContentLength(); + + client_->didReceiveResponse(this, response); + + // we may have been cancelled after didReceiveResponse, which would leave us + // without a client and therefore without much need to do multipart handling. + if (!client_) + return; + + DCHECK(!multipart_delegate_.get()); + if (info.headers && info.mime_type == "multipart/x-mixed-replace") { + std::string content_type; + info.headers->EnumerateHeader(NULL, "content-type", &content_type); + + std::string boundary = net::GetHeaderParamValue(content_type, "boundary"); + TrimString(boundary, " \"", &boundary); + + // If there's no boundary, just handle the request normally. In the gecko + // code, nsMultiMixedConv::OnStartRequest throws an exception. + if (!boundary.empty()) { + multipart_delegate_.reset( + new MultipartResponseDelegate(client_, this, response, boundary)); + } + } +} + +void WebURLLoaderImpl::OnReceivedData(const char* data, int len) { + if (!client_) + return; + + if (multipart_delegate_.get()) { + // The multipart delegate will make the appropriate calls to + // client_->didReceiveData and client_->didReceiveResponse. + multipart_delegate_->OnReceivedData(data, len); + } else { + client_->didReceiveData(this, data, len, expected_content_length_); + } +} + +void WebURLLoaderImpl::OnCompletedRequest(const URLRequestStatus& status, + const std::string& security_info) { + if (multipart_delegate_.get()) { + multipart_delegate_->OnCompletedRequest(); + multipart_delegate_.reset(NULL); + } + + if (!client_) + return; + + if (status.status() != URLRequestStatus::SUCCESS) { + int error_code; + if (status.status() == URLRequestStatus::HANDLED_EXTERNALLY) { + // By marking this request as aborted we insure that we don't navigate + // to an error page. + error_code = net::ERR_ABORTED; + } else { + error_code = status.os_error(); + } + WebURLError error; + error.domain = WebString::fromUTF8(net::kErrorDomain); + error.reason = error_code; + error.unreachableURL = url_; + client_->didFail(this, error); + } else { + client_->didFinishLoading(this); + } +} + +std::string WebURLLoaderImpl::GetURLForDebugging() { + return url_.spec(); +} + +void WebURLLoaderImpl::Start( + const WebURLRequest& request, + ResourceLoaderBridge::SyncLoadResponse* sync_load_response) { + DCHECK(!bridge_.get()); + + url_ = request.url(); + if (url_.SchemeIs("data")) { + if (sync_load_response) { + // This is a sync load. Do the work now. + sync_load_response->url = url_; + std::string data; + GetInfoFromDataURL(sync_load_response->url, sync_load_response, + &sync_load_response->data, + &sync_load_response->status); + } else { + MessageLoop::current()->PostTask(FROM_HERE, + task_factory_.NewRunnableMethod(&WebURLLoaderImpl::HandleDataURL)); + } + return; + } + + GURL referrer_url(WebStringToStdString( + request.httpHeaderField(WebString::fromUTF8("Referer")))); + const std::string& method = WebStringToStdString(request.httpMethod()); + + int load_flags = net::LOAD_NORMAL; + switch (request.cachePolicy()) { + case WebURLRequest::ReloadIgnoringCacheData: + // Required by LayoutTests/http/tests/misc/refresh-headers.php + load_flags |= net::LOAD_VALIDATE_CACHE; + break; + case WebURLRequest::ReturnCacheDataElseLoad: + load_flags |= net::LOAD_PREFERRING_CACHE; + break; + case WebURLRequest::ReturnCacheDataDontLoad: + load_flags |= net::LOAD_ONLY_FROM_CACHE; + break; + case WebURLRequest::UseProtocolCachePolicy: + break; + } + + if (request.reportUploadProgress()) + load_flags |= net::LOAD_ENABLE_UPLOAD_PROGRESS; + + // TODO(jcampan): in the non out-of-process plugin case the request does not + // have a requestor_pid. Find a better place to set this. + int requestor_pid = request.requestorProcessID(); + if (requestor_pid == 0) + requestor_pid = base::GetCurrentProcId(); + + HeaderFlattener flattener(load_flags); + request.visitHTTPHeaderFields(&flattener); + + // TODO(abarth): These are wrong! I need to figure out how to get the right + // strings here. See: http://crbug.com/8706 + std::string frame_origin = request.firstPartyForCookies().spec(); + std::string main_frame_origin = request.firstPartyForCookies().spec(); + + // TODO(brettw) this should take parameter encoding into account when + // creating the GURLs. + bridge_.reset(ResourceLoaderBridge::Create( + method, + url_, + request.firstPartyForCookies(), + referrer_url, + frame_origin, + main_frame_origin, + flattener.GetBuffer(), + load_flags, + requestor_pid, + FromTargetType(request.targetType()), + request.appCacheContextID(), + request.requestorID())); + + if (!request.httpBody().isNull()) { + // GET and HEAD requests shouldn't have http bodies. + DCHECK(method != "GET" && method != "HEAD"); + const WebHTTPBody& httpBody = request.httpBody(); + size_t i = 0; + WebHTTPBody::Element element; + while (httpBody.elementAt(i++, element)) { + switch (element.type) { + case WebHTTPBody::Element::TypeData: + if (!element.data.isEmpty()) { + // WebKit sometimes gives up empty data to append. These aren't + // necessary so we just optimize those out here. + bridge_->AppendDataToUpload( + element.data.data(), static_cast<int>(element.data.size())); + } + break; + case WebHTTPBody::Element::TypeFile: + bridge_->AppendFileToUpload( + FilePath(WebStringToFilePathString(element.filePath))); + break; + default: + NOTREACHED(); + } + } + bridge_->SetUploadIdentifier(request.httpBody().identifier()); + } + + if (sync_load_response) { + bridge_->SyncLoad(sync_load_response); + return; + } + + if (!bridge_->Start(this)) + bridge_.reset(); +} + +void WebURLLoaderImpl::HandleDataURL() { + if (!client_) + return; + + ResourceLoaderBridge::ResponseInfo info; + URLRequestStatus status; + std::string data; + + if (GetInfoFromDataURL(url_, &info, &data, &status)) { + OnReceivedResponse(info, false); + if (!data.empty()) + OnReceivedData(data.data(), data.size()); + } + + OnCompletedRequest(status, info.security_info); +} + +} // namespace webkit_glue diff --git a/webkit/glue/weburlloader_impl.h b/webkit/glue/weburlloader_impl.h new file mode 100644 index 0000000..2ad50c3 --- /dev/null +++ b/webkit/glue/weburlloader_impl.h @@ -0,0 +1,61 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. Use of this +// source code is governed by a BSD-style license that can be found in the +// LICENSE file. + +#ifndef WEBKIT_GLUE_WEBURLLOADER_IMPL_H_ +#define WEBKIT_GLUE_WEBURLLOADER_IMPL_H_ + +#include "base/scoped_ptr.h" +#include "base/task.h" +#include "webkit/api/public/WebURLLoader.h" +#include "webkit/glue/multipart_response_delegate.h" +#include "webkit/glue/resource_loader_bridge.h" + +namespace webkit_glue { + +class WebURLLoaderImpl : public WebKit::WebURLLoader, + public ResourceLoaderBridge::Peer { + public: + WebURLLoaderImpl(); + ~WebURLLoaderImpl(); + + // WebURLLoader methods: + virtual void loadSynchronously( + const WebKit::WebURLRequest& request, + WebKit::WebURLResponse& response, + WebKit::WebURLError& error, + WebKit::WebData& data); + virtual void loadAsynchronously( + const WebKit::WebURLRequest& request, + WebKit::WebURLLoaderClient* client); + virtual void cancel(); + virtual void setDefersLoading(bool value); + + // ResourceLoaderBridge::Peer methods: + virtual void OnUploadProgress(uint64 position, uint64 size); + virtual void OnReceivedRedirect(const GURL& new_url); + virtual void OnReceivedResponse( + const ResourceLoaderBridge::ResponseInfo& info, bool content_filtered); + virtual void OnReceivedData(const char* data, int len); + virtual void OnCompletedRequest( + const URLRequestStatus& status, const std::string& security_info); + virtual std::string GetURLForDebugging(); + + private: + void Start( + const WebKit::WebURLRequest& request, + ResourceLoaderBridge::SyncLoadResponse* sync_load_response); + void HandleDataURL(); + + ScopedRunnableMethodFactory<WebURLLoaderImpl> task_factory_; + + GURL url_; + WebKit::WebURLLoaderClient* client_; + scoped_ptr<ResourceLoaderBridge> bridge_; + scoped_ptr<MultipartResponseDelegate> multipart_delegate_; + int64 expected_content_length_; +}; + +} // namespace webkit_glue + +#endif // WEBKIT_GLUE_WEBURLLOADER_IMPL_H_ diff --git a/webkit/webkit.gyp b/webkit/webkit.gyp index 534ce7d..844acc1 100644 --- a/webkit/webkit.gyp +++ b/webkit/webkit.gyp @@ -4208,6 +4208,7 @@ 'api/public/WebData.h', 'api/public/WebDragData.h', 'api/public/WebFindOptions.h', + 'api/public/WebHTTPBody.h', 'api/public/WebImage.h', 'api/public/WebInputEvent.h', 'api/public/WebKit.h', @@ -4215,6 +4216,7 @@ 'api/public/WebMediaPlayer.h', 'api/public/WebMediaPlayerClient.h', 'api/public/WebMimeRegistry.h', + 'api/public/WebNonCopyable.h', 'api/public/WebPluginListBuilder.h', 'api/public/WebPoint.h', 'api/public/WebRect.h', @@ -4223,6 +4225,11 @@ 'api/public/WebSize.h', 'api/public/WebString.h', 'api/public/WebURL.h', + 'api/public/WebURLError.h', + 'api/public/WebURLLoader.h', + 'api/public/WebURLLoaderClient.h', + 'api/public/WebURLRequest.h', + 'api/public/WebURLResponse.h', 'api/public/WebVector.h', 'api/public/win/WebInputEventFactory.h', 'api/public/win/WebSandboxSupport.h', @@ -4236,11 +4243,13 @@ 'api/src/mac/WebInputEventFactory.mm', 'api/src/mac/WebScreenInfoFactory.mm', 'api/src/MediaPlayerPrivateChromium.cpp', + 'api/src/ResourceHandle.cpp', 'api/src/TemporaryGlue.h', 'api/src/WebCache.cpp', 'api/src/WebCString.cpp', 'api/src/WebData.cpp', 'api/src/WebDragData.cpp', + 'api/src/WebHTTPBody.cpp', 'api/src/WebImageSkia.cpp', 'api/src/WebInputEvent.cpp', 'api/src/WebKit.cpp', @@ -4250,6 +4259,13 @@ 'api/src/WebPluginListBuilderImpl.h', 'api/src/WebString.cpp', 'api/src/WebURL.cpp', + 'api/src/WebURLRequest.cpp', + 'api/src/WebURLRequestPrivate.h', + 'api/src/WebURLResponse.cpp', + 'api/src/WebURLResponsePrivate.h', + 'api/src/WebURLError.cpp', + 'api/src/WrappedResourceRequest.h', + 'api/src/WrappedResourceResponse.h', 'api/src/win/WebInputEventFactory.cpp', 'api/src/win/WebScreenInfoFactory.cpp', ], @@ -4510,7 +4526,6 @@ 'glue/password_form_dom_manager.h', 'glue/resource_fetcher.cc', 'glue/resource_fetcher.h', - 'glue/resource_handle_impl.cc', 'glue/resource_loader_bridge.cc', 'glue/resource_loader_bridge.h', 'glue/resource_type.h', @@ -4577,6 +4592,8 @@ 'glue/webtextinput_impl.cc', 'glue/webtextinput_impl.h', 'glue/webthemeengine_impl_win.cc', + 'glue/weburlloader_impl.cc', + 'glue/weburlloader_impl.h', 'glue/weburlrequest.h', 'glue/weburlrequest_impl.cc', 'glue/weburlrequest_impl.h', |