ResourceHandleSoup.cpp revision 65f03d4f644ce73618e5f4f50dd694b26f55ae12
18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2008 Alp Toker <alp@atoker.com>
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2008 Xan Lopez <xan@gnome.org>
4dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block * Copyright (C) 2008, 2010 Collabora Ltd.
5635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project * Copyright (C) 2009 Holger Hans Peter Freyther
68f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * Copyright (C) 2009 Gustavo Noronha Silva <gns@gnome.org>
78f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * Copyright (C) 2009 Christian Dywan <christian@imendio.com>
88f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian * Copyright (C) 2009 Igalia S.L.
90bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch * Copyright (C) 2009 John Kjellberg <john.kjellberg@power.alstom.com>
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is free software; you can redistribute it and/or
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modify it under the terms of the GNU Library General Public
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * License as published by the Free Software Foundation; either
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * version 2 of the License, or (at your option) any later version.
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This library is distributed in the hope that it will be useful,
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * but WITHOUT ANY WARRANTY; without even the implied warranty of
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Library General Public License for more details.
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * You should have received a copy of the GNU Library General Public License
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * along with this library; see the file COPYING.LIB.  If not, write to
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Boston, MA 02110-1301, USA.
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ResourceHandle.h"
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Base64.h"
316c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen#include "CString.h"
328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "ChromeClient.h"
33dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "CookieJarSoup.h"
345abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick#include "CachedResourceLoader.h"
358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "FileSystem.h"
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Frame.h"
37dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "GOwnPtrSoup.h"
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTTPParsers.h"
398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "Logging.h"
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "MIMETypeRegistry.h"
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "NotImplemented.h"
428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include "Page.h"
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ResourceError.h"
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ResourceHandleClient.h"
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ResourceHandleInternal.h"
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ResourceResponse.h"
47dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "SharedBuffer.h"
48a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "soup-request-http.h"
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "TextEncoding.h"
508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include <errno.h>
518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include <fcntl.h>
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <gio/gio.h>
536c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen#include <glib.h>
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <libsoup/soup.h>
558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include <sys/stat.h>
566c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen#include <sys/types.h>
578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian#include <unistd.h>
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
61a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#define READ_BUFFER_SIZE 8192
62a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochclass WebCoreSynchronousLoader : public ResourceHandleClient, public Noncopyable {
648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianpublic:
658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    WebCoreSynchronousLoader(ResourceError&, ResourceResponse &, Vector<char>&);
668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    ~WebCoreSynchronousLoader();
678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&);
698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    virtual void didReceiveData(ResourceHandle*, const char*, int, int lengthReceived);
7068513a70bcd92384395513322f1b801e7bf9c729Steve Block    virtual void didFinishLoading(ResourceHandle*, double /*finishTime*/);
718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    virtual void didFail(ResourceHandle*, const ResourceError&);
728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
738f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    void run();
748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianprivate:
768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    ResourceError& m_error;
778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    ResourceResponse& m_response;
788f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    Vector<char>& m_data;
798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    bool m_finished;
808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    GMainLoop* m_mainLoop;
818f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian};
828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianWebCoreSynchronousLoader::WebCoreSynchronousLoader(ResourceError& error, ResourceResponse& response, Vector<char>& data)
848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    : m_error(error)
858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    , m_response(response)
868f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    , m_data(data)
878f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    , m_finished(false)
888f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
898f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    m_mainLoop = g_main_loop_new(0, false);
908f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
918f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianWebCoreSynchronousLoader::~WebCoreSynchronousLoader()
938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    g_main_loop_unref(m_mainLoop);
958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid WebCoreSynchronousLoader::didReceiveResponse(ResourceHandle*, const ResourceResponse& response)
988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    m_response = response;
1008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
1018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid WebCoreSynchronousLoader::didReceiveData(ResourceHandle*, const char* data, int length, int)
1038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
1048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    m_data.append(data, length);
1058f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
1068f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
10768513a70bcd92384395513322f1b801e7bf9c729Steve Blockvoid WebCoreSynchronousLoader::didFinishLoading(ResourceHandle*, double)
1088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
1098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    g_main_loop_quit(m_mainLoop);
1108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    m_finished = true;
1118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
1128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid WebCoreSynchronousLoader::didFail(ResourceHandle* handle, const ResourceError& error)
1148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
1158f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    m_error = error;
11668513a70bcd92384395513322f1b801e7bf9c729Steve Block    didFinishLoading(handle, 0);
1178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
1188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianvoid WebCoreSynchronousLoader::run()
1208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
1218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!m_finished)
1228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        g_main_loop_run(m_mainLoop);
1238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
1248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
125a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochstatic void cleanupSoupRequestOperation(ResourceHandle*, bool isDestroying);
126a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochstatic void sendRequestCallback(GObject*, GAsyncResult*, gpointer);
127a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochstatic void readCallback(GObject*, GAsyncResult*, gpointer);
128a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochstatic void closeCallback(GObject*, GAsyncResult*, gpointer);
129a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochstatic bool startGio(ResourceHandle*, KURL);
130635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectResourceHandleInternal::~ResourceHandleInternal()
1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
133a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (m_soupRequest)
134a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        g_object_set_data(G_OBJECT(m_soupRequest.get()), "webkit-resource", 0);
135635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
136635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (m_idleHandler) {
137635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        g_source_remove(m_idleHandler);
138635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        m_idleHandler = 0;
139635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectResourceHandle::~ResourceHandle()
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
144a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    cleanupSoupRequestOperation(this, true);
145231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
146231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
147dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockvoid ResourceHandle::prepareForURL(const KURL &url)
148dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
149dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#ifdef HAVE_LIBSOUP_2_29_90
150dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    GOwnPtr<SoupURI> soupURI(soup_uri_new(url.prettyURL().utf8().data()));
151dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (!soupURI)
152dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return;
153dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    soup_session_prepare_for_uri(ResourceHandle::defaultSession(), soupURI.get());
154dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#endif
155dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
156dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
157231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block// All other kinds of redirections, except for the *304* status code
158231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block// (SOUP_STATUS_NOT_MODIFIED) which needs to be fed into WebCore, will be
159231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block// handled by soup directly.
160231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockstatic gboolean statusWillBeHandledBySoup(guint statusCode)
161231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
162231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (SOUP_STATUS_IS_TRANSPORT_ERROR(statusCode)
163231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        || (SOUP_STATUS_IS_REDIRECTION(statusCode) && (statusCode != SOUP_STATUS_NOT_MODIFIED))
164231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        || (statusCode == SOUP_STATUS_UNAUTHORIZED))
165231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return true;
166231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
167231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return false;
1688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void fillResponseFromMessage(SoupMessage* msg, ResourceResponse* response)
1718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
172dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    response->updateFromSoupMessage(msg);
1738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Called each time the message is going to be sent again except the first time.
1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// It's used mostly to let webkit know about redirects.
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void restartedCallback(SoupMessage* msg, gpointer data)
1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ResourceHandle* handle = static_cast<ResourceHandle*>(data);
1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!handle)
1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ResourceHandleInternal* d = handle->getInternal();
1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (d->m_cancelled)
1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
186a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    GOwnPtr<char> uri(soup_uri_to_string(soup_message_get_uri(msg), false));
187a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    String location = String::fromUTF8(uri.get());
188967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    KURL newURL = KURL(handle->firstRequest().url(), location);
1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
190967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    ResourceRequest request = handle->firstRequest();
1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ResourceResponse response;
1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    request.setURL(newURL);
193231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    request.setHTTPMethod(msg->method);
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    fillResponseFromMessage(msg, &response);
195643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
196643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // Should not set Referer after a redirect from a secure resource to non-secure one.
197643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (!request.url().protocolIs("https") && protocolIs(request.httpReferrer(), "https")) {
198643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        request.clearHTTPReferrer();
199643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        soup_message_headers_remove(msg->request_headers, "Referer");
200643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    }
201643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (d->client())
2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        d->client()->willSendRequest(handle, request, response);
2048a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
2056c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    if (d->m_cancelled)
2066c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen        return;
2076c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen
2088a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#ifdef HAVE_LIBSOUP_2_29_90
2098a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    // Update the first party in case the base URL changed with the redirect
2108a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    String firstPartyString = request.firstPartyForCookies().string();
2118a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    if (!firstPartyString.isEmpty()) {
2128a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        GOwnPtr<SoupURI> firstParty(soup_uri_new(firstPartyString.utf8().data()));
213a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        soup_message_set_first_party(d->m_soupMessage.get(), firstParty.get());
2148a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    }
2158a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#endif
2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
21865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochstatic void contentSniffedCallback(SoupMessage*, const char*, GHashTable*, gpointer);
21965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void gotHeadersCallback(SoupMessage* msg, gpointer data)
2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // For 401, we will accumulate the resource body, and only use it
223a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // in case authentication with the soup feature doesn't happen.
224a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // For 302 we accumulate the body too because it could be used by
225a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // some servers to redirect with a clunky http-equiv=REFRESH
226a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (statusWillBeHandledBySoup(msg->status_code)) {
2278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        soup_message_body_set_accumulate(msg->response_body, TRUE);
2288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return;
2298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
2308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // For all the other responses, we handle each chunk ourselves,
2328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // and we don't need msg->response_body to contain all of the data
2338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // we got, when we finish downloading.
2348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    soup_message_body_set_accumulate(msg->response_body, FALSE);
2358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
236231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(data);
2370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
238231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // The content-sniffed callback will handle the response if WebCore
239231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // require us to sniff.
24065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (!handle || statusWillBeHandledBySoup(msg->status_code))
241231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return;
242231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
24365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (handle->shouldContentSniff()) {
24465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        // Avoid MIME type sniffing if the response comes back as 304 Not Modified.
24565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        if (msg->status_code == SOUP_STATUS_NOT_MODIFIED) {
24665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            soup_message_disable_feature(msg, SOUP_TYPE_CONTENT_SNIFFER);
24765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            g_signal_handlers_disconnect_by_func(msg, reinterpret_cast<gpointer>(contentSniffedCallback), handle.get());
24865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        } else
24965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            return;
25065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    }
25165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch
252231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    ResourceHandleInternal* d = handle->getInternal();
253231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (d->m_cancelled)
254231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return;
255231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    ResourceHandleClient* client = handle->client();
256231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!client)
257231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return;
258231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
2594576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    ASSERT(d->m_response.isNull());
2604576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
261231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    fillResponseFromMessage(msg, &d->m_response);
262231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    client->didReceiveResponse(handle.get(), d->m_response);
2630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
2640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
265231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block// This callback will not be called if the content sniffer is disabled in startHttp.
2660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic void contentSniffedCallback(SoupMessage* msg, const char* sniffedType, GHashTable *params, gpointer data)
2670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
2680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (sniffedType) {
2690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        const char* officialType = soup_message_headers_get_one(msg->response_headers, "Content-Type");
2700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (!officialType || strcmp(officialType, sniffedType))
2720bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            soup_message_headers_set_content_type(msg->response_headers, sniffedType, params);
2730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
2740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
275231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (statusWillBeHandledBySoup(msg->status_code))
2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
2778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2785f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(data);
2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!handle)
2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ResourceHandleInternal* d = handle->getInternal();
2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (d->m_cancelled)
2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ResourceHandleClient* client = handle->client();
2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!client)
2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2884576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    ASSERT(d->m_response.isNull());
2894576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
2908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    fillResponseFromMessage(msg, &d->m_response);
2915f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    client->didReceiveResponse(handle.get(), d->m_response);
2928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void gotChunkCallback(SoupMessage* msg, SoupBuffer* chunk, gpointer data)
2958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
296231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (statusWillBeHandledBySoup(msg->status_code))
2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2995f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(data);
3008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!handle)
3018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ResourceHandleInternal* d = handle->getInternal();
3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (d->m_cancelled)
3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ResourceHandleClient* client = handle->client();
3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!client)
3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
3088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3094576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    ASSERT(!d->m_response.isNull());
3104576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
3115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    client->didReceiveData(handle.get(), chunk->data, chunk->length, false);
3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3146c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsenstatic gboolean parseDataUrl(gpointer callbackData)
3158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3166c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    ResourceHandle* handle = static_cast<ResourceHandle*>(callbackData);
3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ResourceHandleClient* client = handle->client();
3185f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    ResourceHandleInternal* d = handle->getInternal();
3195f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (d->m_cancelled)
3205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return false;
3218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    d->m_idleHandler = 0;
323635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(client);
3258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!client)
3268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return false;
3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
328967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    String url = handle->firstRequest().url().string();
3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(url.startsWith("data:", false));
3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int index = url.find(',');
3328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (index == -1) {
3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        client->cannotShowURL(handle);
3348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return false;
3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    String mediaType = url.substring(5, index - 5);
3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    bool isBase64 = mediaType.endsWith(";base64", false);
3408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (isBase64)
3418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        mediaType = mediaType.left(mediaType.length() - 7);
3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (mediaType.isEmpty())
3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        mediaType = "text/plain;charset=US-ASCII";
3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    String mimeType = extractMIMETypeFromMediaType(mediaType);
3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    String charset = extractCharsetFromMediaType(mediaType);
3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3494576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    ASSERT(d->m_response.isNull());
3504576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
3514576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    d->m_response.setURL(handle->firstRequest().url());
3524576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    d->m_response.setMimeType(mimeType);
3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
354a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // For non base64 encoded data we have to convert to UTF-16 early
355a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // due to limitations in KURL
3564576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    d->m_response.setTextEncodingName(isBase64 ? charset : "UTF-16");
3574576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    client->didReceiveResponse(handle, d->m_response);
3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
359a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // The load may be cancelled, and the client may be destroyed
360a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // by any of the client reporting calls, so we check, and bail
361a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // out in either of those cases.
362dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (d->m_cancelled || !handle->client())
363692e5dbf12901edacf14812a6fae25462920af42Steve Block        return false;
364692e5dbf12901edacf14812a6fae25462920af42Steve Block
365a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    SoupSession* session = handle->defaultSession();
366a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    GOwnPtr<GError> error;
367cad810f21b803229eb11403f9209855525a25d57Steve Block    d->m_soupRequest = adoptGRef(webkit_soup_requester_request(d->m_requester.get(), handle->firstRequest().url().string().utf8().data(), session, &error.outPtr()));
368a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (error) {
369a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        d->m_soupRequest = 0;
370a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        client->didFinishLoading(handle, 0);
371a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return false;
372a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
373a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
374cad810f21b803229eb11403f9209855525a25d57Steve Block    d->m_inputStream = adoptGRef(webkit_soup_request_send(d->m_soupRequest.get(), 0, &error.outPtr()));
375a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (error) {
376a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        d->m_inputStream = 0;
377a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        client->didFinishLoading(handle, 0);
378a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return false;
379a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
380a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
381a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    d->m_buffer = static_cast<char*>(g_slice_alloc0(READ_BUFFER_SIZE));
382a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    d->m_total = 0;
383a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
384a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    g_object_set_data(G_OBJECT(d->m_inputStream.get()), "webkit-resource", handle);
385a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // balanced by a deref() in cleanupSoupRequestOperation, which should always run
386a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    handle->ref();
387a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
388cad810f21b803229eb11403f9209855525a25d57Steve Block    d->m_cancellable = adoptGRef(g_cancellable_new());
389a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    g_input_stream_read_async(d->m_inputStream.get(), d->m_buffer, READ_BUFFER_SIZE, G_PRIORITY_DEFAULT,
390a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                              d->m_cancellable.get(), readCallback, GINT_TO_POINTER(!isBase64));
3918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return false;
3938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic bool startData(ResourceHandle* handle, String urlString)
3968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ASSERT(handle);
3980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ResourceHandleInternal* d = handle->getInternal();
400635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
401635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // If parseDataUrl is called synchronously the job is not yet effectively started
402635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // and webkit won't never know that the data has been parsed even didFinishLoading is called.
403dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    d->m_idleHandler = g_timeout_add(0, parseDataUrl, handle);
404635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return true;
4058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4078f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic SoupSession* createSoupSession()
4088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4098f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return soup_session_async_new();
4108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
4118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
412231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block// Values taken from http://stevesouders.com/ua/index.php following
413231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block// the rule "Do What Every Other Modern Browser Is Doing". They seem
414231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block// to significantly improve page loading time compared to soup's
415231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block// default values.
416231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#define MAX_CONNECTIONS          60
417231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#define MAX_CONNECTIONS_PER_HOST 6
418231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
4198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic void ensureSessionIsInitialized(SoupSession* session)
4208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
4218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (g_object_get_data(G_OBJECT(session), "webkit-init"))
4228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return;
4238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    SoupCookieJar* jar = reinterpret_cast<SoupCookieJar*>(soup_session_get_feature(session, SOUP_TYPE_COOKIE_JAR));
4258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!jar)
4268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        soup_session_add_feature(session, SOUP_SESSION_FEATURE(defaultCookieJar()));
4278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    else
4288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        setDefaultCookieJar(jar);
4298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!soup_session_get_feature(session, SOUP_TYPE_LOGGER) && LogNetwork.state == WTFLogChannelOn) {
4318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        SoupLogger* logger = soup_logger_new(static_cast<SoupLoggerLogLevel>(SOUP_LOGGER_LOG_BODY), -1);
4328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        soup_logger_attach(logger, session);
4338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        g_object_unref(logger);
4348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
436231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    g_object_set(session,
437231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                 SOUP_SESSION_MAX_CONNS, MAX_CONNECTIONS,
438231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                 SOUP_SESSION_MAX_CONNS_PER_HOST, MAX_CONNECTIONS_PER_HOST,
439231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                 NULL);
440231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
4418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    g_object_set_data(G_OBJECT(session), "webkit-init", reinterpret_cast<void*>(0xdeadbeef));
4428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
4438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
444a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochstatic void cleanupSoupRequestOperation(ResourceHandle* handle, bool isDestroying = false)
445a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
446a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ResourceHandleInternal* d = handle->getInternal();
447a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
448a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (d->m_soupRequest) {
449a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        g_object_set_data(G_OBJECT(d->m_soupRequest.get()), "webkit-resource", 0);
450a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        d->m_soupRequest.clear();
451a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
452a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
453a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (d->m_inputStream) {
454a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        g_object_set_data(G_OBJECT(d->m_inputStream.get()), "webkit-resource", 0);
455a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        d->m_inputStream.clear();
456a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
457a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
458a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    d->m_cancellable.clear();
459a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
460a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (d->m_soupMessage) {
461a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        g_signal_handlers_disconnect_matched(d->m_soupMessage.get(), G_SIGNAL_MATCH_DATA,
462a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                                             0, 0, 0, 0, handle);
463a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        d->m_soupMessage.clear();
464a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
465a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
466a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (d->m_buffer) {
467a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        g_slice_free1(READ_BUFFER_SIZE, d->m_buffer);
468a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        d->m_buffer = 0;
469a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
470a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
471a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (!isDestroying)
472a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        handle->deref();
473a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
474a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
475a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochstatic void sendRequestCallback(GObject* source, GAsyncResult* res, gpointer userData)
476a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
477a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(g_object_get_data(source, "webkit-resource"));
478a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (!handle)
479a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return;
480a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
481a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ResourceHandleInternal* d = handle->getInternal();
482a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ResourceHandleClient* client = handle->client();
483a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
484a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (d->m_gotChunkHandler) {
485a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // No need to call gotChunkHandler anymore. Received data will
486a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // be reported by readCallback
487a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (g_signal_handler_is_connected(d->m_soupMessage.get(), d->m_gotChunkHandler))
488a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            g_signal_handler_disconnect(d->m_soupMessage.get(), d->m_gotChunkHandler);
489a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
490a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
491a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (d->m_cancelled || !client) {
492a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        cleanupSoupRequestOperation(handle.get());
493a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return;
494a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
495a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
496a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    GOwnPtr<GError> error;
497a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    GInputStream* in = webkit_soup_request_send_finish(d->m_soupRequest.get(), res, &error.outPtr());
498a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
499a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (error) {
500a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        SoupMessage* soupMsg = d->m_soupMessage.get();
501a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        gboolean isTransportError = d->m_soupMessage && SOUP_STATUS_IS_TRANSPORT_ERROR(soupMsg->status_code);
502a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
503a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (isTransportError || (error->domain == G_IO_ERROR)) {
504a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            SoupURI* uri = webkit_soup_request_get_uri(d->m_soupRequest.get());
505a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            GOwnPtr<char> uriStr(soup_uri_to_string(uri, false));
506f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            gint errorCode = isTransportError ? static_cast<gint>(soupMsg->status_code) : error->code;
507a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            const gchar* errorMsg = isTransportError ? soupMsg->reason_phrase : error->message;
508a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            const gchar* quarkStr = isTransportError ? g_quark_to_string(SOUP_HTTP_ERROR) : g_quark_to_string(G_IO_ERROR);
509a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            ResourceError resourceError(quarkStr, errorCode, uriStr.get(), String::fromUTF8(errorMsg));
510a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
511a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            cleanupSoupRequestOperation(handle.get());
512a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            client->didFail(handle.get(), resourceError);
513a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            return;
514a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        }
515a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
516a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (d->m_soupMessage && statusWillBeHandledBySoup(d->m_soupMessage->status_code)) {
5174576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang            ASSERT(d->m_response.isNull());
5184576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
519a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            fillResponseFromMessage(soupMsg, &d->m_response);
520a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            client->didReceiveResponse(handle.get(), d->m_response);
521a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
522f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            // WebCore might have cancelled the job in the while. We
523f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            // must check for response_body->length and not
524f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            // response_body->data as libsoup always creates the
525f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            // SoupBuffer for the body even if the length is 0
526f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            if (!d->m_cancelled && soupMsg->response_body->length)
527a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                client->didReceiveData(handle.get(), soupMsg->response_body->data, soupMsg->response_body->length, true);
528a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        }
529a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
530a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // didReceiveData above might have cancelled it
531a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (d->m_cancelled || !client) {
532a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            cleanupSoupRequestOperation(handle.get());
533a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            return;
534a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        }
535a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
536a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        client->didFinishLoading(handle.get(), 0);
537a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return;
538a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
539a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
540a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (d->m_cancelled) {
541a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        cleanupSoupRequestOperation(handle.get());
542a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return;
543a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
544a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
545cad810f21b803229eb11403f9209855525a25d57Steve Block    d->m_inputStream = adoptGRef(in);
546a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    d->m_buffer = static_cast<char*>(g_slice_alloc0(READ_BUFFER_SIZE));
547a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    d->m_total = 0;
548a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
549a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // readCallback needs it
550a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    g_object_set_data(G_OBJECT(d->m_inputStream.get()), "webkit-resource", handle.get());
551a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
5524576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    // Ensure a response is sent for any protocols that don't explicitly support responses
5534576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    // through got-headers signal or content sniffing.
5544576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    // (e.g. file and GIO based protocol).
5554576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    if (!handle->shouldContentSniff() && d->m_response.isNull()) {
5564576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        d->m_response.setURL(handle->firstRequest().url());
5574576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        d->m_response.setMimeType(webkit_soup_request_get_content_type(d->m_soupRequest.get()));
5584576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        d->m_response.setExpectedContentLength(webkit_soup_request_get_content_length(d->m_soupRequest.get()));
5594576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        client->didReceiveResponse(handle.get(), d->m_response);
560a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
561a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (d->m_cancelled) {
562a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            cleanupSoupRequestOperation(handle.get());
563a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            return;
564a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        }
565a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
566a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
567f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (d->m_defersLoading)
568f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch         soup_session_pause_message(handle->defaultSession(), d->m_soupMessage.get());
569f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
570a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    g_input_stream_read_async(d->m_inputStream.get(), d->m_buffer, READ_BUFFER_SIZE,
571a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                              G_PRIORITY_DEFAULT, d->m_cancellable.get(), readCallback, 0);
572a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
573a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
574231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockstatic bool startHttp(ResourceHandle* handle)
5758f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
5760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ASSERT(handle);
577231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
5780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    SoupSession* session = handle->defaultSession();
5798f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    ensureSessionIsInitialized(session);
5808f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
5810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ResourceHandleInternal* d = handle->getInternal();
5820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
583967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    ResourceRequest request(handle->firstRequest());
584231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    KURL url(request.url());
585231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    url.removeFragmentIdentifier();
586231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    request.setURL(url);
587231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
588a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    GOwnPtr<GError> error;
589cad810f21b803229eb11403f9209855525a25d57Steve Block    d->m_soupRequest = adoptGRef(webkit_soup_requester_request(d->m_requester.get(), url.string().utf8().data(), session, &error.outPtr()));
590a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (error) {
591a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        d->m_soupRequest = 0;
5920bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return false;
593a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
594a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
595a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    g_object_set_data(G_OBJECT(d->m_soupRequest.get()), "webkit-resource", handle);
596a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
597cad810f21b803229eb11403f9209855525a25d57Steve Block    d->m_soupMessage = adoptGRef(webkit_soup_request_http_get_message(WEBKIT_SOUP_REQUEST_HTTP(d->m_soupRequest.get())));
598a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (!d->m_soupMessage)
599a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return false;
600a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
601a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    SoupMessage* soupMessage = d->m_soupMessage.get();
602a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    request.updateSoupMessage(soupMessage);
603231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
6046c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    if (!handle->shouldContentSniff())
605a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        soup_message_disable_feature(soupMessage, SOUP_TYPE_CONTENT_SNIFFER);
6064576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    else
6074576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang        g_signal_connect(soupMessage, "content-sniffed", G_CALLBACK(contentSniffedCallback), handle);
6080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
609a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    g_signal_connect(soupMessage, "restarted", G_CALLBACK(restartedCallback), handle);
610a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    g_signal_connect(soupMessage, "got-headers", G_CALLBACK(gotHeadersCallback), handle);
611a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    d->m_gotChunkHandler = g_signal_connect(soupMessage, "got-chunk", G_CALLBACK(gotChunkCallback), handle);
6128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
6138a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#ifdef HAVE_LIBSOUP_2_29_90
6148a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    String firstPartyString = request.firstPartyForCookies().string();
6158a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    if (!firstPartyString.isEmpty()) {
6168a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        GOwnPtr<SoupURI> firstParty(soup_uri_new(firstPartyString.utf8().data()));
617a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        soup_message_set_first_party(soupMessage, firstParty.get());
6188a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    }
6198a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block#endif
6208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
621967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    FormData* httpBody = d->m_firstRequest.httpBody();
6228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (httpBody && !httpBody->isEmpty()) {
6238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        size_t numElements = httpBody->elements().size();
6248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
6258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // handle the most common case (i.e. no file upload)
6268f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if (numElements < 2) {
6278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            Vector<char> body;
6288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            httpBody->flatten(body);
629a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            soup_message_set_request(soupMessage, d->m_firstRequest.httpContentType().utf8().data(),
6308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                                     SOUP_MEMORY_COPY, body.data(), body.size());
6318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        } else {
6328f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            /*
6338f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian             * we have more than one element to upload, and some may
6348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian             * be (big) files, which we will want to mmap instead of
6358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian             * copying into memory; TODO: support upload of non-local
6368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian             * (think sftp://) files by using GIO?
6378f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian             */
638a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            soup_message_body_set_accumulate(soupMessage->request_body, FALSE);
6398f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            for (size_t i = 0; i < numElements; i++) {
6408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                const FormDataElement& element = httpBody->elements()[i];
6418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
6428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                if (element.m_type == FormDataElement::data)
643a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                    soup_message_body_append(soupMessage->request_body, SOUP_MEMORY_TEMPORARY, element.m_data.data(), element.m_data.size());
6448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                else {
6458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                    /*
6468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                     * mapping for uploaded files code inspired by technique used in
6478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                     * libsoup's simple-httpd test
6488f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                     */
649a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                    GOwnPtr<GError> error;
650545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch                    CString fileName = fileSystemRepresentation(element.m_filename);
651a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                    GMappedFile* fileMapping = g_mapped_file_new(fileName.data(), false, &error.outPtr());
6528f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
6538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                    if (error) {
654a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                        g_signal_handlers_disconnect_matched(soupMessage, G_SIGNAL_MATCH_DATA,
6550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                                                             0, 0, 0, 0, handle);
656a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                        d->m_soupMessage.clear();
6575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
6588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                        return false;
6598f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                    }
6608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
6618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                    SoupBuffer* soupBuffer = soup_buffer_new_with_owner(g_mapped_file_get_contents(fileMapping),
6628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                                                                        g_mapped_file_get_length(fileMapping),
6630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                                                                        fileMapping,
6640bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                                                                        reinterpret_cast<GDestroyNotify>(g_mapped_file_unref));
665a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                    soup_message_body_append_buffer(soupMessage->request_body, soupBuffer);
6668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                    soup_buffer_free(soupBuffer);
6678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                }
6688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            }
6698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        }
6708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
672a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // balanced by a deref() in cleanupSoupRequestOperation, which should always run
6730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    handle->ref();
6748f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
675692e5dbf12901edacf14812a6fae25462920af42Steve Block    // Make sure we have an Accept header for subresources; some sites
676692e5dbf12901edacf14812a6fae25462920af42Steve Block    // want this to serve some of their subresources
677a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (!soup_message_headers_get_one(soupMessage->request_headers, "Accept"))
678a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        soup_message_headers_append(soupMessage->request_headers, "Accept", "*/*");
679692e5dbf12901edacf14812a6fae25462920af42Steve Block
680f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // Send the request only if it's not been explicitely deferred.
681f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!d->m_defersLoading) {
682cad810f21b803229eb11403f9209855525a25d57Steve Block        d->m_cancellable = adoptGRef(g_cancellable_new());
683f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        webkit_soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, 0);
684f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    }
6858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return true;
6878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
68968513a70bcd92384395513322f1b801e7bf9c729Steve Blockbool ResourceHandle::start(NetworkingContext* context)
6908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
691a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(!d->m_soupMessage);
6928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // The frame could be null if the ResourceHandle is not associated to any
6948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Frame, e.g. if we are downloading a file.
6958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // If the frame is not null but the page is null this must be an attempted
69668513a70bcd92384395513322f1b801e7bf9c729Steve Block    // load from an unload handler, so let's just block it.
69768513a70bcd92384395513322f1b801e7bf9c729Steve Block    // If both the frame and the page are not null the context is valid.
69868513a70bcd92384395513322f1b801e7bf9c729Steve Block    if (context && !context->isValid())
6998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
7008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
701e14391e94c850b8bd03680c23b38978db68687a8John Reck    if (!(d->m_user.isEmpty() || d->m_pass.isEmpty())) {
702e14391e94c850b8bd03680c23b38978db68687a8John Reck        // If credentials were specified for this request, add them to the url,
703e14391e94c850b8bd03680c23b38978db68687a8John Reck        // so that they will be passed to NetworkRequest.
704e14391e94c850b8bd03680c23b38978db68687a8John Reck        KURL urlWithCredentials(firstRequest().url());
705e14391e94c850b8bd03680c23b38978db68687a8John Reck        urlWithCredentials.setUser(d->m_user);
706e14391e94c850b8bd03680c23b38978db68687a8John Reck        urlWithCredentials.setPass(d->m_pass);
707e14391e94c850b8bd03680c23b38978db68687a8John Reck        d->m_firstRequest.setURL(urlWithCredentials);
708e14391e94c850b8bd03680c23b38978db68687a8John Reck    }
709e14391e94c850b8bd03680c23b38978db68687a8John Reck
710967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    KURL url = firstRequest().url();
7118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    String urlString = url.string();
7128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    String protocol = url.protocol();
7138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Used to set the authentication dialog toplevel; may be NULL
71568513a70bcd92384395513322f1b801e7bf9c729Steve Block    d->m_context = context;
7168f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
7178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (equalIgnoringCase(protocol, "data"))
7180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return startData(this, urlString);
7198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
720231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (equalIgnoringCase(protocol, "http") || equalIgnoringCase(protocol, "https")) {
721231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (startHttp(this))
722231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return true;
723231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
7248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
725231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (equalIgnoringCase(protocol, "file") || equalIgnoringCase(protocol, "ftp") || equalIgnoringCase(protocol, "ftps")) {
7268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // FIXME: should we be doing any other protocols here?
727231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (startGio(this, url))
728231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return true;
729231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
7308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
7315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // Error must not be reported immediately
7325f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    this->scheduleFailure(InvalidURLFailure);
7335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
7348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return true;
7358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ResourceHandle::cancel()
7388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    d->m_cancelled = true;
740a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (d->m_soupMessage)
741a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        soup_session_cancel_message(defaultSession(), d->m_soupMessage.get(), SOUP_STATUS_CANCELLED);
7428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    else if (d->m_cancellable)
743a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        g_cancellable_cancel(d->m_cancellable.get());
7448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectPassRefPtr<SharedBuffer> ResourceHandle::bufferedData()
7478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT_NOT_REACHED();
7498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
7508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool ResourceHandle::supportsBufferedData()
7538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return false;
7558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
757f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid ResourceHandle::platformSetDefersLoading(bool defersLoading)
7588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
759f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // Initial implementation of this method was required for bug #44157.
760f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
761f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (d->m_cancelled)
762f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return;
763f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
764f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!defersLoading && !d->m_cancellable && d->m_soupRequest.get()) {
765cad810f21b803229eb11403f9209855525a25d57Steve Block        d->m_cancellable = adoptGRef(g_cancellable_new());
766f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        webkit_soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, 0);
767f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return;
768f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    }
769f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
770f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // Only supported for http(s) transfers. Something similar would
771f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // probably be needed for data transfers done with GIO.
772f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!d->m_soupMessage)
773f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return;
774f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
775f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (defersLoading)
776f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        soup_session_pause_message(defaultSession(), d->m_soupMessage.get());
777f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    else
778f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        soup_session_unpause_message(defaultSession(), d->m_soupMessage.get());
7798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool ResourceHandle::loadsBlocked()
7828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return false;
7848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochbool ResourceHandle::willLoadFromCache(ResourceRequest&, Frame*)
7878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Not having this function means that we'll ask the user about re-posting a form
7898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // even when we go back to a page that's still in the cache.
7908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    notImplemented();
7918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return false;
7928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
79468513a70bcd92384395513322f1b801e7bf9c729Steve Blockvoid ResourceHandle::loadResourceSynchronously(NetworkingContext* context, const ResourceRequest& request, StoredCredentials /*storedCredentials*/, ResourceError& error, ResourceResponse& response, Vector<char>& data)
7958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    WebCoreSynchronousLoader syncLoader(error, response, data);
797e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    // FIXME: we should use the ResourceHandle::create method here,
798e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    // but it makes us timeout in a couple of tests. See
799e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    // https://bugs.webkit.org/show_bug.cgi?id=41823
800f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    RefPtr<ResourceHandle> handle = adoptRef(new ResourceHandle(request, &syncLoader, false /*defersLoading*/, false /*shouldContentSniff*/));
80168513a70bcd92384395513322f1b801e7bf9c729Steve Block    handle->start(context);
8028f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
8038f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    syncLoader.run();
8048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
806635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectstatic void closeCallback(GObject* source, GAsyncResult* res, gpointer)
8078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
808231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(g_object_get_data(source, "webkit-resource"));
809635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (!handle)
810635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return;
811635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
8128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ResourceHandleInternal* d = handle->getInternal();
8138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ResourceHandleClient* client = handle->client();
8148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
815a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    g_input_stream_close_finish(d->m_inputStream.get(), res, 0);
816a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    cleanupSoupRequestOperation(handle.get());
817643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
818643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // The load may have been cancelled, the client may have been
819643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // destroyed already. In such cases calling didFinishLoading is a
820643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    // bad idea.
821643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    if (d->m_cancelled || !client)
822643ca7872b450ea4efacab6188849e5aac2ba161Steve Block        return;
823643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
82468513a70bcd92384395513322f1b801e7bf9c729Steve Block    client->didFinishLoading(handle.get(), 0);
8258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
827a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochstatic void readCallback(GObject* source, GAsyncResult* asyncResult, gpointer data)
8288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    RefPtr<ResourceHandle> handle = static_cast<ResourceHandle*>(g_object_get_data(source, "webkit-resource"));
830635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (!handle)
831635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return;
832635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
833a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    bool convertToUTF16 = static_cast<bool>(data);
8348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ResourceHandleInternal* d = handle->getInternal();
8358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ResourceHandleClient* client = handle->client();
8368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (d->m_cancelled || !client) {
838a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        cleanupSoupRequestOperation(handle.get());
8398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
8408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
8418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
842a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    GOwnPtr<GError> error;
8438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
844a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    gssize bytesRead = g_input_stream_read_finish(d->m_inputStream.get(), asyncResult, &error.outPtr());
8458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (error) {
846a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        SoupURI* uri = webkit_soup_request_get_uri(d->m_soupRequest.get());
847a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        GOwnPtr<char> uriStr(soup_uri_to_string(uri, false));
848a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ResourceError resourceError(g_quark_to_string(G_IO_ERROR), error->code, uriStr.get(),
8495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                                    error ? String::fromUTF8(error->message) : String());
850a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        cleanupSoupRequestOperation(handle.get());
8518f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        client->didFail(handle.get(), resourceError);
8528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
8538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
8548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
8558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!bytesRead) {
856a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        g_input_stream_close_async(d->m_inputStream.get(), G_PRIORITY_DEFAULT,
8578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                                   0, closeCallback, 0);
8588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
8598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
8608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8614576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    // It's mandatory to have sent a response before sending data
8624576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang    ASSERT(!d->m_response.isNull());
8634576aa36e9a9671459299c7963ac95aa94beaea9Shimeng (Simon) Wang
8648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    d->m_total += bytesRead;
865a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (G_LIKELY(!convertToUTF16))
866a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        client->didReceiveData(handle.get(), d->m_buffer, bytesRead, d->m_total);
867a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    else {
868a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // We have to convert it to UTF-16 due to limitations in KURL
869a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        String data = String::fromUTF8(d->m_buffer, bytesRead);
870a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        client->didReceiveData(handle.get(), reinterpret_cast<const char*>(data.characters()), data.length() * sizeof(UChar), 0);
8718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
8728f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
873a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // didReceiveData may cancel the load, which may release the last reference.
8748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (d->m_cancelled || !client) {
875a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        cleanupSoupRequestOperation(handle.get());
8768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
8778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
8788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
879a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    g_input_stream_read_async(d->m_inputStream.get(), d->m_buffer, READ_BUFFER_SIZE, G_PRIORITY_DEFAULT,
880a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                              d->m_cancellable.get(), readCallback, data);
8818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochstatic bool startGio(ResourceHandle* handle, KURL url)
8848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8850bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ASSERT(handle);
8860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
887967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    if (handle->firstRequest().httpMethod() != "GET" && handle->firstRequest().httpMethod() != "POST")
8888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
8898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
890a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    SoupSession* session = handle->defaultSession();
891a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ResourceHandleInternal* d = handle->getInternal();
892a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
8938f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // GIO doesn't know how to handle refs and queries, so remove them
8948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // TODO: use KURL.fileSystemPath after KURLGtk and FileSystemGtk are
8958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // using GIO internally, and providing URIs instead of file paths
8960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    url.removeFragmentIdentifier();
8978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    url.setQuery(String());
898643ca7872b450ea4efacab6188849e5aac2ba161Steve Block    url.removePort();
899a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    CString urlStr = url.string().utf8();
9008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
901a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    GOwnPtr<GError> error;
902cad810f21b803229eb11403f9209855525a25d57Steve Block    d->m_soupRequest = adoptGRef(webkit_soup_requester_request(d->m_requester.get(), urlStr.data(), session, &error.outPtr()));
903a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (error) {
904a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        d->m_soupRequest = 0;
905a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return false;
906a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
907a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
908a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    g_object_set_data(G_OBJECT(d->m_soupRequest.get()), "webkit-resource", handle);
909231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
910a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // balanced by a deref() in cleanupSoupRequestOperation, which should always run
911231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    handle->ref();
912231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
913cad810f21b803229eb11403f9209855525a25d57Steve Block    d->m_cancellable = adoptGRef(g_cancellable_new());
914a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    webkit_soup_request_send_async(d->m_soupRequest.get(), d->m_cancellable.get(), sendRequestCallback, 0);
915a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
9168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return true;
9178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianSoupSession* ResourceHandle::defaultSession()
9208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
9216c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen    static SoupSession* session = createSoupSession();
9228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
9238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    return session;
9248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
9258f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
9268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
927