This source file includes following definitions.
- RegisterInputStream
- FromInputStream
- BytesAvailable
- Skip
- Read
#include "android_webview/native/input_stream_impl.h"
#include "base/android/jni_android.h"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#include "jni/InputStream_jni.h"
#pragma GCC diagnostic pop
#include "net/base/io_buffer.h"
using base::android::AttachCurrentThread;
using base::android::ClearException;
using base::android::JavaRef;
using JNI_InputStream::Java_InputStream_available;
using JNI_InputStream::Java_InputStream_close;
using JNI_InputStream::Java_InputStream_skip;
using JNI_InputStream::Java_InputStream_readI_AB_I_I;
namespace android_webview {
bool RegisterInputStream(JNIEnv* env) {
return JNI_InputStream::RegisterNativesImpl(env);
}
const int InputStreamImpl::kBufferSize = 4096;
const InputStreamImpl* InputStreamImpl::FromInputStream(
const InputStream* input_stream) {
return static_cast<const InputStreamImpl*>(input_stream);
}
InputStreamImpl::InputStreamImpl() {
}
InputStreamImpl::InputStreamImpl(const JavaRef<jobject>& stream)
: jobject_(stream) {
DCHECK(!stream.is_null());
}
InputStreamImpl::~InputStreamImpl() {
JNIEnv* env = AttachCurrentThread();
Java_InputStream_close(env, jobject_.obj());
}
bool InputStreamImpl::BytesAvailable(int* bytes_available) const {
JNIEnv* env = AttachCurrentThread();
int bytes = Java_InputStream_available(env, jobject_.obj());
if (ClearException(env))
return false;
*bytes_available = bytes;
return true;
}
bool InputStreamImpl::Skip(int64_t n, int64_t* bytes_skipped) {
JNIEnv* env = AttachCurrentThread();
int bytes = Java_InputStream_skip(env, jobject_.obj(), n);
if (ClearException(env))
return false;
if (bytes > n)
return false;
*bytes_skipped = bytes;
return true;
}
bool InputStreamImpl::Read(net::IOBuffer* dest, int length, int* bytes_read) {
JNIEnv* env = AttachCurrentThread();
if (!buffer_.obj()) {
base::android::ScopedJavaLocalRef<jbyteArray> temp(
env, env->NewByteArray(kBufferSize));
buffer_.Reset(temp);
if (ClearException(env))
return false;
}
int remaining_length = length;
char* dest_write_ptr = dest->data();
jbyteArray buffer = buffer_.obj();
*bytes_read = 0;
while (remaining_length > 0) {
const int max_transfer_length = std::min(remaining_length, kBufferSize);
const int transfer_length = Java_InputStream_readI_AB_I_I(
env, jobject_.obj(), buffer, 0, max_transfer_length);
if (ClearException(env))
return false;
if (transfer_length < 0)
break;
if (transfer_length == 0)
continue;
DCHECK_GE(max_transfer_length, transfer_length);
DCHECK_GE(env->GetArrayLength(buffer), transfer_length);
if (transfer_length > max_transfer_length)
return false;
DCHECK_GE(remaining_length, transfer_length);
env->GetByteArrayRegion(buffer, 0, transfer_length,
reinterpret_cast<jbyte*>(dest_write_ptr));
if (ClearException(env))
return false;
remaining_length -= transfer_length;
dest_write_ptr += transfer_length;
}
DCHECK(remaining_length >= 0 && remaining_length <= length);
*bytes_read = length - remaining_length;
return true;
}
}