summaryrefslogtreecommitdiffstats
path: root/android_webview/native
diff options
context:
space:
mode:
authormnaganov@chromium.org <mnaganov@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-27 18:36:26 +0000
committermnaganov@chromium.org <mnaganov@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-09-27 18:36:26 +0000
commite7bee399b0d064cdd281bc567a2736852079e87a (patch)
treee9c1b83b4d70a1d8bc52021db2d96a91f33eb8e7 /android_webview/native
parent0d2cb888776e6a8e0dd4939390a2b9c220ff40fa (diff)
downloadchromium_src-e7bee399b0d064cdd281bc567a2736852079e87a.zip
chromium_src-e7bee399b0d064cdd281bc567a2736852079e87a.tar.gz
chromium_src-e7bee399b0d064cdd281bc567a2736852079e87a.tar.bz2
Move AndroidProtocolAdaptor into android_webview
Also move Android-specific URL constants into android_webview R=benm@chromium.org,joth@chromium.org Review URL: https://chromiumcodereview.appspot.com/10985044 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@159078 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'android_webview/native')
-rw-r--r--android_webview/native/android_protocol_handler.cc285
-rw-r--r--android_webview/native/android_protocol_handler.h42
-rw-r--r--android_webview/native/android_stream_reader_url_request_job.cc228
-rw-r--r--android_webview/native/android_stream_reader_url_request_job.h81
-rw-r--r--android_webview/native/android_webview_jni_registrar.cc5
-rw-r--r--android_webview/native/webview_native.gyp18
6 files changed, 659 insertions, 0 deletions
diff --git a/android_webview/native/android_protocol_handler.cc b/android_webview/native/android_protocol_handler.cc
new file mode 100644
index 0000000..d8ef423
--- /dev/null
+++ b/android_webview/native/android_protocol_handler.cc
@@ -0,0 +1,285 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// URL request job for reading from resources and assets.
+
+#include "android_webview/native/android_protocol_handler.h"
+
+#include "android_webview/common/url_constants.h"
+#include "android_webview/native/android_stream_reader_url_request_job.h"
+#include "base/android/jni_android.h"
+#include "base/android/jni_helper.h"
+#include "base/android/jni_string.h"
+#include "base/string_util.h"
+#include "content/public/common/url_constants.h"
+#include "googleurl/src/gurl.h"
+#include "jni/AndroidProtocolHandler_jni.h"
+#include "net/base/io_buffer.h"
+#include "net/base/mime_util.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_util.h"
+#include "net/http/http_util.h"
+#include "net/url_request/url_request_context.h"
+#include "net/url_request/url_request_context_getter.h"
+#include "net/url_request/url_request_job_factory.h"
+#include "net/url_request/url_request_job_manager.h"
+
+using base::android::AttachCurrentThread;
+using base::android::ClearException;
+using base::android::ConvertUTF8ToJavaString;
+using base::android::ScopedJavaGlobalRef;
+using base::android::ScopedJavaLocalRef;
+
+namespace {
+
+// Override resource context for reading resource and asset files. Used for
+// testing.
+JavaObjectWeakGlobalRef* g_resource_context = NULL;
+
+void ResetResourceContext(JavaObjectWeakGlobalRef* ref) {
+ if (g_resource_context)
+ delete g_resource_context;
+
+ g_resource_context = ref;
+}
+
+class AndroidStreamReaderURLRequestJobDelegateImpl
+ : public AndroidStreamReaderURLRequestJob::Delegate {
+ public:
+ AndroidStreamReaderURLRequestJobDelegateImpl();
+
+ virtual ScopedJavaLocalRef<jobject> OpenInputStream(
+ JNIEnv* env,
+ net::URLRequest* request) OVERRIDE;
+
+ virtual bool GetMimeType(JNIEnv* env,
+ net::URLRequest* request,
+ jobject stream,
+ std::string* mime_type) OVERRIDE;
+
+ virtual bool GetCharset(JNIEnv* env,
+ net::URLRequest* request,
+ jobject stream,
+ std::string* charset) OVERRIDE;
+
+ virtual ~AndroidStreamReaderURLRequestJobDelegateImpl();
+};
+
+class AssetFileProtocolInterceptor :
+ public net::URLRequestJobFactory::Interceptor {
+ public:
+ AssetFileProtocolInterceptor();
+ virtual ~AssetFileProtocolInterceptor() OVERRIDE;
+ virtual net::URLRequestJob* MaybeIntercept(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const OVERRIDE;
+ virtual net::URLRequestJob* MaybeInterceptRedirect(
+ const GURL& location,
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const OVERRIDE;
+ virtual net::URLRequestJob* MaybeInterceptResponse(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const OVERRIDE;
+
+ private:
+ // file:///android_asset/
+ const std::string asset_prefix_;
+ // file:///android_res/
+ const std::string resource_prefix_;
+};
+
+} // namespace
+
+// static
+net::URLRequestJob* AndroidProtocolHandler::Factory(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ const std::string& scheme) {
+ DCHECK(scheme == android_webview::kContentScheme);
+ return new AndroidStreamReaderURLRequestJob(
+ request,
+ network_delegate,
+ scoped_ptr<AndroidStreamReaderURLRequestJob::Delegate>(
+ new AndroidStreamReaderURLRequestJobDelegateImpl()));
+}
+
+static void AddFileSchemeInterceptorOnIOThread(
+ net::URLRequestContextGetter* context_getter) {
+ // The job factory takes ownership of the interceptor.
+ const_cast<net::URLRequestJobFactory*>(
+ context_getter->GetURLRequestContext()->job_factory())->AddInterceptor(
+ new AssetFileProtocolInterceptor());
+}
+
+bool RegisterAndroidProtocolHandler(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+// static
+void AndroidProtocolHandler::RegisterProtocols(
+ net::URLRequestContextGetter* context_getter) {
+ // Register content://. Note that even though a scheme is
+ // registered here, it cannot be used by child processes until access to it is
+ // granted via ChildProcessSecurityPolicy::GrantScheme(). This is done in
+ // RenderViewHost.
+ // TODO(mnaganov): Convert into a ProtocolHandler.
+ net::URLRequestJobManager* job_manager =
+ net::URLRequestJobManager::GetInstance();
+ job_manager->RegisterProtocolFactory(android_webview::kContentScheme,
+ &AndroidProtocolHandler::Factory);
+
+ // Register a file: scheme interceptor for application assets.
+ context_getter->GetNetworkTaskRunner()->PostTask(
+ FROM_HERE,
+ base::Bind(&AddFileSchemeInterceptorOnIOThread,
+ make_scoped_refptr(context_getter)));
+ // TODO(mnaganov): Add an interceptor for the incognito profile?
+}
+
+// Set a context object to be used for resolving resource queries. This can
+// be used to override the default application context and redirect all
+// resource queries to a specific context object, e.g., for the purposes of
+// testing.
+//
+// |context| should be a android.content.Context instance or NULL to enable
+// the use of the standard application context.
+static void SetResourceContextForTesting(JNIEnv* env, jclass /*clazz*/,
+ jobject context) {
+ if (context) {
+ ResetResourceContext(new JavaObjectWeakGlobalRef(env, context));
+ } else {
+ ResetResourceContext(NULL);
+ }
+}
+
+static jstring GetAndroidAssetPath(JNIEnv* env, jclass /*clazz*/) {
+ // OK to release, JNI binding.
+ return ConvertUTF8ToJavaString(
+ env, android_webview::kAndroidAssetPath).Release();
+}
+
+static jstring GetAndroidResourcePath(JNIEnv* env, jclass /*clazz*/) {
+ // OK to release, JNI binding.
+ return ConvertUTF8ToJavaString(
+ env, android_webview::kAndroidResourcePath).Release();
+}
+
+static ScopedJavaLocalRef<jobject> GetResourceContext(JNIEnv* env) {
+ if (g_resource_context)
+ return g_resource_context->get(env);
+ ScopedJavaLocalRef<jobject> context;
+ // We have to reset as GetApplicationContext() returns a jobject with a
+ // global ref. The constructor that takes a jobject would expect a local ref
+ // and would assert.
+ context.Reset(env, base::android::GetApplicationContext());
+ return context;
+}
+
+AndroidStreamReaderURLRequestJobDelegateImpl::
+AndroidStreamReaderURLRequestJobDelegateImpl() {
+}
+
+AndroidStreamReaderURLRequestJobDelegateImpl::
+~AndroidStreamReaderURLRequestJobDelegateImpl() {
+}
+
+ScopedJavaLocalRef<jobject>
+AndroidStreamReaderURLRequestJobDelegateImpl::OpenInputStream(
+ JNIEnv* env, net::URLRequest* request) {
+ DCHECK(request);
+ DCHECK(env);
+
+ // Open the input stream.
+ ScopedJavaLocalRef<jstring> url =
+ ConvertUTF8ToJavaString(env, request->url().spec());
+ ScopedJavaLocalRef<jobject> stream = Java_AndroidProtocolHandler_open(
+ env,
+ GetResourceContext(env).obj(),
+ url.obj());
+
+ // Check and clear pending exceptions.
+ if (ClearException(env) || stream.is_null()) {
+ DLOG(ERROR) << "Unable to open input stream for Android URL";
+ return ScopedJavaLocalRef<jobject>(env, NULL);
+ }
+ return stream;
+}
+
+bool AndroidStreamReaderURLRequestJobDelegateImpl::GetMimeType(
+ JNIEnv* env,
+ net::URLRequest* request,
+ jobject stream,
+ std::string* mime_type) {
+ DCHECK(env);
+ DCHECK(request);
+ DCHECK(mime_type);
+
+ if (!stream)
+ return false;
+
+ // Query the mime type from the Java side. It is possible for the query to
+ // fail, as the mime type cannot be determined for all supported schemes.
+ ScopedJavaLocalRef<jstring> url =
+ ConvertUTF8ToJavaString(env, request->url().spec());
+ ScopedJavaLocalRef<jstring> returned_type =
+ Java_AndroidProtocolHandler_getMimeType(env,
+ GetResourceContext(env).obj(),
+ stream, url.obj());
+ if (ClearException(env) || returned_type.is_null())
+ return false;
+
+ *mime_type = base::android::ConvertJavaStringToUTF8(returned_type);
+ return true;
+}
+
+bool AndroidStreamReaderURLRequestJobDelegateImpl::GetCharset(
+ JNIEnv* env,
+ net::URLRequest* request,
+ jobject stream,
+ std::string* charset) {
+ // TODO: We should probably be getting this from the managed side.
+ return false;
+}
+
+AssetFileProtocolInterceptor::AssetFileProtocolInterceptor()
+ : asset_prefix_(std::string(chrome::kFileScheme) +
+ std::string(content::kStandardSchemeSeparator) +
+ android_webview::kAndroidAssetPath),
+ resource_prefix_(std::string(chrome::kFileScheme) +
+ std::string(content::kStandardSchemeSeparator) +
+ android_webview::kAndroidResourcePath) {
+}
+
+AssetFileProtocolInterceptor::~AssetFileProtocolInterceptor() {
+}
+
+net::URLRequestJob* AssetFileProtocolInterceptor::MaybeIntercept(
+ net::URLRequest* request, net::NetworkDelegate* network_delegate) const {
+ if (!request->url().SchemeIsFile()) return NULL;
+
+ const std::string& url = request->url().spec();
+ if (!StartsWithASCII(url, asset_prefix_, /*case_sensitive=*/ true) &&
+ !StartsWithASCII(url, resource_prefix_, /*case_sensitive=*/ true)) {
+ return NULL;
+ }
+
+ return new AndroidStreamReaderURLRequestJob(
+ request,
+ network_delegate,
+ scoped_ptr<AndroidStreamReaderURLRequestJob::Delegate>(
+ new AndroidStreamReaderURLRequestJobDelegateImpl()));
+}
+
+net::URLRequestJob* AssetFileProtocolInterceptor::MaybeInterceptRedirect(
+ const GURL& location,
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const {
+ return NULL;
+}
+
+net::URLRequestJob* AssetFileProtocolInterceptor::MaybeInterceptResponse(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const {
+ return NULL;
+}
diff --git a/android_webview/native/android_protocol_handler.h b/android_webview/native/android_protocol_handler.h
new file mode 100644
index 0000000..a60b1f1
--- /dev/null
+++ b/android_webview/native/android_protocol_handler.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ANDROID_WEBVIEW_NATIVE_ANDROID_PROTOCOL_HANDLER_H_
+#define ANDROID_WEBVIEW_NATIVE_ANDROID_PROTOCOL_HANDLER_H_
+
+#include "base/android/jni_android.h"
+#include "net/url_request/url_request.h"
+
+namespace net {
+
+class URLRequestContextGetter;
+
+}
+
+// This class adds support for Android WebView-specific protocol schemes:
+//
+// - "content:" scheme is used for accessing data from Android content
+// providers, see http://developer.android.com/guide/topics/providers/
+// content-provider-basics.html#ContentURIs
+//
+// - "file:" scheme extension for accessing application assets and resources
+// (file:///android_asset/ and file:///android_res/), see
+// http://developer.android.com/reference/android/webkit/
+// WebSettings.html#setAllowFileAccess(boolean)
+//
+class AndroidProtocolHandler {
+ public:
+ static net::URLRequest::ProtocolFactory Factory;
+
+ // Register handlers for all supported Android protocol schemes.
+ static void RegisterProtocols(
+ net::URLRequestContextGetter* context_getter);
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(AndroidProtocolHandler);
+};
+
+bool RegisterAndroidProtocolHandler(JNIEnv* env);
+
+#endif // ANDROID_WEBVIEW_NATIVE_ANDROID_PROTOCOL_HANDLER_H_
diff --git a/android_webview/native/android_stream_reader_url_request_job.cc b/android_webview/native/android_stream_reader_url_request_job.cc
new file mode 100644
index 0000000..b288da6
--- /dev/null
+++ b/android_webview/native/android_stream_reader_url_request_job.cc
@@ -0,0 +1,228 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "android_webview/native/android_stream_reader_url_request_job.h"
+
+#include "base/android/jni_android.h"
+#include "base/android/jni_string.h"
+#include "net/base/io_buffer.h"
+#include "net/base/mime_util.h"
+#include "net/base/net_errors.h"
+#include "net/base/net_util.h"
+#include "net/http/http_util.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_error_job.h"
+#include "net/url_request/url_request_file_job.h"
+#include "net/url_request/url_request_job_manager.h"
+// Disable "Warnings treated as errors" for input_stream_jni as it's a Java
+// system class and we have to generate C++ hooks for all methods in the class
+// even if they're unused.
+#pragma GCC diagnostic ignored "-Wunused-function"
+#include "jni/InputStream_jni.h"
+
+using base::android::AttachCurrentThread;
+using base::android::ClearException;
+using base::android::ConvertUTF8ToJavaString;
+using base::android::ScopedJavaGlobalRef;
+using base::android::ScopedJavaLocalRef;
+using JNI_InputStream::Java_InputStream_available;
+using JNI_InputStream::Java_InputStream_skip;
+using JNI_InputStream::Java_InputStream_read;
+
+
+namespace {
+
+// Maximum number of bytes to be read in a single read.
+const int kBufferSize = 4096;
+
+} // namespace
+
+bool RegisterAndroidStreamReaderUrlRequestJob(JNIEnv* env) {
+ return JNI_InputStream::RegisterNativesImpl(env);
+}
+
+AndroidStreamReaderURLRequestJob::AndroidStreamReaderURLRequestJob(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ scoped_ptr<Delegate> delegate)
+ : URLRequestJob(request, network_delegate),
+ delegate_(delegate.Pass()) {
+ DCHECK(delegate_.get());
+}
+
+AndroidStreamReaderURLRequestJob::~AndroidStreamReaderURLRequestJob() {
+}
+
+void AndroidStreamReaderURLRequestJob::Start() {
+ JNIEnv* env = AttachCurrentThread();
+ DCHECK(env);
+
+ stream_.Reset(env, delegate_->OpenInputStream(env, request()).obj());
+ if (!stream_.obj()) {
+ NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+ net::ERR_FAILED));
+ return;
+ }
+
+ if (VerifyRequestedRange(env) && SkipToRequestedRange(env))
+ NotifyHeadersComplete();
+}
+
+bool AndroidStreamReaderURLRequestJob::VerifyRequestedRange(JNIEnv* env) {
+ int32_t size = Java_InputStream_available(env, stream_.obj());
+ if (ClearException(env)) {
+ NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+ net::ERR_FAILED));
+ return false;
+ }
+
+ if (size <= 0)
+ return true;
+
+ // Check that the requested range was valid.
+ if (!byte_range_.ComputeBounds(size)) {
+ NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+ net::ERR_REQUEST_RANGE_NOT_SATISFIABLE));
+ return false;
+ }
+
+ size = byte_range_.last_byte_position() -
+ byte_range_.first_byte_position() + 1;
+ DCHECK_GE(size, 0);
+ set_expected_content_size(size);
+
+ return true;
+}
+
+bool AndroidStreamReaderURLRequestJob::SkipToRequestedRange(JNIEnv* env) {
+ // Skip to the start of the requested data. This has to be done in a loop
+ // because the underlying InputStream is not guaranteed to skip the requested
+ // number of bytes.
+ if (byte_range_.first_byte_position() != 0) {
+ int64_t skipped, bytes_to_skip = byte_range_.first_byte_position();
+ do {
+ skipped = Java_InputStream_skip(env, stream_.obj(), bytes_to_skip);
+ if (ClearException(env)) {
+ NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+ net::ERR_FAILED));
+ return false;
+ }
+ if (skipped <= 0) {
+ NotifyDone(
+ net::URLRequestStatus(net::URLRequestStatus::FAILED,
+ net::ERR_REQUEST_RANGE_NOT_SATISFIABLE));
+ return false;
+ }
+ } while ((bytes_to_skip -= skipped) > 0);
+ }
+ return true;
+}
+
+bool AndroidStreamReaderURLRequestJob::ReadRawData(net::IOBuffer* dest,
+ int dest_size,
+ int *bytes_read) {
+ DCHECK_NE(dest_size, 0);
+ DCHECK(bytes_read);
+ DCHECK(stream_.obj());
+
+ JNIEnv* env = AttachCurrentThread();
+ DCHECK(env);
+
+ if (!buffer_.obj()) {
+ // Allocate transfer buffer.
+ buffer_.Reset(env, env->NewByteArray(kBufferSize));
+ if (ClearException(env)) {
+ NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+ net::ERR_FAILED));
+ return false;
+ }
+ }
+
+ jbyteArray buffer = buffer_.obj();
+ *bytes_read = 0;
+ if (!dest_size)
+ return true;
+
+ // Read data in multiples of the buffer size.
+ while (dest_size > 0) {
+ int read_size = std::min(dest_size, kBufferSize);
+ // TODO(skyostil): Make this non-blocking
+ int32_t byte_count =
+ Java_InputStream_read(env, stream_.obj(), buffer, 0, read_size);
+ if (byte_count <= 0) {
+ // net::URLRequestJob will call NotifyDone for us after the end of the
+ // file is reached.
+ break;
+ }
+
+ if (ClearException(env)) {
+ NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+ net::ERR_FAILED));
+ return false;
+ }
+
+#ifndef NDEBUG
+ int32_t buffer_length = env->GetArrayLength(buffer);
+ DCHECK_GE(read_size, byte_count);
+ DCHECK_GE(buffer_length, byte_count);
+#endif // NDEBUG
+
+ // Copy the data over to the provided C++ side buffer.
+ DCHECK_GE(dest_size, byte_count);
+ env->GetByteArrayRegion(buffer, 0, byte_count,
+ reinterpret_cast<jbyte*>(dest->data() + *bytes_read));
+
+ if (ClearException(env)) {
+ NotifyDone(net::URLRequestStatus(net::URLRequestStatus::FAILED,
+ net::ERR_FAILED));
+ return false;
+ }
+
+ *bytes_read += byte_count;
+ dest_size -= byte_count;
+ }
+ return true;
+}
+
+bool AndroidStreamReaderURLRequestJob::GetMimeType(
+ std::string* mime_type) const {
+ JNIEnv* env = AttachCurrentThread();
+ DCHECK(env);
+
+ return delegate_->GetMimeType(env,
+ request(),
+ stream_.obj(),
+ mime_type);
+}
+
+bool AndroidStreamReaderURLRequestJob::GetCharset(
+ std::string* charset) {
+ JNIEnv* env = AttachCurrentThread();
+ DCHECK(env);
+
+ return delegate_->GetCharset(env,
+ request(),
+ stream_.obj(),
+ charset);
+}
+
+void AndroidStreamReaderURLRequestJob::SetExtraRequestHeaders(
+ const net::HttpRequestHeaders& headers) {
+ std::string range_header;
+ if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) {
+ // We only care about "Range" header here.
+ std::vector<net::HttpByteRange> ranges;
+ if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) {
+ if (ranges.size() == 1) {
+ byte_range_ = ranges[0];
+ } else {
+ // We don't support multiple range requests in one single URL request,
+ // because we need to do multipart encoding here.
+ NotifyDone(net::URLRequestStatus(
+ net::URLRequestStatus::FAILED,
+ net::ERR_REQUEST_RANGE_NOT_SATISFIABLE));
+ }
+ }
+ }
+}
diff --git a/android_webview/native/android_stream_reader_url_request_job.h b/android_webview/native/android_stream_reader_url_request_job.h
new file mode 100644
index 0000000..2e46572
--- /dev/null
+++ b/android_webview/native/android_stream_reader_url_request_job.h
@@ -0,0 +1,81 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ANDROID_WEBVIEW_NATIVE_ANDROID_STREAM_READER_URL_REQUEST_JOB_H_
+#define ANDROID_WEBVIEW_NATIVE_ANDROID_STREAM_READER_URL_REQUEST_JOB_H_
+
+#include "base/android/scoped_java_ref.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/threading/non_thread_safe.h"
+#include "net/http/http_byte_range.h"
+#include "net/url_request/url_request_job.h"
+
+namespace net {
+class URLRequest;
+}
+
+// A request job that reads data from a Java InputStream.
+class AndroidStreamReaderURLRequestJob : public net::URLRequestJob {
+ public:
+ /*
+ * We use a delegate so that we can share code for this job in slightly
+ * different contexts.
+ */
+ class Delegate {
+ public:
+ virtual base::android::ScopedJavaLocalRef<jobject> OpenInputStream(
+ JNIEnv* env,
+ net::URLRequest* request) = 0;
+
+ virtual bool GetMimeType(
+ JNIEnv* env,
+ net::URLRequest* request,
+ jobject stream,
+ std::string* mime_type) = 0;
+
+ virtual bool GetCharset(
+ JNIEnv* env,
+ net::URLRequest* request,
+ jobject stream,
+ std::string* charset) = 0;
+
+ virtual ~Delegate() {}
+ };
+
+ explicit AndroidStreamReaderURLRequestJob(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ scoped_ptr<Delegate> delegate);
+
+ // URLRequestJob:
+ virtual void Start() OVERRIDE;
+ virtual bool ReadRawData(net::IOBuffer* buf,
+ int buf_size,
+ int* bytes_read) OVERRIDE;
+ virtual void SetExtraRequestHeaders(
+ const net::HttpRequestHeaders& headers) OVERRIDE;
+ virtual bool GetMimeType(std::string* mime_type) const OVERRIDE;
+ virtual bool GetCharset(std::string* charset) OVERRIDE;
+
+ protected:
+ virtual ~AndroidStreamReaderURLRequestJob();
+
+ private:
+ // Verify the requested range against the stream size.
+ bool VerifyRequestedRange(JNIEnv* env);
+
+ // Skip to the first byte of the requested read range.
+ bool SkipToRequestedRange(JNIEnv* env);
+
+ net::HttpByteRange byte_range_;
+ scoped_ptr<Delegate> delegate_;
+ base::android::ScopedJavaGlobalRef<jobject> stream_;
+ base::android::ScopedJavaGlobalRef<jbyteArray> buffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(AndroidStreamReaderURLRequestJob);
+};
+
+bool RegisterAndroidStreamReaderUrlRequestJob(JNIEnv* env);
+
+#endif // ANDROID_WEBVIEW_NATIVE_ANDROID_STREAM_READER_URL_REQUEST_JOB_H_
diff --git a/android_webview/native/android_webview_jni_registrar.cc b/android_webview/native/android_webview_jni_registrar.cc
index ba497db..8e877e1 100644
--- a/android_webview/native/android_webview_jni_registrar.cc
+++ b/android_webview/native/android_webview_jni_registrar.cc
@@ -4,6 +4,8 @@
#include "android_webview/native/android_webview_jni_registrar.h"
+#include "android_webview/native/android_protocol_handler.h"
+#include "android_webview/native/android_stream_reader_url_request_job.h"
#include "android_webview/native/android_web_view_util.h"
#include "android_webview/native/aw_contents.h"
#include "android_webview/native/aw_contents_io_thread_client.h"
@@ -17,6 +19,9 @@
namespace android_webview {
static base::android::RegistrationMethod kWebViewRegisteredMethods[] = {
+ { "AndroidProtocolHandler", RegisterAndroidProtocolHandler },
+ { "AndroidStreamReaderUrlRequestJob",
+ RegisterAndroidStreamReaderUrlRequestJob },
{ "AndroidWebViewUtil", RegisterAndroidWebViewUtil },
{ "AwContents", RegisterAwContents },
{ "AwContentsIoThreadClient", RegisterAwContentsIoThreadClient},
diff --git a/android_webview/native/webview_native.gyp b/android_webview/native/webview_native.gyp
index 83a537f..57d0e89 100644
--- a/android_webview/native/webview_native.gyp
+++ b/android_webview/native/webview_native.gyp
@@ -20,6 +20,10 @@
'<(SHARED_INTERMEDIATE_DIR)/android_webview',
],
'sources': [
+ 'android_protocol_handler.cc',
+ 'android_protocol_handler.h',
+ 'android_stream_reader_url_request_job.cc',
+ 'android_stream_reader_url_request_job.h',
'android_web_view_util.cc',
'android_web_view_util.h',
'android_webview_jni_registrar.cc',
@@ -46,9 +50,20 @@
],
},
{
+ 'target_name': 'android_jar_jni_headers',
+ 'type': 'none',
+ 'variables': {
+ 'jni_gen_dir': 'android_webview',
+ 'input_java_class': 'java/io/InputStream.class',
+ 'input_jar_file': '<(android_sdk)/android.jar',
+ },
+ 'includes': [ '../../build/jar_file_jni_generator.gypi' ],
+ },
+ {
'target_name': 'android_webview_native_jni',
'type': 'none',
'sources': [
+ '../java/src/org/chromium/android_webview/AndroidProtocolHandler.java',
'../java/src/org/chromium/android_webview/AndroidWebViewUtil.java',
'../java/src/org/chromium/android_webview/AwContents.java',
'../java/src/org/chromium/android_webview/AwContentsIoThreadClient.java',
@@ -61,6 +76,9 @@
'jni_gen_dir': 'android_webview',
},
'includes': [ '../../build/jni_generator.gypi' ],
+ 'dependencies': [
+ 'android_jar_jni_headers',
+ ],
},
],
}