1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "ChromiumHTTPDataSourceSupport"
19#include <utils/Log.h>
20
21#include <media/stagefright/foundation/AString.h>
22
23#include "support.h"
24
25#include "android/net/android_network_library_impl.h"
26#include "base/logging.h"
27#include "base/threading/thread.h"
28#include "net/base/cert_verifier.h"
29#include "net/base/cookie_monster.h"
30#include "net/base/host_resolver.h"
31#include "net/base/ssl_config_service.h"
32#include "net/http/http_auth_handler_factory.h"
33#include "net/http/http_cache.h"
34#include "net/proxy/proxy_config_service_android.h"
35
36#include "include/ChromiumHTTPDataSource.h"
37
38#include <cutils/log.h>
39#include <cutils/properties.h>
40#include <media/stagefright/MediaErrors.h>
41#include <string>
42
43namespace android {
44
45static Mutex gNetworkThreadLock;
46static base::Thread *gNetworkThread = NULL;
47static scoped_refptr<net::URLRequestContext> gReqContext;
48static scoped_ptr<net::NetworkChangeNotifier> gNetworkChangeNotifier;
49
50bool logMessageHandler(
51        int severity,
52        const char* file,
53        int line,
54        size_t message_start,
55        const std::string& str) {
56    int androidSeverity = ANDROID_LOG_VERBOSE;
57    switch(severity) {
58    case logging::LOG_FATAL:
59        androidSeverity = ANDROID_LOG_FATAL;
60        break;
61    case logging::LOG_ERROR_REPORT:
62    case logging::LOG_ERROR:
63        androidSeverity = ANDROID_LOG_ERROR;
64        break;
65    case logging::LOG_WARNING:
66        androidSeverity = ANDROID_LOG_WARN;
67        break;
68    default:
69        androidSeverity = ANDROID_LOG_VERBOSE;
70        break;
71    }
72    android_printLog(androidSeverity, "chromium-libstagefright",
73                    "%s:%d: %s", file, line, str.c_str());
74    return false;
75}
76
77struct AutoPrioritySaver {
78    AutoPrioritySaver()
79        : mTID(androidGetTid()),
80          mPrevPriority(androidGetThreadPriority(mTID)) {
81        androidSetThreadPriority(mTID, ANDROID_PRIORITY_NORMAL);
82    }
83
84    ~AutoPrioritySaver() {
85        androidSetThreadPriority(mTID, mPrevPriority);
86    }
87
88private:
89    pid_t mTID;
90    int mPrevPriority;
91
92    DISALLOW_EVIL_CONSTRUCTORS(AutoPrioritySaver);
93};
94
95static void InitializeNetworkThreadIfNecessary() {
96    Mutex::Autolock autoLock(gNetworkThreadLock);
97
98    if (gNetworkThread == NULL) {
99        // Make sure any threads spawned by the chromium framework are
100        // running at normal priority instead of inheriting this thread's.
101        AutoPrioritySaver saver;
102
103        gNetworkThread = new base::Thread("network");
104        base::Thread::Options options;
105        options.message_loop_type = MessageLoop::TYPE_IO;
106        CHECK(gNetworkThread->StartWithOptions(options));
107
108        gReqContext = new SfRequestContext;
109
110        gNetworkChangeNotifier.reset(net::NetworkChangeNotifier::Create());
111
112        net::AndroidNetworkLibrary::RegisterSharedInstance(
113                new SfNetworkLibrary);
114        logging::SetLogMessageHandler(logMessageHandler);
115    }
116}
117
118static void MY_LOGI(const char *s) {
119    LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "%s", s);
120}
121
122static void MY_LOGV(const char *s) {
123#if !defined(LOG_NDEBUG) || LOG_NDEBUG == 0
124    LOG_PRI(ANDROID_LOG_VERBOSE, LOG_TAG, "%s", s);
125#endif
126}
127
128SfNetLog::SfNetLog()
129    : mNextID(1) {
130}
131
132void SfNetLog::AddEntry(
133        EventType type,
134        const base::TimeTicks &time,
135        const Source &source,
136        EventPhase phase,
137        EventParameters *params) {
138#if 0
139    MY_LOGI(StringPrintf(
140                "AddEntry time=%s type=%s source=%s phase=%s\n",
141                TickCountToString(time).c_str(),
142                EventTypeToString(type),
143                SourceTypeToString(source.type),
144                EventPhaseToString(phase)).c_str());
145#endif
146}
147
148uint32 SfNetLog::NextID() {
149    return mNextID++;
150}
151
152net::NetLog::LogLevel SfNetLog::GetLogLevel() const {
153    return LOG_ALL;
154}
155
156////////////////////////////////////////////////////////////////////////////////
157
158SfRequestContext::SfRequestContext() {
159    AString ua;
160    ua.append("stagefright/1.2 (Linux;Android ");
161
162#if (PROPERTY_VALUE_MAX < 8)
163#error "PROPERTY_VALUE_MAX must be at least 8"
164#endif
165
166    char value[PROPERTY_VALUE_MAX];
167    property_get("ro.build.version.release", value, "Unknown");
168    ua.append(value);
169    ua.append(")");
170
171    mUserAgent = ua.c_str();
172
173    set_net_log(new SfNetLog());
174
175    set_host_resolver(
176        net::CreateSystemHostResolver(
177                net::HostResolver::kDefaultParallelism,
178                NULL /* resolver_proc */,
179                net_log()));
180
181    set_ssl_config_service(
182        net::SSLConfigService::CreateSystemSSLConfigService());
183
184    set_proxy_service(net::ProxyService::CreateWithoutProxyResolver(
185        new net::ProxyConfigServiceAndroid, net_log()));
186
187    set_http_transaction_factory(new net::HttpCache(
188            host_resolver(),
189            new net::CertVerifier(),
190            dnsrr_resolver(),
191            dns_cert_checker(),
192            proxy_service(),
193            ssl_config_service(),
194            net::HttpAuthHandlerFactory::CreateDefault(host_resolver()),
195            network_delegate(),
196            net_log(),
197            NULL));  // backend_factory
198
199    set_cookie_store(new net::CookieMonster(NULL, NULL));
200}
201
202const std::string &SfRequestContext::GetUserAgent(const GURL &url) const {
203    return mUserAgent;
204}
205
206////////////////////////////////////////////////////////////////////////////////
207
208SfNetworkLibrary::SfNetworkLibrary() {}
209
210SfNetworkLibrary::VerifyResult SfNetworkLibrary::VerifyX509CertChain(
211        const std::vector<std::string>& cert_chain,
212        const std::string& hostname,
213        const std::string& auth_type) {
214    return VERIFY_OK;
215}
216
217////////////////////////////////////////////////////////////////////////////////
218
219SfDelegate::SfDelegate()
220    : mOwner(NULL),
221      mURLRequest(NULL),
222      mReadBuffer(new net::IOBufferWithSize(8192)),
223      mNumBytesRead(0),
224      mNumBytesTotal(0),
225      mDataDestination(NULL),
226      mAtEOS(false) {
227    InitializeNetworkThreadIfNecessary();
228}
229
230SfDelegate::~SfDelegate() {
231    CHECK(mURLRequest == NULL);
232}
233
234void SfDelegate::setOwner(ChromiumHTTPDataSource *owner) {
235    mOwner = owner;
236}
237
238void SfDelegate::setUID(uid_t uid) {
239    gReqContext->setUID(uid);
240}
241
242bool SfDelegate::getUID(uid_t *uid) const {
243    return gReqContext->getUID(uid);
244}
245
246void SfDelegate::OnReceivedRedirect(
247            net::URLRequest *request, const GURL &new_url, bool *defer_redirect) {
248    MY_LOGV("OnReceivedRedirect");
249}
250
251void SfDelegate::OnAuthRequired(
252            net::URLRequest *request, net::AuthChallengeInfo *auth_info) {
253    MY_LOGV("OnAuthRequired");
254
255    inherited::OnAuthRequired(request, auth_info);
256}
257
258void SfDelegate::OnCertificateRequested(
259            net::URLRequest *request, net::SSLCertRequestInfo *cert_request_info) {
260    MY_LOGV("OnCertificateRequested");
261
262    inherited::OnCertificateRequested(request, cert_request_info);
263}
264
265void SfDelegate::OnSSLCertificateError(
266            net::URLRequest *request, int cert_error, net::X509Certificate *cert) {
267    fprintf(stderr, "OnSSLCertificateError cert_error=%d\n", cert_error);
268
269    inherited::OnSSLCertificateError(request, cert_error, cert);
270}
271
272void SfDelegate::OnGetCookies(net::URLRequest *request, bool blocked_by_policy) {
273    MY_LOGV("OnGetCookies");
274}
275
276void SfDelegate::OnSetCookie(
277        net::URLRequest *request,
278        const std::string &cookie_line,
279        const net::CookieOptions &options,
280        bool blocked_by_policy) {
281    MY_LOGV("OnSetCookie");
282}
283
284void SfDelegate::OnResponseStarted(net::URLRequest *request) {
285    if (request->status().status() != net::URLRequestStatus::SUCCESS) {
286        MY_LOGI(StringPrintf(
287                    "Request failed with status %d and os_error %d",
288                    request->status().status(),
289                    request->status().os_error()).c_str());
290
291        delete mURLRequest;
292        mURLRequest = NULL;
293
294        mOwner->onConnectionFailed(ERROR_IO);
295        return;
296    } else if (mRangeRequested && request->GetResponseCode() != 206) {
297        MY_LOGI(StringPrintf(
298                    "We requested a content range, but server didn't "
299                    "support that. (responded with %d)",
300                    request->GetResponseCode()).c_str());
301
302        delete mURLRequest;
303        mURLRequest = NULL;
304
305        mOwner->onConnectionFailed(-EPIPE);
306        return;
307    } else if ((request->GetResponseCode() / 100) != 2) {
308        MY_LOGI(StringPrintf(
309                    "Server responded with http status %d",
310                    request->GetResponseCode()).c_str());
311
312        delete mURLRequest;
313        mURLRequest = NULL;
314
315        mOwner->onConnectionFailed(ERROR_IO);
316        return;
317    }
318
319    MY_LOGV("OnResponseStarted");
320
321    std::string headers;
322    request->GetAllResponseHeaders(&headers);
323
324    MY_LOGV(StringPrintf("response headers: %s", headers.c_str()).c_str());
325
326    std::string contentType;
327    request->GetResponseHeaderByName("Content-Type", &contentType);
328
329    mOwner->onConnectionEstablished(
330            request->GetExpectedContentSize(), contentType.c_str());
331}
332
333void SfDelegate::OnReadCompleted(net::URLRequest *request, int bytes_read) {
334    if (bytes_read == -1) {
335        MY_LOGI(StringPrintf(
336                    "OnReadCompleted, read failed, status %d",
337                    request->status().status()).c_str());
338
339        mOwner->onReadCompleted(ERROR_IO);
340        return;
341    }
342
343    MY_LOGV(StringPrintf("OnReadCompleted, read %d bytes", bytes_read).c_str());
344
345    if (bytes_read < 0) {
346        MY_LOGI(StringPrintf(
347                    "Read failed w/ status %d\n",
348                    request->status().status()).c_str());
349
350        mOwner->onReadCompleted(ERROR_IO);
351        return;
352    } else if (bytes_read == 0) {
353        mAtEOS = true;
354        mOwner->onReadCompleted(mNumBytesRead);
355        return;
356    }
357
358    CHECK_GT(bytes_read, 0);
359    CHECK_LE(mNumBytesRead + bytes_read, mNumBytesTotal);
360
361    memcpy((uint8_t *)mDataDestination + mNumBytesRead,
362           mReadBuffer->data(),
363           bytes_read);
364
365    mNumBytesRead += bytes_read;
366
367    readMore(request);
368}
369
370void SfDelegate::readMore(net::URLRequest *request) {
371    while (mNumBytesRead < mNumBytesTotal) {
372        size_t copy = mNumBytesTotal - mNumBytesRead;
373        if (copy > mReadBuffer->size()) {
374            copy = mReadBuffer->size();
375        }
376
377        int n;
378        if (request->Read(mReadBuffer, copy, &n)) {
379            MY_LOGV(StringPrintf("Read %d bytes directly.", n).c_str());
380
381            CHECK_LE((size_t)n, copy);
382
383            memcpy((uint8_t *)mDataDestination + mNumBytesRead,
384                   mReadBuffer->data(),
385                   n);
386
387            mNumBytesRead += n;
388
389            if (n == 0) {
390                mAtEOS = true;
391                break;
392            }
393        } else {
394            MY_LOGV("readMore pending read");
395
396            if (request->status().status() != net::URLRequestStatus::IO_PENDING) {
397                MY_LOGI(StringPrintf(
398                            "Direct read failed w/ status %d\n",
399                            request->status().status()).c_str());
400
401                mOwner->onReadCompleted(ERROR_IO);
402                return;
403            }
404
405            return;
406        }
407    }
408
409    mOwner->onReadCompleted(mNumBytesRead);
410}
411
412void SfDelegate::initiateConnection(
413        const char *uri,
414        const KeyedVector<String8, String8> *headers,
415        off64_t offset) {
416    GURL url(uri);
417
418    MessageLoop *loop = gNetworkThread->message_loop();
419    loop->PostTask(
420            FROM_HERE,
421            NewRunnableFunction(
422                &SfDelegate::OnInitiateConnectionWrapper,
423                this,
424                url,
425                headers,
426                offset));
427
428}
429
430// static
431void SfDelegate::OnInitiateConnectionWrapper(
432        SfDelegate *me, GURL url,
433        const KeyedVector<String8, String8> *headers,
434        off64_t offset) {
435    me->onInitiateConnection(url, headers, offset);
436}
437
438void SfDelegate::onInitiateConnection(
439        const GURL &url,
440        const KeyedVector<String8, String8> *extra,
441        off64_t offset) {
442    CHECK(mURLRequest == NULL);
443
444    mURLRequest = new net::URLRequest(url, this);
445    mAtEOS = false;
446
447    mRangeRequested = false;
448
449    if (offset != 0 || extra != NULL) {
450        net::HttpRequestHeaders headers =
451            mURLRequest->extra_request_headers();
452
453        if (offset != 0) {
454            headers.AddHeaderFromString(
455                    StringPrintf("Range: bytes=%lld-", offset).c_str());
456
457            mRangeRequested = true;
458        }
459
460        if (extra != NULL) {
461            for (size_t i = 0; i < extra->size(); ++i) {
462                AString s;
463                s.append(extra->keyAt(i).string());
464                s.append(": ");
465                s.append(extra->valueAt(i).string());
466
467                headers.AddHeaderFromString(s.c_str());
468            }
469        }
470
471        mURLRequest->SetExtraRequestHeaders(headers);
472    }
473
474    mURLRequest->set_context(gReqContext);
475
476    mURLRequest->Start();
477}
478
479void SfDelegate::initiateDisconnect() {
480    MessageLoop *loop = gNetworkThread->message_loop();
481    loop->PostTask(
482            FROM_HERE,
483            NewRunnableFunction(
484                &SfDelegate::OnInitiateDisconnectWrapper, this));
485}
486
487// static
488void SfDelegate::OnInitiateDisconnectWrapper(SfDelegate *me) {
489    me->onInitiateDisconnect();
490}
491
492void SfDelegate::onInitiateDisconnect() {
493    if (mURLRequest == NULL) {
494        return;
495    }
496
497    mURLRequest->Cancel();
498
499    delete mURLRequest;
500    mURLRequest = NULL;
501
502    mOwner->onDisconnectComplete();
503}
504
505void SfDelegate::initiateRead(void *data, size_t size) {
506    MessageLoop *loop = gNetworkThread->message_loop();
507    loop->PostTask(
508            FROM_HERE,
509            NewRunnableFunction(
510                &SfDelegate::OnInitiateReadWrapper, this, data, size));
511}
512
513// static
514void SfDelegate::OnInitiateReadWrapper(
515        SfDelegate *me, void *data, size_t size) {
516    me->onInitiateRead(data, size);
517}
518
519void SfDelegate::onInitiateRead(void *data, size_t size) {
520    CHECK(mURLRequest != NULL);
521
522    mNumBytesRead = 0;
523    mNumBytesTotal = size;
524    mDataDestination = data;
525
526    if (mAtEOS) {
527        mOwner->onReadCompleted(0);
528        return;
529    }
530
531    readMore(mURLRequest);
532}
533
534}  // namespace android
535
536