summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/chromium_http
diff options
context:
space:
mode:
authorAnatol Pomozov <anatol.pomozov@gmail.com>2012-03-28 09:12:55 -0700
committerAnatol Pomozov <anatol.pomozov@gmail.com>2012-03-28 12:02:47 -0700
commitb0b2b4d890cf3bfb274797a759642b4e733343d7 (patch)
tree12ad21cbad346f02d542aa4d672ffd76407d58a9 /media/libstagefright/chromium_http
parent51f8eec23a2bcc2cc190373cdd1195972d9b8804 (diff)
parent5a5491c17d74bd2c80cf451c6ddbba22d5d5f08a (diff)
downloadframeworks_av-b0b2b4d890cf3bfb274797a759642b4e733343d7.zip
frameworks_av-b0b2b4d890cf3bfb274797a759642b4e733343d7.tar.gz
frameworks_av-b0b2b4d890cf3bfb274797a759642b4e733343d7.tar.bz2
Merge media files with history from frameworks/base.git
Diffstat (limited to 'media/libstagefright/chromium_http')
-rw-r--r--media/libstagefright/chromium_http/Android.mk25
-rw-r--r--media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp335
-rw-r--r--media/libstagefright/chromium_http/DataUriSource.cpp68
-rw-r--r--media/libstagefright/chromium_http/support.cpp531
-rw-r--r--media/libstagefright/chromium_http/support.h164
5 files changed, 1123 insertions, 0 deletions
diff --git a/media/libstagefright/chromium_http/Android.mk b/media/libstagefright/chromium_http/Android.mk
new file mode 100644
index 0000000..d595686
--- /dev/null
+++ b/media/libstagefright/chromium_http/Android.mk
@@ -0,0 +1,25 @@
+LOCAL_PATH:= $(call my-dir)
+
+ifneq ($(TARGET_BUILD_PDK), true)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ DataUriSource.cpp \
+ ChromiumHTTPDataSource.cpp \
+ support.cpp
+
+LOCAL_C_INCLUDES:= \
+ frameworks/base/media/libstagefright \
+ $(TOP)/frameworks/native/include/media/openmax \
+ external/chromium \
+ external/chromium/android
+
+LOCAL_CFLAGS += -Wno-multichar
+
+LOCAL_SHARED_LIBRARIES += libstlport
+include external/stlport/libstlport.mk
+
+LOCAL_MODULE:= libstagefright_chromium_http
+
+include $(BUILD_STATIC_LIBRARY)
+endif
diff --git a/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
new file mode 100644
index 0000000..76f7946
--- /dev/null
+++ b/media/libstagefright/chromium_http/ChromiumHTTPDataSource.cpp
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ChromiumHTTPDataSource"
+#include <media/stagefright/foundation/ADebug.h>
+
+#include "include/ChromiumHTTPDataSource.h"
+
+#include <media/stagefright/foundation/ALooper.h>
+#include <media/stagefright/MediaErrors.h>
+
+#include "support.h"
+
+#include <cutils/properties.h> // for property_get
+
+namespace android {
+
+ChromiumHTTPDataSource::ChromiumHTTPDataSource(uint32_t flags)
+ : mFlags(flags),
+ mState(DISCONNECTED),
+ mDelegate(new SfDelegate),
+ mCurrentOffset(0),
+ mIOResult(OK),
+ mContentSize(-1),
+ mDecryptHandle(NULL),
+ mDrmManagerClient(NULL) {
+ mDelegate->setOwner(this);
+}
+
+ChromiumHTTPDataSource::~ChromiumHTTPDataSource() {
+ disconnect();
+
+ delete mDelegate;
+ mDelegate = NULL;
+
+ clearDRMState_l();
+
+ if (mDrmManagerClient != NULL) {
+ delete mDrmManagerClient;
+ mDrmManagerClient = NULL;
+ }
+}
+
+status_t ChromiumHTTPDataSource::connect(
+ const char *uri,
+ const KeyedVector<String8, String8> *headers,
+ off64_t offset) {
+ Mutex::Autolock autoLock(mLock);
+
+ uid_t uid;
+ if (getUID(&uid)) {
+ mDelegate->setUID(uid);
+ }
+ LOG_PRI(ANDROID_LOG_VERBOSE, LOG_TAG, "connect on behalf of uid %d", uid);
+
+ return connect_l(uri, headers, offset);
+}
+
+status_t ChromiumHTTPDataSource::connect_l(
+ const char *uri,
+ const KeyedVector<String8, String8> *headers,
+ off64_t offset) {
+ if (mState != DISCONNECTED) {
+ disconnect_l();
+ }
+
+ if (!(mFlags & kFlagIncognito)) {
+ LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "connect to %s @%lld", uri, offset);
+ } else {
+ LOG_PRI(ANDROID_LOG_INFO, LOG_TAG,
+ "connect to <URL suppressed> @%lld", offset);
+ }
+
+ mURI = uri;
+ mContentType = String8("application/octet-stream");
+
+ if (headers != NULL) {
+ mHeaders = *headers;
+ } else {
+ mHeaders.clear();
+ }
+
+ mState = CONNECTING;
+ mContentSize = -1;
+ mCurrentOffset = offset;
+
+ mDelegate->initiateConnection(mURI.c_str(), &mHeaders, offset);
+
+ while (mState == CONNECTING) {
+ mCondition.wait(mLock);
+ }
+
+ return mState == CONNECTED ? OK : mIOResult;
+}
+
+void ChromiumHTTPDataSource::onConnectionEstablished(
+ int64_t contentSize, const char *contentType) {
+ Mutex::Autolock autoLock(mLock);
+ mState = CONNECTED;
+ mContentSize = (contentSize < 0) ? -1 : contentSize + mCurrentOffset;
+ mContentType = String8(contentType);
+ mCondition.broadcast();
+}
+
+void ChromiumHTTPDataSource::onConnectionFailed(status_t err) {
+ Mutex::Autolock autoLock(mLock);
+ mState = DISCONNECTED;
+ mCondition.broadcast();
+
+ // mURI.clear();
+
+ mIOResult = err;
+}
+
+void ChromiumHTTPDataSource::disconnect() {
+ Mutex::Autolock autoLock(mLock);
+ disconnect_l();
+}
+
+void ChromiumHTTPDataSource::disconnect_l() {
+ if (mState == DISCONNECTED) {
+ return;
+ }
+
+ mState = DISCONNECTING;
+ mIOResult = -EINTR;
+
+ mDelegate->initiateDisconnect();
+
+ while (mState == DISCONNECTING) {
+ mCondition.wait(mLock);
+ }
+
+ CHECK_EQ((int)mState, (int)DISCONNECTED);
+}
+
+status_t ChromiumHTTPDataSource::initCheck() const {
+ Mutex::Autolock autoLock(mLock);
+
+ return mState == CONNECTED ? OK : NO_INIT;
+}
+
+ssize_t ChromiumHTTPDataSource::readAt(off64_t offset, void *data, size_t size) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mState != CONNECTED) {
+ return INVALID_OPERATION;
+ }
+
+#if 0
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("media.stagefright.disable-net", value, 0)
+ && (!strcasecmp(value, "true") || !strcmp(value, "1"))) {
+ LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "Simulating that the network is down.");
+ disconnect_l();
+ return ERROR_IO;
+ }
+#endif
+
+ if (offset != mCurrentOffset) {
+ AString tmp = mURI;
+ KeyedVector<String8, String8> tmpHeaders = mHeaders;
+
+ disconnect_l();
+
+ status_t err = connect_l(tmp.c_str(), &tmpHeaders, offset);
+
+ if (err != OK) {
+ return err;
+ }
+ }
+
+ mState = READING;
+
+ int64_t startTimeUs = ALooper::GetNowUs();
+
+ mDelegate->initiateRead(data, size);
+
+ while (mState == READING) {
+ mCondition.wait(mLock);
+ }
+
+ if (mIOResult < OK) {
+ return mIOResult;
+ }
+
+ if (mState == CONNECTED) {
+ int64_t delayUs = ALooper::GetNowUs() - startTimeUs;
+
+ // The read operation was successful, mIOResult contains
+ // the number of bytes read.
+ addBandwidthMeasurement(mIOResult, delayUs);
+
+ mCurrentOffset += mIOResult;
+ return mIOResult;
+ }
+
+ return ERROR_IO;
+}
+
+void ChromiumHTTPDataSource::onReadCompleted(ssize_t size) {
+ Mutex::Autolock autoLock(mLock);
+
+ mIOResult = size;
+
+ if (mState == READING) {
+ mState = CONNECTED;
+ mCondition.broadcast();
+ }
+}
+
+status_t ChromiumHTTPDataSource::getSize(off64_t *size) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mContentSize < 0) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ *size = mContentSize;
+
+ return OK;
+}
+
+uint32_t ChromiumHTTPDataSource::flags() {
+ return kWantsPrefetching | kIsHTTPBasedSource;
+}
+
+// static
+void ChromiumHTTPDataSource::InitiateRead(
+ ChromiumHTTPDataSource *me, void *data, size_t size) {
+ me->initiateRead(data, size);
+}
+
+void ChromiumHTTPDataSource::initiateRead(void *data, size_t size) {
+ mDelegate->initiateRead(data, size);
+}
+
+void ChromiumHTTPDataSource::onDisconnectComplete() {
+ Mutex::Autolock autoLock(mLock);
+ CHECK_EQ((int)mState, (int)DISCONNECTING);
+
+ mState = DISCONNECTED;
+ // mURI.clear();
+
+ mCondition.broadcast();
+}
+
+sp<DecryptHandle> ChromiumHTTPDataSource::DrmInitialization(const char* mime) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mDrmManagerClient == NULL) {
+ mDrmManagerClient = new DrmManagerClient();
+ }
+
+ if (mDrmManagerClient == NULL) {
+ return NULL;
+ }
+
+ if (mDecryptHandle == NULL) {
+ /* Note if redirect occurs, mUri is the redirect uri instead of the
+ * original one
+ */
+ mDecryptHandle = mDrmManagerClient->openDecryptSession(
+ String8(mURI.c_str()), mime);
+ }
+
+ if (mDecryptHandle == NULL) {
+ delete mDrmManagerClient;
+ mDrmManagerClient = NULL;
+ }
+
+ return mDecryptHandle;
+}
+
+void ChromiumHTTPDataSource::getDrmInfo(
+ sp<DecryptHandle> &handle, DrmManagerClient **client) {
+ Mutex::Autolock autoLock(mLock);
+
+ handle = mDecryptHandle;
+ *client = mDrmManagerClient;
+}
+
+String8 ChromiumHTTPDataSource::getUri() {
+ Mutex::Autolock autoLock(mLock);
+
+ return String8(mURI.c_str());
+}
+
+String8 ChromiumHTTPDataSource::getMIMEType() const {
+ Mutex::Autolock autoLock(mLock);
+
+ return mContentType;
+}
+
+void ChromiumHTTPDataSource::clearDRMState_l() {
+ if (mDecryptHandle != NULL) {
+ // To release mDecryptHandle
+ CHECK(mDrmManagerClient);
+ mDrmManagerClient->closeDecryptSession(mDecryptHandle);
+ mDecryptHandle = NULL;
+ }
+}
+
+status_t ChromiumHTTPDataSource::reconnectAtOffset(off64_t offset) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mURI.empty()) {
+ return INVALID_OPERATION;
+ }
+
+ LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "Reconnecting...");
+ status_t err = connect_l(mURI.c_str(), &mHeaders, offset);
+ if (err != OK) {
+ LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "Reconnect failed w/ err 0x%08x", err);
+ }
+
+ return err;
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/chromium_http/DataUriSource.cpp b/media/libstagefright/chromium_http/DataUriSource.cpp
new file mode 100644
index 0000000..ecf3fa1
--- /dev/null
+++ b/media/libstagefright/chromium_http/DataUriSource.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <include/DataUriSource.h>
+
+#include <net/base/data_url.h>
+#include <googleurl/src/gurl.h>
+
+
+namespace android {
+
+DataUriSource::DataUriSource(const char *uri) :
+ mDataUri(uri),
+ mInited(NO_INIT) {
+
+ // Copy1: const char *uri -> String8 mDataUri.
+ std::string mimeTypeStr, unusedCharsetStr, dataStr;
+ // Copy2: String8 mDataUri -> std::string
+ const bool ret = net::DataURL::Parse(
+ GURL(std::string(mDataUri.string())),
+ &mimeTypeStr, &unusedCharsetStr, &dataStr);
+ // Copy3: std::string dataStr -> AString mData
+ mData.setTo(dataStr.data(), dataStr.length());
+ mInited = ret ? OK : UNKNOWN_ERROR;
+
+ // The chromium data url implementation defaults to using "text/plain"
+ // if no mime type is specified. We prefer to leave this unspecified
+ // instead, since the mime type is sniffed in most cases.
+ if (mimeTypeStr != "text/plain") {
+ mMimeType = mimeTypeStr.c_str();
+ }
+}
+
+ssize_t DataUriSource::readAt(off64_t offset, void *out, size_t size) {
+ if (mInited != OK) {
+ return mInited;
+ }
+
+ const off64_t length = mData.size();
+ if (offset >= length) {
+ return UNKNOWN_ERROR;
+ }
+
+ const char *dataBuf = mData.c_str();
+ const size_t bytesToCopy =
+ offset + size >= length ? (length - offset) : size;
+
+ if (bytesToCopy > 0) {
+ memcpy(out, dataBuf + offset, bytesToCopy);
+ }
+
+ return bytesToCopy;
+}
+
+} // namespace android
diff --git a/media/libstagefright/chromium_http/support.cpp b/media/libstagefright/chromium_http/support.cpp
new file mode 100644
index 0000000..f15014e
--- /dev/null
+++ b/media/libstagefright/chromium_http/support.cpp
@@ -0,0 +1,531 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ChromiumHTTPDataSourceSupport"
+#include <utils/Log.h>
+
+#include <media/stagefright/foundation/AString.h>
+
+#include "support.h"
+
+#include "android/net/android_network_library_impl.h"
+#include "base/logging.h"
+#include "base/threading/thread.h"
+#include "net/base/cert_verifier.h"
+#include "net/base/cookie_monster.h"
+#include "net/base/host_resolver.h"
+#include "net/base/ssl_config_service.h"
+#include "net/http/http_auth_handler_factory.h"
+#include "net/http/http_cache.h"
+#include "net/proxy/proxy_config_service_android.h"
+
+#include "include/ChromiumHTTPDataSource.h"
+
+#include <cutils/log.h>
+#include <cutils/properties.h>
+#include <media/stagefright/MediaErrors.h>
+#include <string>
+
+namespace android {
+
+static Mutex gNetworkThreadLock;
+static base::Thread *gNetworkThread = NULL;
+static scoped_refptr<net::URLRequestContext> gReqContext;
+static scoped_ptr<net::NetworkChangeNotifier> gNetworkChangeNotifier;
+
+bool logMessageHandler(
+ int severity,
+ const char* file,
+ int line,
+ size_t message_start,
+ const std::string& str) {
+ int androidSeverity = ANDROID_LOG_VERBOSE;
+ switch(severity) {
+ case logging::LOG_FATAL:
+ androidSeverity = ANDROID_LOG_FATAL;
+ break;
+ case logging::LOG_ERROR_REPORT:
+ case logging::LOG_ERROR:
+ androidSeverity = ANDROID_LOG_ERROR;
+ break;
+ case logging::LOG_WARNING:
+ androidSeverity = ANDROID_LOG_WARN;
+ break;
+ default:
+ androidSeverity = ANDROID_LOG_VERBOSE;
+ break;
+ }
+ android_printLog(androidSeverity, "chromium-libstagefright",
+ "%s:%d: %s", file, line, str.c_str());
+ return false;
+}
+
+struct AutoPrioritySaver {
+ AutoPrioritySaver()
+ : mTID(androidGetTid()),
+ mPrevPriority(androidGetThreadPriority(mTID)) {
+ androidSetThreadPriority(mTID, ANDROID_PRIORITY_NORMAL);
+ }
+
+ ~AutoPrioritySaver() {
+ androidSetThreadPriority(mTID, mPrevPriority);
+ }
+
+private:
+ pid_t mTID;
+ int mPrevPriority;
+
+ DISALLOW_EVIL_CONSTRUCTORS(AutoPrioritySaver);
+};
+
+static void InitializeNetworkThreadIfNecessary() {
+ Mutex::Autolock autoLock(gNetworkThreadLock);
+
+ if (gNetworkThread == NULL) {
+ // Make sure any threads spawned by the chromium framework are
+ // running at normal priority instead of inheriting this thread's.
+ AutoPrioritySaver saver;
+
+ gNetworkThread = new base::Thread("network");
+ base::Thread::Options options;
+ options.message_loop_type = MessageLoop::TYPE_IO;
+ CHECK(gNetworkThread->StartWithOptions(options));
+
+ gReqContext = new SfRequestContext;
+
+ gNetworkChangeNotifier.reset(net::NetworkChangeNotifier::Create());
+
+ net::AndroidNetworkLibrary::RegisterSharedInstance(
+ new SfNetworkLibrary);
+ logging::SetLogMessageHandler(logMessageHandler);
+ }
+}
+
+static void MY_LOGI(const char *s) {
+ LOG_PRI(ANDROID_LOG_INFO, LOG_TAG, "%s", s);
+}
+
+static void MY_LOGV(const char *s) {
+#if !defined(LOG_NDEBUG) || LOG_NDEBUG == 0
+ LOG_PRI(ANDROID_LOG_VERBOSE, LOG_TAG, "%s", s);
+#endif
+}
+
+SfNetLog::SfNetLog()
+ : mNextID(1) {
+}
+
+void SfNetLog::AddEntry(
+ EventType type,
+ const base::TimeTicks &time,
+ const Source &source,
+ EventPhase phase,
+ EventParameters *params) {
+#if 0
+ MY_LOGI(StringPrintf(
+ "AddEntry time=%s type=%s source=%s phase=%s\n",
+ TickCountToString(time).c_str(),
+ EventTypeToString(type),
+ SourceTypeToString(source.type),
+ EventPhaseToString(phase)).c_str());
+#endif
+}
+
+uint32 SfNetLog::NextID() {
+ return mNextID++;
+}
+
+net::NetLog::LogLevel SfNetLog::GetLogLevel() const {
+ return LOG_ALL;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SfRequestContext::SfRequestContext() {
+ AString ua;
+ ua.append("stagefright/1.2 (Linux;Android ");
+
+#if (PROPERTY_VALUE_MAX < 8)
+#error "PROPERTY_VALUE_MAX must be at least 8"
+#endif
+
+ char value[PROPERTY_VALUE_MAX];
+ property_get("ro.build.version.release", value, "Unknown");
+ ua.append(value);
+ ua.append(")");
+
+ mUserAgent = ua.c_str();
+
+ set_net_log(new SfNetLog());
+
+ set_host_resolver(
+ net::CreateSystemHostResolver(
+ net::HostResolver::kDefaultParallelism,
+ NULL /* resolver_proc */,
+ net_log()));
+
+ set_ssl_config_service(
+ net::SSLConfigService::CreateSystemSSLConfigService());
+
+ set_proxy_service(net::ProxyService::CreateWithoutProxyResolver(
+ new net::ProxyConfigServiceAndroid, net_log()));
+
+ set_http_transaction_factory(new net::HttpCache(
+ host_resolver(),
+ new net::CertVerifier(),
+ dnsrr_resolver(),
+ dns_cert_checker(),
+ proxy_service(),
+ ssl_config_service(),
+ net::HttpAuthHandlerFactory::CreateDefault(host_resolver()),
+ network_delegate(),
+ net_log(),
+ NULL)); // backend_factory
+
+ set_cookie_store(new net::CookieMonster(NULL, NULL));
+}
+
+const std::string &SfRequestContext::GetUserAgent(const GURL &url) const {
+ return mUserAgent;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SfNetworkLibrary::SfNetworkLibrary() {}
+
+SfNetworkLibrary::VerifyResult SfNetworkLibrary::VerifyX509CertChain(
+ const std::vector<std::string>& cert_chain,
+ const std::string& hostname,
+ const std::string& auth_type) {
+ return VERIFY_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SfDelegate::SfDelegate()
+ : mOwner(NULL),
+ mURLRequest(NULL),
+ mReadBuffer(new net::IOBufferWithSize(8192)),
+ mNumBytesRead(0),
+ mNumBytesTotal(0),
+ mDataDestination(NULL),
+ mAtEOS(false) {
+ InitializeNetworkThreadIfNecessary();
+}
+
+SfDelegate::~SfDelegate() {
+ CHECK(mURLRequest == NULL);
+}
+
+void SfDelegate::setOwner(ChromiumHTTPDataSource *owner) {
+ mOwner = owner;
+}
+
+void SfDelegate::setUID(uid_t uid) {
+ gReqContext->setUID(uid);
+}
+
+bool SfDelegate::getUID(uid_t *uid) const {
+ return gReqContext->getUID(uid);
+}
+
+void SfDelegate::OnReceivedRedirect(
+ net::URLRequest *request, const GURL &new_url, bool *defer_redirect) {
+ MY_LOGV("OnReceivedRedirect");
+}
+
+void SfDelegate::OnAuthRequired(
+ net::URLRequest *request, net::AuthChallengeInfo *auth_info) {
+ MY_LOGV("OnAuthRequired");
+
+ inherited::OnAuthRequired(request, auth_info);
+}
+
+void SfDelegate::OnCertificateRequested(
+ net::URLRequest *request, net::SSLCertRequestInfo *cert_request_info) {
+ MY_LOGV("OnCertificateRequested");
+
+ inherited::OnCertificateRequested(request, cert_request_info);
+}
+
+void SfDelegate::OnSSLCertificateError(
+ net::URLRequest *request, int cert_error, net::X509Certificate *cert) {
+ fprintf(stderr, "OnSSLCertificateError cert_error=%d\n", cert_error);
+
+ inherited::OnSSLCertificateError(request, cert_error, cert);
+}
+
+void SfDelegate::OnGetCookies(net::URLRequest *request, bool blocked_by_policy) {
+ MY_LOGV("OnGetCookies");
+}
+
+void SfDelegate::OnSetCookie(
+ net::URLRequest *request,
+ const std::string &cookie_line,
+ const net::CookieOptions &options,
+ bool blocked_by_policy) {
+ MY_LOGV("OnSetCookie");
+}
+
+void SfDelegate::OnResponseStarted(net::URLRequest *request) {
+ if (request->status().status() != net::URLRequestStatus::SUCCESS) {
+ MY_LOGI(StringPrintf(
+ "Request failed with status %d and os_error %d",
+ request->status().status(),
+ request->status().os_error()).c_str());
+
+ delete mURLRequest;
+ mURLRequest = NULL;
+
+ mOwner->onConnectionFailed(ERROR_IO);
+ return;
+ } else if (mRangeRequested && request->GetResponseCode() != 206) {
+ MY_LOGI(StringPrintf(
+ "We requested a content range, but server didn't "
+ "support that. (responded with %d)",
+ request->GetResponseCode()).c_str());
+
+ delete mURLRequest;
+ mURLRequest = NULL;
+
+ mOwner->onConnectionFailed(-EPIPE);
+ return;
+ } else if ((request->GetResponseCode() / 100) != 2) {
+ MY_LOGI(StringPrintf(
+ "Server responded with http status %d",
+ request->GetResponseCode()).c_str());
+
+ delete mURLRequest;
+ mURLRequest = NULL;
+
+ mOwner->onConnectionFailed(ERROR_IO);
+ return;
+ }
+
+ MY_LOGV("OnResponseStarted");
+
+ std::string headers;
+ request->GetAllResponseHeaders(&headers);
+
+ MY_LOGV(StringPrintf("response headers: %s", headers.c_str()).c_str());
+
+ std::string contentType;
+ request->GetResponseHeaderByName("Content-Type", &contentType);
+
+ mOwner->onConnectionEstablished(
+ request->GetExpectedContentSize(), contentType.c_str());
+}
+
+void SfDelegate::OnReadCompleted(net::URLRequest *request, int bytes_read) {
+ if (bytes_read == -1) {
+ MY_LOGI(StringPrintf(
+ "OnReadCompleted, read failed, status %d",
+ request->status().status()).c_str());
+
+ mOwner->onReadCompleted(ERROR_IO);
+ return;
+ }
+
+ MY_LOGV(StringPrintf("OnReadCompleted, read %d bytes", bytes_read).c_str());
+
+ if (bytes_read < 0) {
+ MY_LOGI(StringPrintf(
+ "Read failed w/ status %d\n",
+ request->status().status()).c_str());
+
+ mOwner->onReadCompleted(ERROR_IO);
+ return;
+ } else if (bytes_read == 0) {
+ mAtEOS = true;
+ mOwner->onReadCompleted(mNumBytesRead);
+ return;
+ }
+
+ CHECK_GT(bytes_read, 0);
+ CHECK_LE(mNumBytesRead + bytes_read, mNumBytesTotal);
+
+ memcpy((uint8_t *)mDataDestination + mNumBytesRead,
+ mReadBuffer->data(),
+ bytes_read);
+
+ mNumBytesRead += bytes_read;
+
+ readMore(request);
+}
+
+void SfDelegate::readMore(net::URLRequest *request) {
+ while (mNumBytesRead < mNumBytesTotal) {
+ size_t copy = mNumBytesTotal - mNumBytesRead;
+ if (copy > mReadBuffer->size()) {
+ copy = mReadBuffer->size();
+ }
+
+ int n;
+ if (request->Read(mReadBuffer, copy, &n)) {
+ MY_LOGV(StringPrintf("Read %d bytes directly.", n).c_str());
+
+ CHECK_LE((size_t)n, copy);
+
+ memcpy((uint8_t *)mDataDestination + mNumBytesRead,
+ mReadBuffer->data(),
+ n);
+
+ mNumBytesRead += n;
+
+ if (n == 0) {
+ mAtEOS = true;
+ break;
+ }
+ } else {
+ MY_LOGV("readMore pending read");
+
+ if (request->status().status() != net::URLRequestStatus::IO_PENDING) {
+ MY_LOGI(StringPrintf(
+ "Direct read failed w/ status %d\n",
+ request->status().status()).c_str());
+
+ mOwner->onReadCompleted(ERROR_IO);
+ return;
+ }
+
+ return;
+ }
+ }
+
+ mOwner->onReadCompleted(mNumBytesRead);
+}
+
+void SfDelegate::initiateConnection(
+ const char *uri,
+ const KeyedVector<String8, String8> *headers,
+ off64_t offset) {
+ GURL url(uri);
+
+ MessageLoop *loop = gNetworkThread->message_loop();
+ loop->PostTask(
+ FROM_HERE,
+ NewRunnableFunction(
+ &SfDelegate::OnInitiateConnectionWrapper,
+ this,
+ url,
+ headers,
+ offset));
+
+}
+
+// static
+void SfDelegate::OnInitiateConnectionWrapper(
+ SfDelegate *me, GURL url,
+ const KeyedVector<String8, String8> *headers,
+ off64_t offset) {
+ me->onInitiateConnection(url, headers, offset);
+}
+
+void SfDelegate::onInitiateConnection(
+ const GURL &url,
+ const KeyedVector<String8, String8> *extra,
+ off64_t offset) {
+ CHECK(mURLRequest == NULL);
+
+ mURLRequest = new net::URLRequest(url, this);
+ mAtEOS = false;
+
+ mRangeRequested = false;
+
+ if (offset != 0 || extra != NULL) {
+ net::HttpRequestHeaders headers =
+ mURLRequest->extra_request_headers();
+
+ if (offset != 0) {
+ headers.AddHeaderFromString(
+ StringPrintf("Range: bytes=%lld-", offset).c_str());
+
+ mRangeRequested = true;
+ }
+
+ if (extra != NULL) {
+ for (size_t i = 0; i < extra->size(); ++i) {
+ AString s;
+ s.append(extra->keyAt(i).string());
+ s.append(": ");
+ s.append(extra->valueAt(i).string());
+
+ headers.AddHeaderFromString(s.c_str());
+ }
+ }
+
+ mURLRequest->SetExtraRequestHeaders(headers);
+ }
+
+ mURLRequest->set_context(gReqContext);
+
+ mURLRequest->Start();
+}
+
+void SfDelegate::initiateDisconnect() {
+ MessageLoop *loop = gNetworkThread->message_loop();
+ loop->PostTask(
+ FROM_HERE,
+ NewRunnableFunction(
+ &SfDelegate::OnInitiateDisconnectWrapper, this));
+}
+
+// static
+void SfDelegate::OnInitiateDisconnectWrapper(SfDelegate *me) {
+ me->onInitiateDisconnect();
+}
+
+void SfDelegate::onInitiateDisconnect() {
+ mURLRequest->Cancel();
+
+ delete mURLRequest;
+ mURLRequest = NULL;
+
+ mOwner->onDisconnectComplete();
+}
+
+void SfDelegate::initiateRead(void *data, size_t size) {
+ MessageLoop *loop = gNetworkThread->message_loop();
+ loop->PostTask(
+ FROM_HERE,
+ NewRunnableFunction(
+ &SfDelegate::OnInitiateReadWrapper, this, data, size));
+}
+
+// static
+void SfDelegate::OnInitiateReadWrapper(
+ SfDelegate *me, void *data, size_t size) {
+ me->onInitiateRead(data, size);
+}
+
+void SfDelegate::onInitiateRead(void *data, size_t size) {
+ CHECK(mURLRequest != NULL);
+
+ mNumBytesRead = 0;
+ mNumBytesTotal = size;
+ mDataDestination = data;
+
+ if (mAtEOS) {
+ mOwner->onReadCompleted(0);
+ return;
+ }
+
+ readMore(mURLRequest);
+}
+
+} // namespace android
+
diff --git a/media/libstagefright/chromium_http/support.h b/media/libstagefright/chromium_http/support.h
new file mode 100644
index 0000000..d2c5bc0
--- /dev/null
+++ b/media/libstagefright/chromium_http/support.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SUPPORT_H_
+
+#define SUPPORT_H_
+
+#include <assert.h>
+
+#include "net/base/net_log.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_context.h"
+#include "net/base/android_network_library.h"
+#include "net/base/io_buffer.h"
+
+#include <utils/KeyedVector.h>
+#include <utils/String8.h>
+
+namespace android {
+
+struct SfNetLog : public net::NetLog {
+ SfNetLog();
+
+ virtual void AddEntry(
+ EventType type,
+ const base::TimeTicks &time,
+ const Source &source,
+ EventPhase phase,
+ EventParameters *params);
+
+ virtual uint32 NextID();
+ virtual LogLevel GetLogLevel() const;
+
+private:
+ uint32 mNextID;
+
+ DISALLOW_EVIL_CONSTRUCTORS(SfNetLog);
+};
+
+struct SfRequestContext : public net::URLRequestContext {
+ SfRequestContext();
+
+ virtual const std::string &GetUserAgent(const GURL &url) const;
+
+private:
+ std::string mUserAgent;
+
+ DISALLOW_EVIL_CONSTRUCTORS(SfRequestContext);
+};
+
+// This is required for https support, we don't really verify certificates,
+// we accept anything...
+struct SfNetworkLibrary : public net::AndroidNetworkLibrary {
+ SfNetworkLibrary();
+
+ virtual VerifyResult VerifyX509CertChain(
+ const std::vector<std::string>& cert_chain,
+ const std::string& hostname,
+ const std::string& auth_type);
+
+private:
+ DISALLOW_EVIL_CONSTRUCTORS(SfNetworkLibrary);
+};
+
+struct ChromiumHTTPDataSource;
+
+struct SfDelegate : public net::URLRequest::Delegate {
+ SfDelegate();
+ virtual ~SfDelegate();
+
+ void initiateConnection(
+ const char *uri,
+ const KeyedVector<String8, String8> *headers,
+ off64_t offset);
+
+ void initiateDisconnect();
+ void initiateRead(void *data, size_t size);
+
+ void setOwner(ChromiumHTTPDataSource *mOwner);
+
+ // Gets the UID of the calling process
+ bool getUID(uid_t *uid) const;
+
+ void setUID(uid_t uid);
+
+ virtual void OnReceivedRedirect(
+ net::URLRequest *request, const GURL &new_url, bool *defer_redirect);
+
+ virtual void OnAuthRequired(
+ net::URLRequest *request, net::AuthChallengeInfo *auth_info);
+
+ virtual void OnCertificateRequested(
+ net::URLRequest *request, net::SSLCertRequestInfo *cert_request_info);
+
+ virtual void OnSSLCertificateError(
+ net::URLRequest *request, int cert_error, net::X509Certificate *cert);
+
+ virtual void OnGetCookies(net::URLRequest *request, bool blocked_by_policy);
+
+ virtual void OnSetCookie(
+ net::URLRequest *request,
+ const std::string &cookie_line,
+ const net::CookieOptions &options,
+ bool blocked_by_policy);
+
+ virtual void OnResponseStarted(net::URLRequest *request);
+
+ virtual void OnReadCompleted(net::URLRequest *request, int bytes_read);
+
+private:
+ typedef Delegate inherited;
+
+ ChromiumHTTPDataSource *mOwner;
+
+ net::URLRequest *mURLRequest;
+ scoped_refptr<net::IOBufferWithSize> mReadBuffer;
+
+ size_t mNumBytesRead;
+ size_t mNumBytesTotal;
+ void *mDataDestination;
+
+ bool mRangeRequested;
+ bool mAtEOS;
+
+ void readMore(net::URLRequest *request);
+
+ static void OnInitiateConnectionWrapper(
+ SfDelegate *me,
+ GURL url,
+ const KeyedVector<String8, String8> *headers,
+ off64_t offset);
+
+ static void OnInitiateDisconnectWrapper(SfDelegate *me);
+
+ static void OnInitiateReadWrapper(
+ SfDelegate *me, void *data, size_t size);
+
+ void onInitiateConnection(
+ const GURL &url,
+ const KeyedVector<String8, String8> *headers,
+ off64_t offset);
+
+ void onInitiateDisconnect();
+ void onInitiateRead(void *data, size_t size);
+
+ DISALLOW_EVIL_CONSTRUCTORS(SfDelegate);
+};
+
+} // namespace android
+
+#endif // SUPPORT_H_