support.cpp revision a533975a8e3bb741948750a68a2c962a48777fe0
11156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber/* 21156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber * Copyright (C) 2011 The Android Open Source Project 31156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber * 41156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 51156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber * you may not use this file except in compliance with the License. 61156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber * You may obtain a copy of the License at 71156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber * 81156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 91156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber * 101156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber * Unless required by applicable law or agreed to in writing, software 111156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 121156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 131156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber * See the License for the specific language governing permissions and 141156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber * limitations under the License. 151156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber */ 161156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 171156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber//#define LOG_NDEBUG 0 181156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#define LOG_TAG "ChromiumHTTPDataSourceSupport" 191156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#include <utils/Log.h> 201156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 211156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#include <media/stagefright/foundation/AString.h> 221156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 231156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#include "support.h" 241156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 251156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#include "android/net/android_network_library_impl.h" 26a533975a8e3bb741948750a68a2c962a48777fe0Kristian Monsen#include "base/threading/thread.h" 27cd45ccddb00662f2af8409b895fbcdd0434da8b1Kristian Monsen#include "net/base/cert_verifier.h" 281156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#include "net/base/host_resolver.h" 291156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#include "net/base/ssl_config_service.h" 3070fcf534d3fb6faa3aaa8061fc87f720c396e7aeAndreas Huber#include "net/http/http_auth_handler_factory.h" 311156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#include "net/http/http_cache.h" 3272fee698602ede6f6b64b77c0f1f28d96ff673d3Andreas Huber#include "net/proxy/proxy_config_service_android.h" 331156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 341156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#include "include/ChromiumHTTPDataSource.h" 351156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 361156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#include <cutils/properties.h> 371156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#include <media/stagefright/MediaErrors.h> 381156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 391156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubernamespace android { 401156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 411156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huberstatic Mutex gNetworkThreadLock; 421156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huberstatic base::Thread *gNetworkThread = NULL; 431156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huberstatic scoped_refptr<URLRequestContext> gReqContext; 441156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 451156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huberstatic void InitializeNetworkThreadIfNecessary() { 461156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber Mutex::Autolock autoLock(gNetworkThreadLock); 471156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber if (gNetworkThread == NULL) { 481156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber gNetworkThread = new base::Thread("network"); 491156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber base::Thread::Options options; 501156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber options.message_loop_type = MessageLoop::TYPE_IO; 511156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber CHECK(gNetworkThread->StartWithOptions(options)); 521156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 531156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber gReqContext = new SfRequestContext; 541156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 551156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber net::AndroidNetworkLibrary::RegisterSharedInstance( 561156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber new SfNetworkLibrary); 571156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber } 581156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 591156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 601156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huberstatic void MY_LOGI(const char *s) { 611156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "%s", s); 621156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 631156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 641156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huberstatic void MY_LOGV(const char *s) { 651156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#if !defined(LOG_NDEBUG) || LOG_NDEBUG == 0 661156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber LOG_PRI(ANDROID_LOG_VERBOSE, LOG_TAG, "%s", s); 671156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#endif 681156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 691156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 701156dc913a5ba7b2bc86489468d4914430f03d14Andreas HuberSfNetLog::SfNetLog() 711156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber : mNextID(1) { 721156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 731156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 741156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfNetLog::AddEntry( 751156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber EventType type, 761156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber const base::TimeTicks &time, 771156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber const Source &source, 781156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber EventPhase phase, 791156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber EventParameters *params) { 801156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#if 0 811156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber MY_LOGI(StringPrintf( 821156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber "AddEntry time=%s type=%s source=%s phase=%s\n", 831156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber TickCountToString(time).c_str(), 841156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber EventTypeToString(type), 851156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber SourceTypeToString(source.type), 861156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber EventPhaseToString(phase)).c_str()); 871156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#endif 881156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 891156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 901156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huberuint32 SfNetLog::NextID() { 911156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber return mNextID++; 921156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 931156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 941156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubernet::NetLog::LogLevel SfNetLog::GetLogLevel() const { 951156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber return LOG_ALL; 961156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 971156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 981156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber//////////////////////////////////////////////////////////////////////////////// 991156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 1001156dc913a5ba7b2bc86489468d4914430f03d14Andreas HuberSfRequestContext::SfRequestContext() { 1011156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber AString ua; 1021156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber ua.append("stagefright/1.2 (Linux;Android "); 1031156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 1041156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#if (PROPERTY_VALUE_MAX < 8) 1051156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#error "PROPERTY_VALUE_MAX must be at least 8" 1061156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#endif 1071156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 1081156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber char value[PROPERTY_VALUE_MAX]; 1091156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber property_get("ro.build.version.release", value, "Unknown"); 1101156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber ua.append(value); 1111156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber ua.append(")"); 1121156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 1131156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mUserAgent = ua.c_str(); 1141156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 1151156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber net_log_ = new SfNetLog; 1161156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 1171156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber host_resolver_ = 1181156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber net::CreateSystemHostResolver( 1191156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber net::HostResolver::kDefaultParallelism, 1201156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber NULL /* resolver_proc */, 1211156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber net_log_); 1221156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 1231156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber ssl_config_service_ = 1241156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber net::SSLConfigService::CreateSystemSSLConfigService(); 1251156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 12672fee698602ede6f6b64b77c0f1f28d96ff673d3Andreas Huber proxy_service_ = net::ProxyService::CreateWithoutProxyResolver( 12772fee698602ede6f6b64b77c0f1f28d96ff673d3Andreas Huber new net::ProxyConfigServiceAndroid, net_log_); 1281156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 1291156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber http_transaction_factory_ = new net::HttpCache( 1301156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber host_resolver_, 131cd45ccddb00662f2af8409b895fbcdd0434da8b1Kristian Monsen new net::CertVerifier(), 1321156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber dnsrr_resolver_, 1331156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber dns_cert_checker_.get(), 1341156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber proxy_service_.get(), 1351156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber ssl_config_service_.get(), 13670fcf534d3fb6faa3aaa8061fc87f720c396e7aeAndreas Huber net::HttpAuthHandlerFactory::CreateDefault(host_resolver_), 1371156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber network_delegate_, 1381156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber net_log_, 1391156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber NULL); // backend_factory 1401156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 1411156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 1421156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huberconst std::string &SfRequestContext::GetUserAgent(const GURL &url) const { 1431156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber return mUserAgent; 1441156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 1451156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 1461156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber//////////////////////////////////////////////////////////////////////////////// 1471156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 1481156dc913a5ba7b2bc86489468d4914430f03d14Andreas HuberSfNetworkLibrary::SfNetworkLibrary() {} 1491156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 1501156dc913a5ba7b2bc86489468d4914430f03d14Andreas HuberSfNetworkLibrary::VerifyResult SfNetworkLibrary::VerifyX509CertChain( 1511156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber const std::vector<std::string>& cert_chain, 1521156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber const std::string& hostname, 1531156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber const std::string& auth_type) { 1541156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber return VERIFY_OK; 1551156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 1561156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 1571156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber//////////////////////////////////////////////////////////////////////////////// 1581156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 1591156dc913a5ba7b2bc86489468d4914430f03d14Andreas HuberSfDelegate::SfDelegate() 1601156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber : mOwner(NULL), 1611156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mURLRequest(NULL), 1621156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mReadBuffer(new net::IOBufferWithSize(8192)), 1631156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mNumBytesRead(0), 1641156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mNumBytesTotal(0), 1651156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mDataDestination(NULL), 1661156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mAtEOS(false) { 1671156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber InitializeNetworkThreadIfNecessary(); 1681156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 1691156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 1701156dc913a5ba7b2bc86489468d4914430f03d14Andreas HuberSfDelegate::~SfDelegate() { 1711156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber CHECK(mURLRequest == NULL); 1721156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 1731156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 1741156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::setOwner(ChromiumHTTPDataSource *owner) { 1751156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mOwner = owner; 1761156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 1771156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 1781156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::OnReceivedRedirect( 179cd45ccddb00662f2af8409b895fbcdd0434da8b1Kristian Monsen net::URLRequest *request, const GURL &new_url, bool *defer_redirect) { 1801156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber MY_LOGI("OnReceivedRedirect"); 1811156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 1821156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 1831156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::OnAuthRequired( 184cd45ccddb00662f2af8409b895fbcdd0434da8b1Kristian Monsen net::URLRequest *request, net::AuthChallengeInfo *auth_info) { 1851156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber MY_LOGI("OnAuthRequired"); 1861156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 1871156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber inherited::OnAuthRequired(request, auth_info); 1881156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 1891156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 1901156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::OnCertificateRequested( 191cd45ccddb00662f2af8409b895fbcdd0434da8b1Kristian Monsen net::URLRequest *request, net::SSLCertRequestInfo *cert_request_info) { 1921156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber MY_LOGI("OnCertificateRequested"); 1931156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 1941156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber inherited::OnCertificateRequested(request, cert_request_info); 1951156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 1961156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 1971156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::OnSSLCertificateError( 198cd45ccddb00662f2af8409b895fbcdd0434da8b1Kristian Monsen net::URLRequest *request, int cert_error, net::X509Certificate *cert) { 1991156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber fprintf(stderr, "OnSSLCertificateError cert_error=%d\n", cert_error); 2001156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 2011156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber inherited::OnSSLCertificateError(request, cert_error, cert); 2021156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 2031156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 204cd45ccddb00662f2af8409b895fbcdd0434da8b1Kristian Monsenvoid SfDelegate::OnGetCookies(net::URLRequest *request, bool blocked_by_policy) { 2051156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber MY_LOGI("OnGetCookies"); 2061156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 2071156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 2081156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::OnSetCookie( 209cd45ccddb00662f2af8409b895fbcdd0434da8b1Kristian Monsen net::URLRequest *request, 2101156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber const std::string &cookie_line, 2111156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber const net::CookieOptions &options, 2121156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber bool blocked_by_policy) { 2131156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber MY_LOGI("OnSetCookie"); 2141156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 2151156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 216cd45ccddb00662f2af8409b895fbcdd0434da8b1Kristian Monsenvoid SfDelegate::OnResponseStarted(net::URLRequest *request) { 2171156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber if (request->status().status() != URLRequestStatus::SUCCESS) { 2181156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber MY_LOGI(StringPrintf( 2191156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber "Request failed with status %d and os_error %d", 2201156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber request->status().status(), 2211156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber request->status().os_error()).c_str()); 2221156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 2231156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber delete mURLRequest; 2241156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mURLRequest = NULL; 2251156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 2261156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mOwner->onConnectionFailed(ERROR_IO); 2271156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber return; 2281156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber } else if (mRangeRequested && request->GetResponseCode() != 206) { 2291156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber MY_LOGI(StringPrintf( 2301156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber "We requested a content range, but server didn't " 2311156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber "support that. (responded with %d)", 2321156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber request->GetResponseCode()).c_str()); 2331156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 2341156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber delete mURLRequest; 2351156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mURLRequest = NULL; 2361156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 2371156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mOwner->onConnectionFailed(-EPIPE); 2381156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber return; 2391156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber } else if ((request->GetResponseCode() / 100) != 2) { 2401156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber MY_LOGI(StringPrintf( 2411156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber "Server responded with http status %d", 2421156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber request->GetResponseCode()).c_str()); 2431156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 2441156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber delete mURLRequest; 2451156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mURLRequest = NULL; 2461156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 2471156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mOwner->onConnectionFailed(ERROR_IO); 2481156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber return; 2491156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber } 2501156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 2511156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber MY_LOGV("OnResponseStarted"); 2521156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 2531156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber std::string headers; 2541156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber request->GetAllResponseHeaders(&headers); 2551156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 2561156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber MY_LOGV(StringPrintf("response headers: %s", headers.c_str()).c_str()); 2571156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 2586511c9755c3a3360ba869772600c7aae048a7ffcAndreas Huber std::string contentType; 2596511c9755c3a3360ba869772600c7aae048a7ffcAndreas Huber request->GetResponseHeaderByName("Content-Type", &contentType); 2606511c9755c3a3360ba869772600c7aae048a7ffcAndreas Huber 2616511c9755c3a3360ba869772600c7aae048a7ffcAndreas Huber mOwner->onConnectionEstablished( 2626511c9755c3a3360ba869772600c7aae048a7ffcAndreas Huber request->GetExpectedContentSize(), contentType.c_str()); 2631156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 2641156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 265cd45ccddb00662f2af8409b895fbcdd0434da8b1Kristian Monsenvoid SfDelegate::OnReadCompleted(net::URLRequest *request, int bytes_read) { 2661156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber if (bytes_read == -1) { 2671156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber MY_LOGI(StringPrintf( 2681156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber "OnReadCompleted, read failed, status %d", 2691156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber request->status().status()).c_str()); 2701156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 2711156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mOwner->onReadCompleted(ERROR_IO); 2721156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber return; 2731156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber } 2741156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 2751156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber MY_LOGV(StringPrintf("OnReadCompleted, read %d bytes", bytes_read).c_str()); 2761156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 2771156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber if (bytes_read < 0) { 2781156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber MY_LOGI(StringPrintf( 2791156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber "Read failed w/ status %d\n", 2801156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber request->status().status()).c_str()); 2811156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 2821156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mOwner->onReadCompleted(ERROR_IO); 2831156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber return; 2841156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber } else if (bytes_read == 0) { 2851156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mAtEOS = true; 2861156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mOwner->onReadCompleted(mNumBytesRead); 2871156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber return; 2881156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber } 2891156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 2901156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber CHECK_GT(bytes_read, 0); 2911156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber CHECK_LE(mNumBytesRead + bytes_read, mNumBytesTotal); 2921156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 2931156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber memcpy((uint8_t *)mDataDestination + mNumBytesRead, 2941156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mReadBuffer->data(), 2951156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber bytes_read); 2961156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 2971156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mNumBytesRead += bytes_read; 2981156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 2991156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber readMore(request); 3001156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 3011156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 302cd45ccddb00662f2af8409b895fbcdd0434da8b1Kristian Monsenvoid SfDelegate::readMore(net::URLRequest *request) { 3031156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber while (mNumBytesRead < mNumBytesTotal) { 3041156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber size_t copy = mNumBytesTotal - mNumBytesRead; 3051156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber if (copy > mReadBuffer->size()) { 3061156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber copy = mReadBuffer->size(); 3071156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber } 3081156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 3091156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber int n; 3101156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber if (request->Read(mReadBuffer, copy, &n)) { 3111156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber MY_LOGV(StringPrintf("Read %d bytes directly.", n).c_str()); 3121156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 3131156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber CHECK_LE((size_t)n, copy); 3141156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 3151156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber memcpy((uint8_t *)mDataDestination + mNumBytesRead, 3161156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mReadBuffer->data(), 3171156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber n); 3181156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 3191156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mNumBytesRead += n; 3201156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 3211156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber if (n == 0) { 3221156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mAtEOS = true; 3231156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber break; 3241156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber } 3251156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber } else { 3261156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber MY_LOGV("readMore pending read"); 3271156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 3281156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber if (request->status().status() != URLRequestStatus::IO_PENDING) { 3291156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber MY_LOGI(StringPrintf( 3301156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber "Direct read failed w/ status %d\n", 3311156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber request->status().status()).c_str()); 3321156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 3331156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mOwner->onReadCompleted(ERROR_IO); 3341156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber return; 3351156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber } 3361156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 3371156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber return; 3381156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber } 3391156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber } 3401156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 3411156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mOwner->onReadCompleted(mNumBytesRead); 3421156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 3431156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 3441156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::initiateConnection( 3451156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber const char *uri, 3461156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber const KeyedVector<String8, String8> *headers, 3471156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber off64_t offset) { 3481156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber GURL url(uri); 3491156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 3501156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber MessageLoop *loop = gNetworkThread->message_loop(); 3511156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber loop->PostTask( 3521156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber FROM_HERE, 3531156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber NewRunnableFunction( 3541156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber &SfDelegate::OnInitiateConnectionWrapper, 3551156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber this, 3561156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber url, 3571156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber headers, 3581156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber offset)); 3591156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 3601156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 3611156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 3621156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber// static 3631156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::OnInitiateConnectionWrapper( 3641156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber SfDelegate *me, GURL url, 3651156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber const KeyedVector<String8, String8> *headers, 3661156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber off64_t offset) { 3671156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber me->onInitiateConnection(url, headers, offset); 3681156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 3691156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 3701156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::onInitiateConnection( 3711156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber const GURL &url, 3721156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber const KeyedVector<String8, String8> *extra, 3731156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber off64_t offset) { 3741156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber CHECK(mURLRequest == NULL); 3751156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 376cd45ccddb00662f2af8409b895fbcdd0434da8b1Kristian Monsen mURLRequest = new net::URLRequest(url, this); 3771156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mAtEOS = false; 3781156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 3791156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mRangeRequested = false; 3801156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 3811156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber if (offset != 0 || extra != NULL) { 3821156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber net::HttpRequestHeaders headers = 3831156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mURLRequest->extra_request_headers(); 3841156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 3851156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber if (offset != 0) { 3861156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber headers.AddHeaderFromString( 3871156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber StringPrintf("Range: bytes=%lld-", offset).c_str()); 3881156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 3891156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mRangeRequested = true; 3901156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber } 3911156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 3921156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber if (extra != NULL) { 3931156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber for (size_t i = 0; i < extra->size(); ++i) { 3941156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber AString s; 3951156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber s.append(extra->keyAt(i).string()); 3961156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber s.append(": "); 3971156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber s.append(extra->valueAt(i).string()); 3981156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 3991156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber headers.AddHeaderFromString(s.c_str()); 4001156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber } 4011156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber } 4021156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 4031156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mURLRequest->SetExtraRequestHeaders(headers); 4041156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber } 4051156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 4061156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mURLRequest->set_context(gReqContext); 4071156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 4081156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mURLRequest->Start(); 4091156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 4101156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 4111156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::initiateDisconnect() { 4121156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber MessageLoop *loop = gNetworkThread->message_loop(); 4131156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber loop->PostTask( 4141156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber FROM_HERE, 4151156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber NewRunnableFunction( 4161156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber &SfDelegate::OnInitiateDisconnectWrapper, this)); 4171156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 4181156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 4191156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber// static 4201156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::OnInitiateDisconnectWrapper(SfDelegate *me) { 4211156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber me->onInitiateDisconnect(); 4221156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 4231156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 4241156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::onInitiateDisconnect() { 4251156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mURLRequest->Cancel(); 4261156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 4271156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber delete mURLRequest; 4281156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mURLRequest = NULL; 4291156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 4301156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mOwner->onDisconnectComplete(); 4311156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 4321156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 4331156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::initiateRead(void *data, size_t size) { 4341156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber MessageLoop *loop = gNetworkThread->message_loop(); 4351156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber loop->PostTask( 4361156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber FROM_HERE, 4371156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber NewRunnableFunction( 4381156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber &SfDelegate::OnInitiateReadWrapper, this, data, size)); 4391156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 4401156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 4411156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber// static 4421156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::OnInitiateReadWrapper( 4431156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber SfDelegate *me, void *data, size_t size) { 4441156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber me->onInitiateRead(data, size); 4451156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 4461156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 4471156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::onInitiateRead(void *data, size_t size) { 4481156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber CHECK(mURLRequest != NULL); 4491156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 4501156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mNumBytesRead = 0; 4511156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mNumBytesTotal = size; 4521156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mDataDestination = data; 4531156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 4541156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber if (mAtEOS) { 4551156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber mOwner->onReadCompleted(0); 4561156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber return; 4571156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber } 4581156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 4591156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber readMore(mURLRequest); 4601156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} 4611156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 4621156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber} // namespace android 4631156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber 464