support.cpp revision 553f66e21be6e11120460830fc78793a4d11b465
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;
4364125da2f3b76f2d88bb757cb6bf5bd5e29a0639Kristian Monsenstatic scoped_refptr<net::URLRequestContext> gReqContext;
44553f66e21be6e11120460830fc78793a4d11b465Andreas Huberstatic scoped_ptr<net::NetworkChangeNotifier> gNetworkChangeNotifier;
451156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
461156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huberstatic void InitializeNetworkThreadIfNecessary() {
471156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    Mutex::Autolock autoLock(gNetworkThreadLock);
481156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    if (gNetworkThread == NULL) {
491156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        gNetworkThread = new base::Thread("network");
501156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        base::Thread::Options options;
511156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        options.message_loop_type = MessageLoop::TYPE_IO;
521156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        CHECK(gNetworkThread->StartWithOptions(options));
531156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
541156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        gReqContext = new SfRequestContext;
551156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
56553f66e21be6e11120460830fc78793a4d11b465Andreas Huber        gNetworkChangeNotifier.reset(net::NetworkChangeNotifier::Create());
57553f66e21be6e11120460830fc78793a4d11b465Andreas Huber
581156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        net::AndroidNetworkLibrary::RegisterSharedInstance(
591156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                new SfNetworkLibrary);
601156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    }
611156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
621156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
631156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huberstatic void MY_LOGI(const char *s) {
641156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "%s", s);
651156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
661156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
671156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huberstatic void MY_LOGV(const char *s) {
681156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#if !defined(LOG_NDEBUG) || LOG_NDEBUG == 0
691156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    LOG_PRI(ANDROID_LOG_VERBOSE, LOG_TAG, "%s", s);
701156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#endif
711156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
721156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
731156dc913a5ba7b2bc86489468d4914430f03d14Andreas HuberSfNetLog::SfNetLog()
741156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    : mNextID(1) {
751156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
761156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
771156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfNetLog::AddEntry(
781156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        EventType type,
791156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        const base::TimeTicks &time,
801156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        const Source &source,
811156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        EventPhase phase,
821156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        EventParameters *params) {
831156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#if 0
841156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    MY_LOGI(StringPrintf(
851156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                "AddEntry time=%s type=%s source=%s phase=%s\n",
861156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                TickCountToString(time).c_str(),
871156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                EventTypeToString(type),
881156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                SourceTypeToString(source.type),
891156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                EventPhaseToString(phase)).c_str());
901156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#endif
911156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
921156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
931156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huberuint32 SfNetLog::NextID() {
941156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    return mNextID++;
951156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
961156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
971156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubernet::NetLog::LogLevel SfNetLog::GetLogLevel() const {
981156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    return LOG_ALL;
991156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
1001156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
1011156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber////////////////////////////////////////////////////////////////////////////////
1021156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
1031156dc913a5ba7b2bc86489468d4914430f03d14Andreas HuberSfRequestContext::SfRequestContext() {
1041156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    AString ua;
1051156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    ua.append("stagefright/1.2 (Linux;Android ");
1061156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
1071156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#if (PROPERTY_VALUE_MAX < 8)
1081156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#error "PROPERTY_VALUE_MAX must be at least 8"
1091156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber#endif
1101156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
1111156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    char value[PROPERTY_VALUE_MAX];
1121156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    property_get("ro.build.version.release", value, "Unknown");
1131156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    ua.append(value);
1141156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    ua.append(")");
1151156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
1161156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    mUserAgent = ua.c_str();
1171156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
1181156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    net_log_ = new SfNetLog;
1191156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
1201156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    host_resolver_ =
1211156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        net::CreateSystemHostResolver(
1221156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                net::HostResolver::kDefaultParallelism,
1231156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                NULL /* resolver_proc */,
1241156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                net_log_);
1251156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
1261156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    ssl_config_service_ =
1271156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        net::SSLConfigService::CreateSystemSSLConfigService();
1281156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
12972fee698602ede6f6b64b77c0f1f28d96ff673d3Andreas Huber    proxy_service_ = net::ProxyService::CreateWithoutProxyResolver(
13072fee698602ede6f6b64b77c0f1f28d96ff673d3Andreas Huber            new net::ProxyConfigServiceAndroid, net_log_);
1311156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
1321156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    http_transaction_factory_ = new net::HttpCache(
1331156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            host_resolver_,
134cd45ccddb00662f2af8409b895fbcdd0434da8b1Kristian Monsen            new net::CertVerifier(),
1351156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            dnsrr_resolver_,
1361156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            dns_cert_checker_.get(),
1371156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            proxy_service_.get(),
1381156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            ssl_config_service_.get(),
13970fcf534d3fb6faa3aaa8061fc87f720c396e7aeAndreas Huber            net::HttpAuthHandlerFactory::CreateDefault(host_resolver_),
1401156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            network_delegate_,
1411156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            net_log_,
1421156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            NULL);  // backend_factory
1431156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
1441156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
1451156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huberconst std::string &SfRequestContext::GetUserAgent(const GURL &url) const {
1461156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    return mUserAgent;
1471156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
1481156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
1491156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber////////////////////////////////////////////////////////////////////////////////
1501156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
1511156dc913a5ba7b2bc86489468d4914430f03d14Andreas HuberSfNetworkLibrary::SfNetworkLibrary() {}
1521156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
1531156dc913a5ba7b2bc86489468d4914430f03d14Andreas HuberSfNetworkLibrary::VerifyResult SfNetworkLibrary::VerifyX509CertChain(
1541156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        const std::vector<std::string>& cert_chain,
1551156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        const std::string& hostname,
1561156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        const std::string& auth_type) {
1571156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    return VERIFY_OK;
1581156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
1591156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
1601156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber////////////////////////////////////////////////////////////////////////////////
1611156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
1621156dc913a5ba7b2bc86489468d4914430f03d14Andreas HuberSfDelegate::SfDelegate()
1631156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    : mOwner(NULL),
1641156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber      mURLRequest(NULL),
1651156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber      mReadBuffer(new net::IOBufferWithSize(8192)),
1661156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber      mNumBytesRead(0),
1671156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber      mNumBytesTotal(0),
1681156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber      mDataDestination(NULL),
1691156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber      mAtEOS(false) {
1701156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    InitializeNetworkThreadIfNecessary();
1711156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
1721156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
1731156dc913a5ba7b2bc86489468d4914430f03d14Andreas HuberSfDelegate::~SfDelegate() {
1741156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    CHECK(mURLRequest == NULL);
1751156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
1761156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
1771156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::setOwner(ChromiumHTTPDataSource *owner) {
1781156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    mOwner = owner;
1791156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
1801156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
1811156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::OnReceivedRedirect(
182cd45ccddb00662f2af8409b895fbcdd0434da8b1Kristian Monsen            net::URLRequest *request, const GURL &new_url, bool *defer_redirect) {
1831156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    MY_LOGI("OnReceivedRedirect");
1841156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
1851156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
1861156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::OnAuthRequired(
187cd45ccddb00662f2af8409b895fbcdd0434da8b1Kristian Monsen            net::URLRequest *request, net::AuthChallengeInfo *auth_info) {
1881156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    MY_LOGI("OnAuthRequired");
1891156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
1901156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    inherited::OnAuthRequired(request, auth_info);
1911156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
1921156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
1931156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::OnCertificateRequested(
194cd45ccddb00662f2af8409b895fbcdd0434da8b1Kristian Monsen            net::URLRequest *request, net::SSLCertRequestInfo *cert_request_info) {
1951156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    MY_LOGI("OnCertificateRequested");
1961156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
1971156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    inherited::OnCertificateRequested(request, cert_request_info);
1981156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
1991156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
2001156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::OnSSLCertificateError(
201cd45ccddb00662f2af8409b895fbcdd0434da8b1Kristian Monsen            net::URLRequest *request, int cert_error, net::X509Certificate *cert) {
2021156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    fprintf(stderr, "OnSSLCertificateError cert_error=%d\n", cert_error);
2031156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
2041156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    inherited::OnSSLCertificateError(request, cert_error, cert);
2051156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
2061156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
207cd45ccddb00662f2af8409b895fbcdd0434da8b1Kristian Monsenvoid SfDelegate::OnGetCookies(net::URLRequest *request, bool blocked_by_policy) {
2081156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    MY_LOGI("OnGetCookies");
2091156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
2101156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
2111156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::OnSetCookie(
212cd45ccddb00662f2af8409b895fbcdd0434da8b1Kristian Monsen        net::URLRequest *request,
2131156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        const std::string &cookie_line,
2141156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        const net::CookieOptions &options,
2151156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        bool blocked_by_policy) {
2161156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    MY_LOGI("OnSetCookie");
2171156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
2181156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
219cd45ccddb00662f2af8409b895fbcdd0434da8b1Kristian Monsenvoid SfDelegate::OnResponseStarted(net::URLRequest *request) {
22064125da2f3b76f2d88bb757cb6bf5bd5e29a0639Kristian Monsen    if (request->status().status() != net::URLRequestStatus::SUCCESS) {
2211156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        MY_LOGI(StringPrintf(
2221156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                    "Request failed with status %d and os_error %d",
2231156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                    request->status().status(),
2241156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                    request->status().os_error()).c_str());
2251156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
2261156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        delete mURLRequest;
2271156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        mURLRequest = NULL;
2281156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
2291156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        mOwner->onConnectionFailed(ERROR_IO);
2301156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        return;
2311156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    } else if (mRangeRequested && request->GetResponseCode() != 206) {
2321156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        MY_LOGI(StringPrintf(
2331156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                    "We requested a content range, but server didn't "
2341156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                    "support that. (responded with %d)",
2351156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                    request->GetResponseCode()).c_str());
2361156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
2371156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        delete mURLRequest;
2381156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        mURLRequest = NULL;
2391156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
2401156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        mOwner->onConnectionFailed(-EPIPE);
2411156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        return;
2421156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    } else if ((request->GetResponseCode() / 100) != 2) {
2431156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        MY_LOGI(StringPrintf(
2441156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                    "Server responded with http status %d",
2451156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                    request->GetResponseCode()).c_str());
2461156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
2471156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        delete mURLRequest;
2481156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        mURLRequest = NULL;
2491156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
2501156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        mOwner->onConnectionFailed(ERROR_IO);
2511156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        return;
2521156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    }
2531156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
2541156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    MY_LOGV("OnResponseStarted");
2551156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
2561156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    std::string headers;
2571156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    request->GetAllResponseHeaders(&headers);
2581156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
2591156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    MY_LOGV(StringPrintf("response headers: %s", headers.c_str()).c_str());
2601156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
2616511c9755c3a3360ba869772600c7aae048a7ffcAndreas Huber    std::string contentType;
2626511c9755c3a3360ba869772600c7aae048a7ffcAndreas Huber    request->GetResponseHeaderByName("Content-Type", &contentType);
2636511c9755c3a3360ba869772600c7aae048a7ffcAndreas Huber
2646511c9755c3a3360ba869772600c7aae048a7ffcAndreas Huber    mOwner->onConnectionEstablished(
2656511c9755c3a3360ba869772600c7aae048a7ffcAndreas Huber            request->GetExpectedContentSize(), contentType.c_str());
2661156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
2671156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
268cd45ccddb00662f2af8409b895fbcdd0434da8b1Kristian Monsenvoid SfDelegate::OnReadCompleted(net::URLRequest *request, int bytes_read) {
2691156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    if (bytes_read == -1) {
2701156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        MY_LOGI(StringPrintf(
2711156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                    "OnReadCompleted, read failed, status %d",
2721156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                    request->status().status()).c_str());
2731156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
2741156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        mOwner->onReadCompleted(ERROR_IO);
2751156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        return;
2761156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    }
2771156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
2781156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    MY_LOGV(StringPrintf("OnReadCompleted, read %d bytes", bytes_read).c_str());
2791156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
2801156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    if (bytes_read < 0) {
2811156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        MY_LOGI(StringPrintf(
2821156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                    "Read failed w/ status %d\n",
2831156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                    request->status().status()).c_str());
2841156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
2851156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        mOwner->onReadCompleted(ERROR_IO);
2861156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        return;
2871156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    } else if (bytes_read == 0) {
2881156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        mAtEOS = true;
2891156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        mOwner->onReadCompleted(mNumBytesRead);
2901156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        return;
2911156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    }
2921156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
2931156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    CHECK_GT(bytes_read, 0);
2941156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    CHECK_LE(mNumBytesRead + bytes_read, mNumBytesTotal);
2951156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
2961156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    memcpy((uint8_t *)mDataDestination + mNumBytesRead,
2971156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber           mReadBuffer->data(),
2981156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber           bytes_read);
2991156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
3001156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    mNumBytesRead += bytes_read;
3011156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
3021156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    readMore(request);
3031156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
3041156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
305cd45ccddb00662f2af8409b895fbcdd0434da8b1Kristian Monsenvoid SfDelegate::readMore(net::URLRequest *request) {
3061156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    while (mNumBytesRead < mNumBytesTotal) {
3071156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        size_t copy = mNumBytesTotal - mNumBytesRead;
3081156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        if (copy > mReadBuffer->size()) {
3091156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            copy = mReadBuffer->size();
3101156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        }
3111156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
3121156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        int n;
3131156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        if (request->Read(mReadBuffer, copy, &n)) {
3141156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            MY_LOGV(StringPrintf("Read %d bytes directly.", n).c_str());
3151156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
3161156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            CHECK_LE((size_t)n, copy);
3171156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
3181156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            memcpy((uint8_t *)mDataDestination + mNumBytesRead,
3191156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                   mReadBuffer->data(),
3201156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                   n);
3211156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
3221156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            mNumBytesRead += n;
3231156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
3241156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            if (n == 0) {
3251156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                mAtEOS = true;
3261156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                break;
3271156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            }
3281156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        } else {
3291156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            MY_LOGV("readMore pending read");
3301156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
33164125da2f3b76f2d88bb757cb6bf5bd5e29a0639Kristian Monsen            if (request->status().status() != net::URLRequestStatus::IO_PENDING) {
3321156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                MY_LOGI(StringPrintf(
3331156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                            "Direct read failed w/ status %d\n",
3341156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                            request->status().status()).c_str());
3351156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
3361156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                mOwner->onReadCompleted(ERROR_IO);
3371156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                return;
3381156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            }
3391156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
3401156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            return;
3411156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        }
3421156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    }
3431156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
3441156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    mOwner->onReadCompleted(mNumBytesRead);
3451156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
3461156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
3471156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::initiateConnection(
3481156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        const char *uri,
3491156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        const KeyedVector<String8, String8> *headers,
3501156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        off64_t offset) {
3511156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    GURL url(uri);
3521156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
3531156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    MessageLoop *loop = gNetworkThread->message_loop();
3541156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    loop->PostTask(
3551156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            FROM_HERE,
3561156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            NewRunnableFunction(
3571156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                &SfDelegate::OnInitiateConnectionWrapper,
3581156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                this,
3591156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                url,
3601156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                headers,
3611156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                offset));
3621156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
3631156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
3641156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
3651156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber// static
3661156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::OnInitiateConnectionWrapper(
3671156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        SfDelegate *me, GURL url,
3681156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        const KeyedVector<String8, String8> *headers,
3691156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        off64_t offset) {
3701156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    me->onInitiateConnection(url, headers, offset);
3711156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
3721156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
3731156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::onInitiateConnection(
3741156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        const GURL &url,
3751156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        const KeyedVector<String8, String8> *extra,
3761156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        off64_t offset) {
3771156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    CHECK(mURLRequest == NULL);
3781156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
379cd45ccddb00662f2af8409b895fbcdd0434da8b1Kristian Monsen    mURLRequest = new net::URLRequest(url, this);
3801156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    mAtEOS = false;
3811156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
3821156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    mRangeRequested = false;
3831156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
3841156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    if (offset != 0 || extra != NULL) {
3851156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        net::HttpRequestHeaders headers =
3861156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            mURLRequest->extra_request_headers();
3871156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
3881156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        if (offset != 0) {
3891156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            headers.AddHeaderFromString(
3901156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                    StringPrintf("Range: bytes=%lld-", offset).c_str());
3911156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
3921156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            mRangeRequested = true;
3931156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        }
3941156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
3951156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        if (extra != NULL) {
3961156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            for (size_t i = 0; i < extra->size(); ++i) {
3971156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                AString s;
3981156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                s.append(extra->keyAt(i).string());
3991156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                s.append(": ");
4001156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                s.append(extra->valueAt(i).string());
4011156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
4021156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                headers.AddHeaderFromString(s.c_str());
4031156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            }
4041156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        }
4051156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
4061156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        mURLRequest->SetExtraRequestHeaders(headers);
4071156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    }
4081156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
4091156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    mURLRequest->set_context(gReqContext);
4101156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
4111156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    mURLRequest->Start();
4121156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
4131156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
4141156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::initiateDisconnect() {
4151156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    MessageLoop *loop = gNetworkThread->message_loop();
4161156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    loop->PostTask(
4171156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            FROM_HERE,
4181156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            NewRunnableFunction(
4191156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                &SfDelegate::OnInitiateDisconnectWrapper, this));
4201156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
4211156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
4221156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber// static
4231156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::OnInitiateDisconnectWrapper(SfDelegate *me) {
4241156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    me->onInitiateDisconnect();
4251156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
4261156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
4271156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::onInitiateDisconnect() {
4281156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    mURLRequest->Cancel();
4291156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
4301156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    delete mURLRequest;
4311156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    mURLRequest = NULL;
4321156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
4331156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    mOwner->onDisconnectComplete();
4341156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
4351156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
4361156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::initiateRead(void *data, size_t size) {
4371156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    MessageLoop *loop = gNetworkThread->message_loop();
4381156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    loop->PostTask(
4391156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            FROM_HERE,
4401156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber            NewRunnableFunction(
4411156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber                &SfDelegate::OnInitiateReadWrapper, this, data, size));
4421156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
4431156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
4441156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber// static
4451156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::OnInitiateReadWrapper(
4461156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        SfDelegate *me, void *data, size_t size) {
4471156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    me->onInitiateRead(data, size);
4481156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
4491156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
4501156dc913a5ba7b2bc86489468d4914430f03d14Andreas Hubervoid SfDelegate::onInitiateRead(void *data, size_t size) {
4511156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    CHECK(mURLRequest != NULL);
4521156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
4531156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    mNumBytesRead = 0;
4541156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    mNumBytesTotal = size;
4551156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    mDataDestination = data;
4561156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
4571156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    if (mAtEOS) {
4581156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        mOwner->onReadCompleted(0);
4591156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber        return;
4601156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    }
4611156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
4621156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber    readMore(mURLRequest);
4631156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}
4641156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
4651156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber}  // namespace android
4661156dc913a5ba7b2bc86489468d4914430f03d14Andreas Huber
467