diff options
author | Kristian Monsen <kristianm@google.com> | 2010-03-22 18:15:40 +0000 |
---|---|---|
committer | Kristian Monsen <kristianm@google.com> | 2010-07-15 11:27:25 +0100 |
commit | f48006ff278822e558c43fa7d6635f0ff34342b6 (patch) | |
tree | 92392399395fb3bce4566ae9bbd5e33fccce6970 /WebKit/android | |
parent | fd88d7ed6810e08b8d8c4512effc4da5e9c08265 (diff) | |
download | external_webkit-f48006ff278822e558c43fa7d6635f0ff34342b6.zip external_webkit-f48006ff278822e558c43fa7d6635f0ff34342b6.tar.gz external_webkit-f48006ff278822e558c43fa7d6635f0ff34342b6.tar.bz2 |
Initial check-in of the external/webkit part of the chrome http stack.
There are no changes in WebCore anymore, the new files live in WebKit/android/WebCoreSupport. There are two WebCore functions implemented in WebUrlLoader.cpp, they are
one-liners that call a WebKit function or return a bool.
Only async downloads are implemented so far. There are crashes on some websites, but better to get things checked in, and then start fixing outstanding issues.
I have tried to address all the issues from the reviews, but since the code has changed a bit I have not replied to each of them.
Change-Id: Ie83798e2f82ce78cb00ee5a4a558c9d8085c9567
Diffstat (limited to 'WebKit/android')
-rw-r--r-- | WebKit/android/WebCoreSupport/WebRequest.cpp | 303 | ||||
-rw-r--r-- | WebKit/android/WebCoreSupport/WebRequest.h | 74 | ||||
-rw-r--r-- | WebKit/android/WebCoreSupport/WebRequestContext.cpp | 94 | ||||
-rw-r--r-- | WebKit/android/WebCoreSupport/WebRequestContext.h | 52 | ||||
-rw-r--r-- | WebKit/android/WebCoreSupport/WebUrlLoader.cpp | 92 | ||||
-rw-r--r-- | WebKit/android/WebCoreSupport/WebUrlLoader.h | 54 | ||||
-rw-r--r-- | WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp | 219 | ||||
-rw-r--r-- | WebKit/android/WebCoreSupport/WebUrlLoaderClient.h | 122 |
8 files changed, 1010 insertions, 0 deletions
diff --git a/WebKit/android/WebCoreSupport/WebRequest.cpp b/WebKit/android/WebCoreSupport/WebRequest.cpp new file mode 100644 index 0000000..8a85d8e --- /dev/null +++ b/WebKit/android/WebCoreSupport/WebRequest.cpp @@ -0,0 +1,303 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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 "WebRequest.h" + +#include "MainThread.h" +#include "ResourceRequest.h" +#include "WebRequestContext.h" + +#include "net/base/data_url.h" +#include "net/base/io_buffer.h" +#include "net/url_request/url_request.h" +#include "text/CString.h" + +#include <string> + +// TODO: +// - Get gmail log in to work +// - Finish the file upload. Testcase is mobile buzz +// - Handle fails better +// - Check the string conversion work for more than the general case +// - Add network throttle needed by Android plugins + +using namespace WebCore; + +namespace android { + +namespace { + const int kInitialReadBufSize = 32768; +} + +WebRequest::WebRequest(WebUrlLoaderClient* loader, WebCore::ResourceRequest& resourceRequest) + : m_urlLoader(loader), m_resourceRequest(resourceRequest), m_request(0) +{ +} + +WebRequest::~WebRequest() +{ +} + +void WebRequest::finish(bool /*success*/) +{ + LoaderData* loaderData = new LoaderData(m_urlLoader); + callOnMainThread(WebUrlLoaderClient::didFinishLoading, loaderData); + m_networkBuffer = 0; + m_request = 0; +} + +void WebRequest::start() +{ + GURL gurl(m_resourceRequest.url().string().utf8().data()); + + // Handle data urls before we send it off to the http stack + if (gurl.SchemeIs("data")) + return handleDataURL(gurl); + + m_request = new URLRequest(gurl, this); + + // Have to set uploads before start is called on the request + if (m_resourceRequest.httpBody()) + setUploadData(m_request.get()); + + m_request->set_method(m_resourceRequest.httpMethod().utf8().data()); + m_request->set_context(WebRequestContext::GetAndroidContext()); + + m_request->Start(); +} + +void WebRequest::setUploadData(URLRequest* request) +{ + const std::string& method = m_resourceRequest.httpMethod().utf8().data(); + if (method == "GET" || method == "HEAD") + return; + + Vector<FormDataElement>::iterator iter; + Vector<FormDataElement> elements = m_resourceRequest.httpBody()->elements(); + for (iter = elements.begin(); iter != elements.end(); iter++) { + FormDataElement element = *iter; + switch (element.m_type) { + case FormDataElement::data: + if (!element.m_data.isEmpty()) { + // WebKit sometimes gives up empty data to append. These aren't + // necessary so we just optimize those out here. + int size = static_cast<int>(element.m_data.size()); + request->AppendBytesToUpload(element.m_data.data(), size); + } + break; + case FormDataElement::encodedFile: + if (element.m_fileLength == -1) + continue; // TODO: Not supporting directories yet + else { + // TODO: Add fileuploads after Google log-in is fixed. + // Chrome code is here: webkit/glue/weburlloader_impl.cc:391 + } + break; + // default: + // TODO: should add the default back in with a warning + } + } +} + +void WebRequest::cancel() +{ + if (m_request) + m_request->Cancel(); + finish(true); +} + +void WebRequest::handleDataURL(GURL url) +{ + OwnPtr<std::string*> data(new std::string); + std::string mimeType; + std::string charset; + + if (net::DataURL::Parse(url, &mimeType, &charset, data.get())) { + // PopulateURLResponse from chrome implementation + // weburlloader_impl.cc + WebCore::ResourceResponse* resourceResponse = new WebCore::ResourceResponse(m_resourceRequest.url(), mimeType.c_str(), data->size(), charset.c_str(), ""); + resourceResponse->setHTTPStatusCode(200); // Do they always succeed? + + LoaderData* loaderResponse = new LoaderData(m_urlLoader, resourceResponse); + callOnMainThread(WebUrlLoaderClient::didReceiveResponse, loaderResponse); + + if (!data->empty()) { + LoaderData* loaderData = new LoaderData(m_urlLoader, data.release()); + callOnMainThread(WebUrlLoaderClient::didReceiveDataUrl, loaderData); + } + } else { + // handle the failed case + } + + finish(true); +} + + +// Called upon a server-initiated redirect. The delegate may call the +// request's Cancel method to prevent the redirect from being followed. +// Since there may be multiple chained redirects, there may also be more +// than one redirect call. +// +// When this function is called, the request will still contain the +// original URL, the destination of the redirect is provided in 'new_url'. +// If the delegate does not cancel the request and |*defer_redirect| is +// false, then the redirect will be followed, and the request's URL will be +// changed to the new URL. Otherwise if the delegate does not cancel the +// request and |*defer_redirect| is true, then the redirect will be +// followed once FollowDeferredRedirect is called on the URLRequest. +// +// The caller must set |*defer_redirect| to false, so that delegates do not +// need to set it if they are happy with the default behavior of not +// deferring redirect. +void WebRequest::OnReceivedRedirect(URLRequest* newRequest, const GURL& newUrl, bool* deferRedirect) +{ + if (newRequest && newRequest->status().is_success()) { + KURL kurl(WebCore::ParsedURLString, newUrl.spec().c_str()); + std::string mime; + std::string encoding; + newRequest->GetMimeType(&mime); + newRequest->GetCharset(&encoding); + long long length = newRequest->GetExpectedContentSize(); + WebCore::ResourceResponse* resourceResponse = new WebCore::ResourceResponse(kurl, mime.c_str(), length, encoding.c_str(), ""); + + resourceResponse->setHTTPStatusCode(newRequest->GetResponseCode()); + LoaderData* ld = new LoaderData(m_urlLoader, resourceResponse); + callOnMainThread(WebUrlLoaderClient::willSendRequest, ld); + } else { + // why would this happen? And what to do? + } + + // Here we should check if the url we get back from webkit is the same + // as newUrl, but since we are on a different thread that is not + // possible. Look into later. + return; +} + +// Called when we receive an authentication failure. The delegate should +// call request->SetAuth() with the user's credentials once it obtains them, +// or request->CancelAuth() to cancel the login and display the error page. +// When it does so, the request will be reissued, restarting the sequence +// of On* callbacks. +void WebRequest::OnAuthRequired(URLRequest* request, net::AuthChallengeInfo* authInfo) +{ + // TODO: This is the default action, have to implement getting the + // username and password from webkit + request->CancelAuth(); +} + +// After calling Start(), the delegate will receive an OnResponseStarted +// callback when the request has completed. If an error occurred, the +// request->status() will be set. On success, all redirects have been +// followed and the final response is beginning to arrive. At this point, +// meta data about the response is available, including for example HTTP +// response headers if this is a request for a HTTP resource. +void WebRequest::OnResponseStarted(URLRequest* request) +{ + if (request && request->status().is_success()) { + KURL kurl(WebCore::ParsedURLString, request->url().spec().c_str()); + std::string mime; + std::string encoding; + request->GetMimeType(&mime); + request->GetCharset(&encoding); + long long int length = request->GetExpectedContentSize(); + WebCore::ResourceResponse* resourceResponse = new WebCore::ResourceResponse(kurl, mime.c_str(), length, encoding.c_str(), ""); + + resourceResponse->setHTTPStatusCode(request->GetResponseCode()); + LoaderData* loaderData = new LoaderData(m_urlLoader, resourceResponse); + + callOnMainThread(WebUrlLoaderClient::didReceiveResponse, loaderData); + + // Start reading the response + startReading(); + } else { + finish(false); + } +} + +void WebRequest::startReading() +{ + int bytesRead = 0; + + // chrome only does one read, and schedules the next on the same thread + while (true) { + if (read(&bytesRead)) { + // bytesRead == 0 indicates finished + if (!bytesRead) { + finish(true); + break; + } + + // Read ok, forward buffer to webcore + m_networkBuffer->AddRef(); + LoaderData* loaderData = new LoaderData(m_urlLoader, m_networkBuffer.get(), bytesRead); + callOnMainThread(WebUrlLoaderClient::didReceiveData, loaderData); + // m_networkBuffer->Release() on main thread + m_networkBuffer = 0; + } else if (m_request && m_request->status().is_io_pending()) { + // got io_pending, so break and wait for read + break; + } else { + // Error, stop and send back + finish(false); + break; + } + } +} + +bool WebRequest::read(int* bytesRead) +{ + // TODO: when asserts work, check that the buffer is 0 here + m_networkBuffer = new net::IOBuffer(kInitialReadBufSize); + return m_request->Read(m_networkBuffer, kInitialReadBufSize, bytesRead); +} + +// This is called when there is data available + +// Called when the a Read of the response body is completed after an +// IO_PENDING status from a Read() call. +// The data read is filled into the buffer which the caller passed +// to Read() previously. +// +// If an error occurred, request->status() will contain the error, +// and bytes read will be -1. +void WebRequest::OnReadCompleted(URLRequest* request, int bytesRead) +{ + if (request->status().is_success()) { + m_networkBuffer->AddRef(); + LoaderData* loaderData = new LoaderData(m_urlLoader, m_networkBuffer.get(), bytesRead); + // m_networkBuffer->Release() on main thread + callOnMainThread(WebUrlLoaderClient::didReceiveData, loaderData); + m_networkBuffer = 0; + + // Get the rest of the data + startReading(); + } else { + finish(false); + } +} + +} // namespace android diff --git a/WebKit/android/WebCoreSupport/WebRequest.h b/WebKit/android/WebCoreSupport/WebRequest.h new file mode 100644 index 0000000..5e1d92c --- /dev/null +++ b/WebKit/android/WebCoreSupport/WebRequest.h @@ -0,0 +1,74 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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 WebRequest_h +#define WebRequest_h + +#include "WebUrlLoaderClient.h" +#include "net/base/io_buffer.h" +#include "net/url_request/url_request.h" + +class MessageLoop; + +namespace WebCore { +class ResourceRequest; +} + +namespace android { + +// All methods in this class must be called on the io thread +class WebRequest : public URLRequest::Delegate, public base::RefCountedThreadSafe<WebRequest> { +public: + WebRequest(WebUrlLoaderClient*, WebCore::ResourceRequest&); + void start(); + void cancel(); + + // From URLRequest::Delegate + virtual void OnReceivedRedirect(URLRequest*, const GURL&, bool* deferRedirect); + virtual void OnResponseStarted(URLRequest*); + virtual void OnReadCompleted(URLRequest*, int bytesRead); + virtual void OnAuthRequired(URLRequest*, net::AuthChallengeInfo*); + +private: + void startReading(); + bool read(int* bytesRead); + + friend class base::RefCountedThreadSafe<WebRequest>; + virtual ~WebRequest(); + void handleDataURL(GURL); + void setUploadData(URLRequest*); + void finish(bool success); + + // Not owned + WebUrlLoaderClient* m_urlLoader; + + WebCore::ResourceRequest m_resourceRequest; + OwnPtr<URLRequest> m_request; + scoped_refptr<net::IOBuffer> m_networkBuffer; +}; + +} // namespace android + +#endif diff --git a/WebKit/android/WebCoreSupport/WebRequestContext.cpp b/WebKit/android/WebCoreSupport/WebRequestContext.cpp new file mode 100644 index 0000000..ecd083b --- /dev/null +++ b/WebKit/android/WebCoreSupport/WebRequestContext.cpp @@ -0,0 +1,94 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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 "WebRequestContext.h" + +#include "JNIUtility.h" +#include "jni.h" +#include "net/base/cookie_monster.h" +#include "net/base/ssl_config_service.h" +#include "net/http/http_cache.h" +#include "net/http/http_network_layer.h" + +namespace { + // TODO: Get uastring from webcore + std::string userAgent("Mozilla/5.0 (Linux; U; Android 2.1; en-gb; Nexus One Build/ERE21) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17"); +} + +namespace android { + +std::string* WebRequestContext::s_dataDirectory = 0; +net::HttpCache* WebRequestContext::s_cache = 0; + +WebRequestContext::WebRequestContext() +{ +} + +WebRequestContext::~WebRequestContext() +{ +} + +const std::string& WebRequestContext::GetUserAgent(const GURL& url) const +{ + return userAgent; +} + +const std::string* WebRequestContext::GetDataDirectory() +{ + if (!s_dataDirectory) { + JNIEnv* env = JSC::Bindings::getJNIEnv(); + jclass bridgeClass = env->FindClass("android/webkit/BrowserFrame"); + jmethodID method = env->GetStaticMethodID(bridgeClass, "getDataDirectory", "()Ljava/lang/String;"); + + jstring str = (jstring)env->CallStaticObjectMethod(bridgeClass, method); + jboolean isCopy; + const char* nativeString = env->GetStringUTFChars(str, &isCopy); + s_dataDirectory = new std::string(nativeString); + if (isCopy == JNI_TRUE) + env->ReleaseStringUTFChars(str, nativeString); + } + + return s_dataDirectory; +} + +// Some of the members of the RequestContext will be deleted when the URLRequest +// is deleted as they are scoped pointers. Documented in WebRequestContext.h +WebRequestContext* WebRequestContext::GetAndroidContext() +{ + WebRequestContext* androidContext = new WebRequestContext(); + androidContext->host_resolver_ = net::CreateSystemHostResolver(0); + androidContext->cookie_store_ = new net::CookieMonster(0); + + // In memory cache + if (!s_cache) + s_cache = new net::HttpCache(0, androidContext->host_resolver(), 0, net::SSLConfigService::CreateSystemSSLConfigService(), 0); + androidContext->http_transaction_factory_ = s_cache; + + return androidContext; +} + +} // namespace android diff --git a/WebKit/android/WebCoreSupport/WebRequestContext.h b/WebKit/android/WebCoreSupport/WebRequestContext.h new file mode 100644 index 0000000..65a0865 --- /dev/null +++ b/WebKit/android/WebCoreSupport/WebRequestContext.h @@ -0,0 +1,52 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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 WebRequestContext_h +#define WebRequestContext_h + +#include "net/http/http_cache.h" +#include "net/url_request/url_request_context.h" + +namespace android { + +class WebRequestContext : public URLRequestContext { +public: + virtual const std::string& GetUserAgent(const GURL& url) const; + static WebRequestContext* GetAndroidContext(); +private: + static const std::string* GetDataDirectory(); + WebRequestContext(); + ~WebRequestContext(); + + // Caching this query from java + static std::string* s_dataDirectory; + + // Not deleted on deletion of URLRequest + static net::HttpCache* s_cache; +}; + +} // namespace android + +#endif diff --git a/WebKit/android/WebCoreSupport/WebUrlLoader.cpp b/WebKit/android/WebCoreSupport/WebUrlLoader.cpp new file mode 100644 index 0000000..9df58e4 --- /dev/null +++ b/WebKit/android/WebCoreSupport/WebUrlLoader.cpp @@ -0,0 +1,92 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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 "WebUrlLoader.h" + +#include "WebUrlLoaderClient.h" + +namespace android { + +// on main thread +WebUrlLoader::WebUrlLoader(WebCore::ResourceHandle* resourceHandle, const WebCore::ResourceRequest& resourceRequest) +{ + m_loaderClient = new WebUrlLoaderClient(resourceHandle, resourceRequest); +} + +// on main thread +WebUrlLoader::~WebUrlLoader() +{ +} + +PassRefPtr<WebUrlLoader> WebUrlLoader::start(WebCore::ResourceHandle* resourceHandle, const WebCore::ResourceRequest& resourceRequest, bool isSync) +{ + RefPtr<WebUrlLoader> loader = WebUrlLoader::create(resourceHandle, resourceRequest); + loader->m_loaderClient->start(isSync); + + return loader.release(); +} + +PassRefPtr<WebUrlLoader> WebUrlLoader::create(WebCore::ResourceHandle* resourceHandle, const WebCore::ResourceRequest& resourceRequest) +{ + return adoptRef(new WebUrlLoader(resourceHandle, resourceRequest)); +} + +// on main thread +void WebUrlLoader::cancel() +{ + m_loaderClient->cancel(); +} + +} // namespace android + + +namespace WebCore { +// on main thread +// static +// TODO: Implement sync requests +PassRefPtr<ResourceLoaderAndroid> ResourceLoaderAndroid::start(WebCore::ResourceHandle* resourceHandle, const WebCore::ResourceRequest& resourceRequest, + FrameLoaderClient* /*client*/, bool /*isMainResource*/, bool isSync) +{ + return android::WebUrlLoader::start(resourceHandle, resourceRequest, isSync); +} + +// static +bool ResourceLoaderAndroid::willLoadFromCache(const WebCore::KURL&, int64_t identifier) +{ + // 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, to prevent the FrameLoader from initiating a + // reload. Then in FrameLoaderClientImpl::dispatchWillSendRequest, we + // fix-up the cache policy of the request to force a load from the cache. + // + return true; +} + +} // namespace WebCore diff --git a/WebKit/android/WebCoreSupport/WebUrlLoader.h b/WebKit/android/WebCoreSupport/WebUrlLoader.h new file mode 100644 index 0000000..167bdc0 --- /dev/null +++ b/WebKit/android/WebCoreSupport/WebUrlLoader.h @@ -0,0 +1,54 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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 WebUrlLoader_h +#define WebUrlLoader_h + +#include "ResourceLoaderAndroid.h" + +using namespace WebCore; + +namespace android { +class WebUrlLoaderClient; + +class WebUrlLoader : public ResourceLoaderAndroid { +public: + virtual ~WebUrlLoader(); + static PassRefPtr<WebUrlLoader> start(WebCore::ResourceHandle*, const WebCore::ResourceRequest&, bool sync); + + virtual void cancel(); + virtual void downloadFile() {} // Not implemented yet + virtual void pauseLoad(bool pause) {} // Android method, does nothing for now + +private: + WebUrlLoader(WebCore::ResourceHandle*, const WebCore::ResourceRequest&); + static PassRefPtr<WebUrlLoader> create(WebCore::ResourceHandle*, const WebCore::ResourceRequest&); + + OwnPtr<WebUrlLoaderClient> m_loaderClient; +}; + +} // namespace android + +#endif diff --git a/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp b/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp new file mode 100644 index 0000000..f73f312 --- /dev/null +++ b/WebKit/android/WebCoreSupport/WebUrlLoaderClient.cpp @@ -0,0 +1,219 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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 "WebUrlLoaderClient.h" + +#include "OwnPtr.h" +#include "ResourceHandle.h" +#include "ResourceHandleClient.h" +#include "ResourceResponse.h" +#include "WebRequest.h" + +#include "base/thread.h" +#include "net/base/io_buffer.h" + +namespace android { + +LoaderData::~LoaderData() +{ + if (m_buffer) + m_buffer->Release(); +} + +std::vector<WebUrlLoaderClient*>* WebUrlLoaderClient::activeLoaders = new std::vector<WebUrlLoaderClient*>(); + +base::Thread* WebUrlLoaderClient::ioThread() +{ + static base::Thread* networkThread = 0; + if (!networkThread) + networkThread = new base::Thread("network"); + + if (!networkThread) + return 0; + + if (networkThread->IsRunning()) + return networkThread; + + base::Thread::Options options; + options.message_loop_type = MessageLoop::TYPE_IO; + if (!networkThread->StartWithOptions(options)) { + delete networkThread; + networkThread = 0; + } + + return networkThread; +} + +WebUrlLoaderClient::~WebUrlLoaderClient() +{ + base::Thread* thread = ioThread(); + if (thread) + thread->message_loop()->ReleaseSoon(FROM_HERE, m_request); + + std::vector<WebUrlLoaderClient*>::iterator iter; + for (iter = activeLoaders->begin(); iter != activeLoaders->end(); ++iter) { + if (*iter == this) { + activeLoaders->erase(iter); + break; + } + } +} + +bool WebUrlLoaderClient::isActive(const WebUrlLoaderClient* loader) +{ + if (!loader) + return false; + + bool exists = false; + std::vector<WebUrlLoaderClient*>::const_iterator iter; + for (iter = activeLoaders->begin(); iter != activeLoaders->end(); ++iter) + if (*iter == loader) + exists = true; + + if (!exists) + return false; + if (loader->m_cancelling) + return false; + if (!loader->m_resourceHandle) + return false; + if (!loader->m_resourceHandle->client()) + return false; + + return true; +} + +WebUrlLoaderClient::WebUrlLoaderClient(WebCore::ResourceHandle* resourceHandle, const WebCore::ResourceRequest& resourceRequest) + : m_resourceHandle(resourceHandle), m_resourceRequest(resourceRequest), m_cancelling(false) +{ + m_request = new WebRequest(this, m_resourceRequest); + m_request->AddRef(); // Matched by ReleaseSoon in destructor + + activeLoaders->push_back(this); +} + +bool WebUrlLoaderClient::start(bool /*sync*/) +{ + base::Thread* thread = ioThread(); + if (thread) { + thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(m_request, &WebRequest::start)); + return true; + } + + return false; +} + +void WebUrlLoaderClient::cancel() +{ + m_cancelling = true; + + base::Thread* thread = ioThread(); + if (thread) + thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(m_request, &WebRequest::cancel)); + + finish(); +} + +void WebUrlLoaderClient::finish() +{ + m_resourceHandle = 0; +} + +// Response methods +// static - on main thread +void WebUrlLoaderClient::didReceiveResponse(void* data) +{ + OwnPtr<LoaderData> loaderData(static_cast<LoaderData*>(data)); + const WebUrlLoaderClient* loader = loaderData->m_loader; + ResourceResponse* resourceResponse = loaderData->m_resourceResponse.get(); + + if (!isActive(loader)) + return; + + loader->m_resourceHandle->client()->didReceiveResponse(loader->m_resourceHandle.get(), *resourceResponse); +} + +// static - on main thread +void WebUrlLoaderClient::didReceiveData(void* data) +{ + OwnPtr<LoaderData> loaderData(static_cast<LoaderData*>(data)); + const WebUrlLoaderClient* loader = loaderData->m_loader; + net::IOBuffer* buf = loaderData->m_buffer; + + if (!isActive(loader)) + return; + + if (loader->m_resourceHandle && loader->m_resourceHandle->client()) + loader->m_resourceHandle->client()->didReceiveData(loader->m_resourceHandle.get(), buf->data(), loaderData->m_size, loaderData->m_size); +} + +// static - on main thread +// For data url's +void WebUrlLoaderClient::didReceiveDataUrl(void* data) +{ + OwnPtr<LoaderData> ld(static_cast<LoaderData*>(data)); + const WebUrlLoaderClient* loader = ld->m_loader; + + if (!isActive(loader)) + return; + + std::string* str = ld->m_string.get(); + loader->m_resourceHandle->client()->didReceiveData(loader->m_resourceHandle.get(), str->data(), str->size(), str->size()); +} + +// static - on main thread +void WebUrlLoaderClient::didFail(void* data) +{ +} + +// static - on main thread +void WebUrlLoaderClient::willSendRequest(void* data) +{ + OwnPtr<LoaderData> loaderData(static_cast<LoaderData*>(data)); + const WebUrlLoaderClient* loader = loaderData->m_loader; + + if (!isActive(loader)) + return; + + WebCore::ResourceResponse* resourceResponse = loaderData->m_resourceResponse.get(); + OwnPtr<WebCore::ResourceRequest> resourceRequest(new WebCore::ResourceRequest(resourceResponse->url())); + loader->m_resourceHandle->client()->willSendRequest(loader->m_resourceHandle.get(), *resourceRequest, *resourceResponse); +} + +// static - on main thread +void WebUrlLoaderClient::didFinishLoading(void* data) +{ + OwnPtr<LoaderData> loaderData(static_cast<LoaderData*>(data)); + WebUrlLoaderClient* loader = loaderData->m_loader; + + if (!isActive(loader)) + return; + + loader->m_resourceHandle->client()->didFinishLoading(loader->m_resourceHandle.get()); + loader->finish(); +} + +} // namespace android diff --git a/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h b/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h new file mode 100644 index 0000000..52fd6e9 --- /dev/null +++ b/WebKit/android/WebCoreSupport/WebUrlLoaderClient.h @@ -0,0 +1,122 @@ +/* + * Copyright 2010, The Android Open Source Project + * + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``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 WebUrlLoaderClient_h +#define WebUrlLoaderClient_h + +#include "RefCounted.h" +#include "WebUrlLoader.h" + +#include "base/ref_counted.h" +#include <string> +#include <vector> + +namespace base { +class Thread; +} + +namespace net { +class IOBuffer; +} + +namespace android { + +class WebRequest; + +// This class handles communication between the IO thread where loading happens +// and the webkit main thread. +// TODO: +// - Corner case where this gets deleted before UrlRequestAndroid +// - Implement didFail +// - Implement sync requests +// - Implement downloadFile +// - Implement pauseLoad +class WebUrlLoaderClient { +public: + WebUrlLoaderClient(WebCore::ResourceHandle*, const WebCore::ResourceRequest&); + ~WebUrlLoaderClient(); + + // Called from WebCore, will be forwarded to the IO thread + bool start(bool sync); + void cancel(); + void downloadFile(); + void pauseLoad(bool pause) {} // Android method, does nothing for now + + // Called by WebRequest, should be forwarded to WebCore + static void didReceiveResponse(void*); + static void didReceiveData(void*); + static void didReceiveDataUrl(void*); + static void didFinishLoading(void*); + static void didFail(void*); + static void willSendRequest(void*); + +private: + void finish(); + RefPtr<WebCore::ResourceHandle> m_resourceHandle; + WebCore::ResourceRequest m_resourceRequest; + bool m_cancelling; + + // Not an OwnPtr since it should be deleted on another thread + WebRequest* m_request; + + // Handle to the chrome IO thread + static base::Thread* ioThread(); + + // Vector containing all active loader clients + static std::vector<WebUrlLoaderClient*>* activeLoaders; + + static bool isActive(const WebUrlLoaderClient*); +}; + +// A struct to send more than one thing in a void*, needed for callOnMainThread +struct LoaderData { + net::IOBuffer* m_buffer; + WebUrlLoaderClient* m_loader; + OwnPtr<WebCore::ResourceResponse*> m_resourceResponse; + const int m_size; + OwnPtr<std::string*> m_string; + + LoaderData(WebUrlLoaderClient* l) : m_buffer(0), m_loader(l), m_resourceResponse(0), m_size(0), m_string(0) + { + } + + LoaderData(WebUrlLoaderClient* l, std::string* s) : m_buffer(0), m_loader(l), m_resourceResponse(0), m_size(0), m_string(s) + { + } + + LoaderData(WebUrlLoaderClient* l, WebCore::ResourceResponse* r) : m_buffer(0), m_loader(l), m_resourceResponse(r), m_size(0), m_string(0) + { + } + + LoaderData(WebUrlLoaderClient* l, net::IOBuffer* b, const int s) : m_buffer(b), m_loader(l), m_resourceResponse(0), m_size(s), m_string(0) + { + } + + ~LoaderData(); +}; + +} // namespace android + +#endif |