18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
28e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2004, 2006 Apple Computer, Inc.  All rights reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2007 Alp Toker <alp@atoker.com>
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2007 Holger Hans Peter Freyther
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2008 Collabora Ltd.
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Copyright (C) 2008 Nuanti Ltd.
8231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * Copyright (C) 2009 Appcelerator Inc.
9231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * Copyright (C) 2009 Brent Fulgham <bfulgham@webkit.org>
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * All rights reserved.
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    documentation and/or other materials provided with the distribution.
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ResourceHandleManager.h"
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
37a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "DataURL.h"
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTTPParsers.h"
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "MIMETypeRegistry.h"
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "NotImplemented.h"
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ResourceError.h"
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ResourceHandle.h"
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ResourceHandleInternal.h"
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <errno.h>
46635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include <stdio.h>
4781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#if USE(CF)
48dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include <wtf/RetainPtr.h>
496c2af9490927c3c5959b5cb07461b646f8b32f6cKristian Monsen#endif
50231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include <wtf/Threading.h>
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/Vector.h>
52dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include <wtf/text/CString.h>
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
54d0825bca7fe65beaee391d30da42e937db621564Steve Block#if !OS(WINDOWS)
55643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#include <sys/param.h>
56643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#define MAX_PATH MAXPATHLEN
57643ca7872b450ea4efacab6188849e5aac2ba161Steve Block#endif
58643ca7872b450ea4efacab6188849e5aac2ba161Steve Block
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectconst int selectTimeoutMS = 5;
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectconst double pollTimeSeconds = 0.05;
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectconst int maxRunningJobs = 5;
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic const bool ignoreSSLErrors = getenv("WEBKIT_IGNORE_SSL_ERRORS");
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
67231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockstatic CString certificatePath()
68231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
6981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch#if USE(CF)
70231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    CFBundleRef webKitBundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.WebKit"));
71231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (webKitBundle) {
72231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        RetainPtr<CFURLRef> certURLRef(AdoptCF, CFBundleCopyResourceURL(webKitBundle, CFSTR("cacert"), CFSTR("pem"), CFSTR("certificates")));
73231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (certURLRef) {
74231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            char path[MAX_PATH];
75231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            CFURLGetFileSystemRepresentation(certURLRef.get(), false, reinterpret_cast<UInt8*>(path), MAX_PATH);
76231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return path;
77231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        }
78231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
79231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#endif
80231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    char* envPath = getenv("CURL_CA_BUNDLE_PATH");
81231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (envPath)
82231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block       return envPath;
83231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
84231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return CString();
85231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
86231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
87231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockstatic Mutex* sharedResourceMutex(curl_lock_data data) {
88231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    DEFINE_STATIC_LOCAL(Mutex, cookieMutex, ());
89231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    DEFINE_STATIC_LOCAL(Mutex, dnsMutex, ());
90231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    DEFINE_STATIC_LOCAL(Mutex, shareMutex, ());
91231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
92231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    switch (data) {
93231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        case CURL_LOCK_DATA_COOKIE:
94231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return &cookieMutex;
95231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        case CURL_LOCK_DATA_DNS:
96231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return &dnsMutex;
97231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        case CURL_LOCK_DATA_SHARE:
98231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return &shareMutex;
99231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        default:
100231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            ASSERT_NOT_REACHED();
101231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return NULL;
102231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
103231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
104231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
105231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block// libcurl does not implement its own thread synchronization primitives.
106231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block// these two functions provide mutexes for cookies, and for the global DNS
107231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block// cache.
108231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockstatic void curl_lock_callback(CURL* handle, curl_lock_data data, curl_lock_access access, void* userPtr)
109231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
110231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (Mutex* mutex = sharedResourceMutex(data))
111231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        mutex->lock();
112231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
113231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
114231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockstatic void curl_unlock_callback(CURL* handle, curl_lock_data data, void* userPtr)
115231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
116231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (Mutex* mutex = sharedResourceMutex(data))
117231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        mutex->unlock();
118231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
119231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
1208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectResourceHandleManager::ResourceHandleManager()
1218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    : m_downloadTimer(this, &ResourceHandleManager::downloadTimerCallback)
1228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_cookieJarFileName(0)
123231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    , m_certificatePath (certificatePath())
124a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    , m_runningJobs(0)
125a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
1268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    curl_global_init(CURL_GLOBAL_ALL);
1288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_curlMultiHandle = curl_multi_init();
1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_curlShareHandle = curl_share_init();
1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    curl_share_setopt(m_curlShareHandle, CURLSHOPT_SHARE, CURL_LOCK_DATA_COOKIE);
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    curl_share_setopt(m_curlShareHandle, CURLSHOPT_SHARE, CURL_LOCK_DATA_DNS);
132231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    curl_share_setopt(m_curlShareHandle, CURLSHOPT_LOCKFUNC, curl_lock_callback);
133231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    curl_share_setopt(m_curlShareHandle, CURLSHOPT_UNLOCKFUNC, curl_unlock_callback);
1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectResourceHandleManager::~ResourceHandleManager()
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    curl_multi_cleanup(m_curlMultiHandle);
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    curl_share_cleanup(m_curlShareHandle);
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_cookieJarFileName)
1418a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        fastFree(m_cookieJarFileName);
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    curl_global_cleanup();
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ResourceHandleManager::setCookieJarFileName(const char* cookieJarFileName)
1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1478a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    m_cookieJarFileName = fastStrDup(cookieJarFileName);
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectResourceHandleManager* ResourceHandleManager::sharedInstance()
1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static ResourceHandleManager* sharedInstance = 0;
1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!sharedInstance)
1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        sharedInstance = new ResourceHandleManager();
1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return sharedInstance;
1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
158231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockstatic void handleLocalReceiveResponse (CURL* handle, ResourceHandle* job, ResourceHandleInternal* d)
159231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
160231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // since the code in headerCallback will not have run for local files
161231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // the code to set the URL and fire didReceiveResponse is never run,
162231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // which means the ResourceLoader's response does not contain the URL.
163231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // Run the code here for local files to resolve the issue.
164231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // TODO: See if there is a better approach for handling this.
165231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block     const char* hdr;
166231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block     CURLcode err = curl_easy_getinfo(handle, CURLINFO_EFFECTIVE_URL, &hdr);
167a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch     ASSERT_UNUSED(err, CURLE_OK == err);
168231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block     d->m_response.setURL(KURL(ParsedURLString, hdr));
169231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block     if (d->client())
170231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block         d->client()->didReceiveResponse(job, d->m_response);
171231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block     d->m_response.setResponseFired(true);
172231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
173231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
174231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// called with data after all headers have been processed via headerCallback
1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic size_t writeCallback(void* ptr, size_t size, size_t nmemb, void* data)
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ResourceHandle* job = static_cast<ResourceHandle*>(data);
1798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ResourceHandleInternal* d = job->getInternal();
1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (d->m_cancelled)
1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if LIBCURL_VERSION_NUM > 0x071200
1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // We should never be called when deferred loading is activated.
1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(!d->m_defersLoading);
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    size_t totalSize = size * nmemb;
1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // this shouldn't be necessary but apparently is. CURL writes the data
1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // of html page even if it is a redirect that was handled internally
1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // can be observed e.g. on gmail.com
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    CURL* h = d->m_handle;
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    long httpCode = 0;
1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    CURLcode err = curl_easy_getinfo(h, CURLINFO_RESPONSE_CODE, &httpCode);
1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (CURLE_OK == err && httpCode >= 300 && httpCode < 400)
1978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return totalSize;
1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!d->m_response.responseFired()) {
200231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        handleLocalReceiveResponse(h, job, d);
201231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        if (d->m_cancelled)
202231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            return 0;
2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (d->client())
2068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        d->client()->didReceiveData(job, static_cast<char*>(ptr), totalSize, 0);
2078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return totalSize;
2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * This is being called for each HTTP header in the response. This includes '\r\n'
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * for the last line of the header.
2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * We will add each HTTP Header to the ResourceResponse and on the termination
2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * of the header (\r\n) we will parse Content-Type and Content-Disposition and
2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * update the ResourceResponse and then send it away.
2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic size_t headerCallback(char* ptr, size_t size, size_t nmemb, void* data)
2208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ResourceHandle* job = static_cast<ResourceHandle*>(data);
2228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ResourceHandleInternal* d = job->getInternal();
2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (d->m_cancelled)
2248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if LIBCURL_VERSION_NUM > 0x071200
2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // We should never be called when deferred loading is activated.
2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(!d->m_defersLoading);
2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
2308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    size_t totalSize = size * nmemb;
2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ResourceHandleClient* client = d->client();
2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    String header(static_cast<const char*>(ptr), totalSize);
2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    /*
2378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project     * a) We can finish and send the ResourceResponse
2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project     * b) We will add the current header to the HTTPHeaderMap of the ResourceResponse
2398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project     *
2408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project     * The HTTP standard requires to use \r\n but for compatibility it recommends to
2418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project     * accept also \n.
2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project     */
2438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (header == String("\r\n") || header == String("\n")) {
2448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        CURL* h = d->m_handle;
2458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        CURLcode err;
2468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        double contentLength = 0;
2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        err = curl_easy_getinfo(h, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &contentLength);
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        d->m_response.setExpectedContentLength(static_cast<long long int>(contentLength));
2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        const char* hdr;
2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        err = curl_easy_getinfo(h, CURLINFO_EFFECTIVE_URL, &hdr);
253231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        d->m_response.setURL(KURL(ParsedURLString, hdr));
2548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        long httpCode = 0;
2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        err = curl_easy_getinfo(h, CURLINFO_RESPONSE_CODE, &httpCode);
2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        d->m_response.setHTTPStatusCode(httpCode);
2588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        d->m_response.setMimeType(extractMIMETypeFromMediaType(d->m_response.httpHeaderField("Content-Type")));
2608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        d->m_response.setTextEncodingName(extractCharsetFromMediaType(d->m_response.httpHeaderField("Content-Type")));
2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        d->m_response.setSuggestedFilename(filenameFromHTTPContentDisposition(d->m_response.httpHeaderField("Content-Disposition")));
2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // HTTP redirection
2648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (httpCode >= 300 && httpCode < 400) {
2658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            String location = d->m_response.httpHeaderField("location");
2668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (!location.isEmpty()) {
267967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch                KURL newURL = KURL(job->firstRequest().url(), location);
2688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
269967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch                ResourceRequest redirectedRequest = job->firstRequest();
2708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                redirectedRequest.setURL(newURL);
2718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (client)
2728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    client->willSendRequest(job, redirectedRequest, d->m_response);
2738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
274967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch                d->m_firstRequest.setURL(newURL);
2758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return totalSize;
2778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
2788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (client)
2818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            client->didReceiveResponse(job, d->m_response);
2828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        d->m_response.setResponseFired(true);
2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
2858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        int splitPos = header.find(":");
2868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (splitPos != -1)
2878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            d->m_response.setHTTPHeaderField(header.left(splitPos), header.substring(splitPos+1).stripWhiteSpace());
2888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return totalSize;
2918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* This is called to obtain HTTP POST or PUT data.
2948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project   Iterate through FormData elements and upload files.
2958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project   Carefully respect the given buffer size and fill the rest of the data at the next calls.
2968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project*/
2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectsize_t readCallback(void* ptr, size_t size, size_t nmemb, void* data)
2988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ResourceHandle* job = static_cast<ResourceHandle*>(data);
3008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ResourceHandleInternal* d = job->getInternal();
301231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
3028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (d->m_cancelled)
3038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
3048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if LIBCURL_VERSION_NUM > 0x071200
3068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // We should never be called when deferred loading is activated.
3078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(!d->m_defersLoading);
3088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
3098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!size || !nmemb)
3118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
3128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!d->m_formDataStream.hasMoreElements())
3148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
3158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    size_t sent = d->m_formDataStream.read(ptr, size, nmemb);
3178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Something went wrong so cancel the job.
3198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!sent)
3208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        job->cancel();
3218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return sent;
3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ResourceHandleManager::downloadTimerCallback(Timer<ResourceHandleManager>* timer)
3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    startScheduledJobs();
3288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    fd_set fdread;
3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    fd_set fdwrite;
3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    fd_set fdexcep;
3328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int maxfd = 0;
3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    struct timeval timeout;
3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    timeout.tv_sec = 0;
3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    timeout.tv_usec = selectTimeoutMS * 1000;       // select waits microseconds
3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
338635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // Retry 'select' if it was interrupted by a process signal.
3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int rc = 0;
3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    do {
3418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        FD_ZERO(&fdread);
3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        FD_ZERO(&fdwrite);
3438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        FD_ZERO(&fdexcep);
3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        curl_multi_fdset(m_curlMultiHandle, &fdread, &fdwrite, &fdexcep, &maxfd);
3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // When the 3 file descriptors are empty, winsock will return -1
3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // and bail out, stopping the file download. So make sure we
3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // have valid file descriptors before calling select.
3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (maxfd >= 0)
3498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            rc = ::select(maxfd + 1, &fdread, &fdwrite, &fdexcep, &timeout);
3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } while (rc == -1 && errno == EINTR);
3518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (-1 == rc) {
3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifndef NDEBUG
3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        perror("bad: select() returned -1: ");
3558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
3568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int runningHandles = 0;
3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (curl_multi_perform(m_curlMultiHandle, &runningHandles) == CURLM_CALL_MULTI_PERFORM) { }
3618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // check the curl messages indicating completed transfers
3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // and free their resources
3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (true) {
3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        int messagesInQueue;
3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        CURLMsg* msg = curl_multi_info_read(m_curlMultiHandle, &messagesInQueue);
3678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!msg)
3688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            break;
3698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // find the node which has same d->m_handle as completed transfer
3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        CURL* handle = msg->easy_handle;
3728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(handle);
3738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ResourceHandle* job = 0;
3748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        CURLcode err = curl_easy_getinfo(handle, CURLINFO_PRIVATE, &job);
375a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT_UNUSED(err, CURLE_OK == err);
3768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(job);
3778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!job)
3788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
3798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ResourceHandleInternal* d = job->getInternal();
3808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(d->m_handle == handle);
3818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (d->m_cancelled) {
3838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            removeFromCurl(job);
3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
3858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (CURLMSG_DONE != msg->msg)
3888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            continue;
3898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (CURLE_OK == msg->data.result) {
391231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            if (!d->m_response.responseFired()) {
392231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                handleLocalReceiveResponse(d->m_handle, job, d);
393231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                if (d->m_cancelled) {
394231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                    removeFromCurl(job);
395231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                    continue;
396231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                }
397231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            }
398231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
3998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (d->client())
40068513a70bcd92384395513322f1b801e7bf9c729Steve Block                d->client()->didFinishLoading(job, 0);
4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else {
4028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            char* url = 0;
4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            curl_easy_getinfo(d->m_handle, CURLINFO_EFFECTIVE_URL, &url);
4045f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian#ifndef NDEBUG
405635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            fprintf(stderr, "Curl ERROR for url='%s', error: '%s'\n", url, curl_easy_strerror(msg->data.result));
4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
4078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (d->client())
4085f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                d->client()->didFail(job, ResourceError(String(), msg->data.result, String(url), String(curl_easy_strerror(msg->data.result))));
4098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        removeFromCurl(job);
4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool started = startScheduledJobs(); // new jobs might have been added in the meantime
4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!m_downloadTimer.isActive() && (started || (runningHandles > 0)))
4178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_downloadTimer.startOneShot(pollTimeSeconds);
4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
420cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Blockvoid ResourceHandleManager::setProxyInfo(const String& host,
421cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block                                         unsigned long port,
422cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block                                         ProxyType type,
423cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block                                         const String& username,
424cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block                                         const String& password)
425cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block{
426cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    m_proxyType = type;
427cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
428cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (!host.length()) {
429cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        m_proxy = String("");
430cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    } else {
431cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        String userPass;
432cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        if (username.length() || password.length())
433cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block            userPass = username + ":" + password + "@";
434cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
435cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        m_proxy = String("http://") + userPass + host + ":" + String::number(port);
436cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    }
437cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block}
438cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ResourceHandleManager::removeFromCurl(ResourceHandle* job)
4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ResourceHandleInternal* d = job->getInternal();
4428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(d->m_handle);
4438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!d->m_handle)
4448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
4458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_runningJobs--;
4468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    curl_multi_remove_handle(m_curlMultiHandle, d->m_handle);
4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    curl_easy_cleanup(d->m_handle);
4488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    d->m_handle = 0;
449635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    job->deref();
4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ResourceHandleManager::setupPUT(ResourceHandle*, struct curl_slist**)
4538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    notImplemented();
4558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/* Calculate the length of the POST.
4588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project   Force chunked data transfer if size of files can't be obtained.
4598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
4608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ResourceHandleManager::setupPOST(ResourceHandle* job, struct curl_slist** headers)
4618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ResourceHandleInternal* d = job->getInternal();
463635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    curl_easy_setopt(d->m_handle, CURLOPT_POST, TRUE);
464635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    curl_easy_setopt(d->m_handle, CURLOPT_POSTFIELDSIZE, 0);
465635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
466967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    if (!job->firstRequest().httpBody())
467635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return;
4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
469967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    Vector<FormDataElement> elements = job->firstRequest().httpBody()->elements();
470635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    size_t numElements = elements.size();
4718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!numElements)
4728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
4738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Do not stream for simple POST data
4758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (numElements == 1) {
476967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch        job->firstRequest().httpBody()->flatten(d->m_postBytes);
4778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (d->m_postBytes.size() != 0) {
4788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            curl_easy_setopt(d->m_handle, CURLOPT_POSTFIELDSIZE, d->m_postBytes.size());
4798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            curl_easy_setopt(d->m_handle, CURLOPT_POSTFIELDS, d->m_postBytes.data());
4808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
4818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
4828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Obtain the total size of the POST
4858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // The size of a curl_off_t could be different in WebKit and in cURL depending on
4868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // compilation flags of both. For CURLOPT_POSTFIELDSIZE_LARGE we have to pass the
4878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // right size or random data will be used as the size.
4888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static int expectedSizeOfCurlOffT = 0;
4898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!expectedSizeOfCurlOffT) {
4908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        curl_version_info_data *infoData = curl_version_info(CURLVERSION_NOW);
4918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (infoData->features & CURL_VERSION_LARGEFILE)
4928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            expectedSizeOfCurlOffT = sizeof(long long);
4938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        else
4948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            expectedSizeOfCurlOffT = sizeof(int);
4958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if COMPILER(MSVC)
4988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // work around compiler error in Visual Studio 2005.  It can't properly
4998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // handle math with 64-bit constant declarations.
5008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#pragma warning(disable: 4307)
5018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
5028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    static const long long maxCurlOffT = (1LL << (expectedSizeOfCurlOffT * 8 - 1)) - 1;
5038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    curl_off_t size = 0;
5048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool chunkedTransfer = false;
5058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (size_t i = 0; i < numElements; i++) {
5068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        FormDataElement element = elements[i];
5078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (element.m_type == FormDataElement::encodedFile) {
5088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            long long fileSizeResult;
5098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (getFileSize(element.m_filename, fileSizeResult)) {
5108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                if (fileSizeResult > maxCurlOffT) {
5118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    // File size is too big for specifying it to cURL
5128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    chunkedTransfer = true;
5138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                    break;
5148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                }
5158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                size += fileSizeResult;
5168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            } else {
5178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                chunkedTransfer = true;
5188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                break;
5198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
5208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else
5218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            size += elements[i].m_data.size();
5228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // cURL guesses that we want chunked encoding as long as we specify the header
5258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (chunkedTransfer)
5268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        *headers = curl_slist_append(*headers, "Transfer-Encoding: chunked");
5278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    else {
5288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (sizeof(long long) == expectedSizeOfCurlOffT)
5298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project          curl_easy_setopt(d->m_handle, CURLOPT_POSTFIELDSIZE_LARGE, (long long)size);
5308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        else
5318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project          curl_easy_setopt(d->m_handle, CURLOPT_POSTFIELDSIZE_LARGE, (int)size);
5328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    curl_easy_setopt(d->m_handle, CURLOPT_READFUNCTION, readCallback);
5358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    curl_easy_setopt(d->m_handle, CURLOPT_READDATA, job);
5368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ResourceHandleManager::add(ResourceHandle* job)
5398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // we can be called from within curl, so to avoid re-entrancy issues
5418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // schedule this job to be added the next time we enter curl download loop
542635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    job->ref();
5438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_resourceHandleList.append(job);
5448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!m_downloadTimer.isActive())
5458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_downloadTimer.startOneShot(pollTimeSeconds);
5468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool ResourceHandleManager::removeScheduledJob(ResourceHandle* job)
5498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    int size = m_resourceHandleList.size();
5518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (int i = 0; i < size; i++) {
5528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (job == m_resourceHandleList[i]) {
5538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_resourceHandleList.remove(i);
554635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            job->deref();
5558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return true;
5568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
5578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return false;
5598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool ResourceHandleManager::startScheduledJobs()
5628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // TODO: Create a separate stack of jobs for each domain.
5648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool started = false;
5668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    while (!m_resourceHandleList.isEmpty() && m_runningJobs < maxRunningJobs) {
5678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ResourceHandle* job = m_resourceHandleList[0];
5688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_resourceHandleList.remove(0);
5698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        startJob(job);
5708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        started = true;
5718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return started;
5738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ResourceHandleManager::dispatchSynchronousJob(ResourceHandle* job)
5768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
577967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    KURL kurl = job->firstRequest().url();
5788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
579a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (kurl.protocolIsData()) {
580a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        handleDataURL(job);
5818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
5828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ResourceHandleInternal* handle = job->getInternal();
5858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if LIBCURL_VERSION_NUM > 0x071200
5878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // If defersLoading is true and we call curl_easy_perform
5888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // on a paused handle, libcURL would do the transfert anyway
5898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // and we would assert so force defersLoading to be false.
5908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    handle->m_defersLoading = false;
5918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
5928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    initializeHandle(job);
5948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // curl_easy_perform blocks until the transfert is finished.
5968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    CURLcode ret =  curl_easy_perform(handle->m_handle);
5978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (ret != 0) {
5998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ResourceError error(String(handle->m_url), ret, String(handle->m_url), String(curl_easy_strerror(ret)));
6008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        handle->client()->didFail(job, error);
6018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    curl_easy_cleanup(handle->m_handle);
6048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ResourceHandleManager::startJob(ResourceHandle* job)
6078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
608967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    KURL kurl = job->firstRequest().url();
6098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
610a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (kurl.protocolIsData()) {
611a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        handleDataURL(job);
6128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
6138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    initializeHandle(job);
6168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_runningJobs++;
6188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    CURLMcode ret = curl_multi_add_handle(m_curlMultiHandle, job->getInternal()->m_handle);
6198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // don't call perform, because events must be async
6208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // timeout will occur and do curl_multi_perform
6218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (ret && ret != CURLM_CALL_MULTI_PERFORM) {
6228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifndef NDEBUG
623967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch        fprintf(stderr, "Error %d starting job %s\n", ret, encodeWithURLEscapeSequences(job->firstRequest().url().string()).latin1().data());
6248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
6258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        job->cancel();
6268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
6278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ResourceHandleManager::initializeHandle(ResourceHandle* job)
6318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
632967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    KURL kurl = job->firstRequest().url();
6338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Remove any fragment part, otherwise curl will send it as part of the request.
6350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    kurl.removeFragmentIdentifier();
6368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ResourceHandleInternal* d = job->getInternal();
6388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    String url = kurl.string();
6398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (kurl.isLocalFile()) {
6418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        String query = kurl.query();
6428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Remove any query part sent to a local file.
6435f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        if (!query.isEmpty()) {
6445f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            int queryIndex = url.find(query);
6455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            if (queryIndex != -1)
6465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian                url = url.left(queryIndex - 1);
6475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        }
6488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Determine the MIME type based on the path.
6498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        d->m_response.setMimeType(MIMETypeRegistry::getMIMETypeForPath(url));
6508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    d->m_handle = curl_easy_init();
6538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
654d0825bca7fe65beaee391d30da42e937db621564Steve Block#if LIBCURL_VERSION_NUM > 0x071200
6558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (d->m_defersLoading) {
6568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        CURLcode error = curl_easy_pause(d->m_handle, CURLPAUSE_ALL);
6578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // If we did not pause the handle, we would ASSERT in the
6588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // header callback. So just assert here.
659a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT_UNUSED(error, error == CURLE_OK);
6608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
6628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#ifndef NDEBUG
6638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (getenv("DEBUG_CURL"))
6648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        curl_easy_setopt(d->m_handle, CURLOPT_VERBOSE, 1);
6658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
6668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    curl_easy_setopt(d->m_handle, CURLOPT_PRIVATE, job);
6678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    curl_easy_setopt(d->m_handle, CURLOPT_ERRORBUFFER, m_curlErrorBuffer);
6688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    curl_easy_setopt(d->m_handle, CURLOPT_WRITEFUNCTION, writeCallback);
6698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    curl_easy_setopt(d->m_handle, CURLOPT_WRITEDATA, job);
6708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    curl_easy_setopt(d->m_handle, CURLOPT_HEADERFUNCTION, headerCallback);
6718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    curl_easy_setopt(d->m_handle, CURLOPT_WRITEHEADER, job);
6728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    curl_easy_setopt(d->m_handle, CURLOPT_AUTOREFERER, 1);
6738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    curl_easy_setopt(d->m_handle, CURLOPT_FOLLOWLOCATION, 1);
6748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    curl_easy_setopt(d->m_handle, CURLOPT_MAXREDIRS, 10);
6758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    curl_easy_setopt(d->m_handle, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
6768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    curl_easy_setopt(d->m_handle, CURLOPT_SHARE, m_curlShareHandle);
6778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    curl_easy_setopt(d->m_handle, CURLOPT_DNS_CACHE_TIMEOUT, 60 * 5); // 5 minutes
6788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: Enable SSL verification when we have a way of shipping certs
6798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // and/or reporting SSL errors to the user.
6808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (ignoreSSLErrors)
6818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        curl_easy_setopt(d->m_handle, CURLOPT_SSL_VERIFYPEER, false);
682231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
683231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (!m_certificatePath.isNull())
684231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block       curl_easy_setopt(d->m_handle, CURLOPT_CAINFO, m_certificatePath.data());
685231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
6868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // enable gzip and deflate through Accept-Encoding:
6878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    curl_easy_setopt(d->m_handle, CURLOPT_ENCODING, "");
6888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // url must remain valid through the request
6908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(!d->m_url);
6918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // url is in ASCII so latin1() will only convert it to char* without character translation.
6938a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block    d->m_url = fastStrDup(url.latin1().data());
6948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    curl_easy_setopt(d->m_handle, CURLOPT_URL, d->m_url);
6958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_cookieJarFileName) {
6978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        curl_easy_setopt(d->m_handle, CURLOPT_COOKIEFILE, m_cookieJarFileName);
6988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        curl_easy_setopt(d->m_handle, CURLOPT_COOKIEJAR, m_cookieJarFileName);
6998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
7008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    struct curl_slist* headers = 0;
702967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    if (job->firstRequest().httpHeaderFields().size() > 0) {
703967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch        HTTPHeaderMap customHeaders = job->firstRequest().httpHeaderFields();
7048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        HTTPHeaderMap::const_iterator end = customHeaders.end();
7058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        for (HTTPHeaderMap::const_iterator it = customHeaders.begin(); it != end; ++it) {
7068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            String key = it->first;
7078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            String value = it->second;
7088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            String headerString(key);
7098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            headerString.append(": ");
7108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            headerString.append(value);
7118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            CString headerLatin1 = headerString.latin1();
7128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            headers = curl_slist_append(headers, headerLatin1.data());
7138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
7148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
7158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
716967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    if ("GET" == job->firstRequest().httpMethod())
7178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        curl_easy_setopt(d->m_handle, CURLOPT_HTTPGET, TRUE);
718967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    else if ("POST" == job->firstRequest().httpMethod())
7198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        setupPOST(job, &headers);
720967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    else if ("PUT" == job->firstRequest().httpMethod())
7218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        setupPUT(job, &headers);
722967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    else if ("HEAD" == job->firstRequest().httpMethod())
7238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        curl_easy_setopt(d->m_handle, CURLOPT_NOBODY, TRUE);
7248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (headers) {
7268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        curl_easy_setopt(d->m_handle, CURLOPT_HTTPHEADER, headers);
7278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        d->m_customHeaders = headers;
7288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
729cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // curl CURLOPT_USERPWD expects username:password
730cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (d->m_user.length() || d->m_pass.length()) {
731cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        String userpass = d->m_user + ":" + d->m_pass;
732cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        curl_easy_setopt(d->m_handle, CURLOPT_USERPWD, userpass.utf8().data());
733cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    }
734cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block
735cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    // Set proxy options if we have them.
736cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    if (m_proxy.length()) {
737cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        curl_easy_setopt(d->m_handle, CURLOPT_PROXY, m_proxy.utf8().data());
738cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block        curl_easy_setopt(d->m_handle, CURLOPT_PROXYTYPE, m_proxyType);
739cac0f67c402d107cdb10971b95719e2ff9c7c76bSteve Block    }
7408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ResourceHandleManager::cancel(ResourceHandle* job)
7438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (removeScheduledJob(job))
7458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
7468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ResourceHandleInternal* d = job->getInternal();
7488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    d->m_cancelled = true;
7498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!m_downloadTimer.isActive())
7508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_downloadTimer.startOneShot(pollTimeSeconds);
7518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project} // namespace WebCore
754