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