blob: 77e3c3292784f002deb5491d6dd8fd586dbf9be7 [file] [log] [blame]
/*
* Copyright 2010, The Android Open Source Project
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#define LOG_TAG "UrlInterceptResponse"
#include "config.h"
#include "JNIUtility.h"
#include "UrlInterceptResponse.h"
#include "WebCoreJni.h"
#include <utils/Log.h>
namespace android {
class JavaInputStreamWrapper {
public:
JavaInputStreamWrapper(JNIEnv* env, jobject inputStream)
: m_inputStream(env->NewGlobalRef(inputStream))
, m_buffer(0) {
LOG_ALWAYS_FATAL_IF(!inputStream);
jclass inputStreamClass = env->FindClass("java/io/InputStream");
LOG_ALWAYS_FATAL_IF(!inputStreamClass);
m_read = env->GetMethodID(inputStreamClass, "read", "([B)I");
LOG_ALWAYS_FATAL_IF(!m_read);
m_close = env->GetMethodID(inputStreamClass, "close", "()V");
LOG_ALWAYS_FATAL_IF(!m_close);
env->DeleteLocalRef(inputStreamClass);
}
~JavaInputStreamWrapper() {
JNIEnv* env = JSC::Bindings::getJNIEnv();
env->CallVoidMethod(m_inputStream, m_close);
checkException(env);
env->DeleteGlobalRef(m_inputStream);
// In case we never call read().
if (m_buffer)
env->DeleteGlobalRef(m_buffer);
}
void read(std::vector<char>* out) {
JNIEnv* env = JSC::Bindings::getJNIEnv();
// Initialize our read buffer to the capacity of out.
if (!m_buffer) {
m_buffer = env->NewByteArray(out->capacity());
m_buffer = (jbyteArray) env->NewGlobalRef(m_buffer);
}
int size = (int) env->CallIntMethod(m_inputStream, m_read, m_buffer);
if (checkException(env) || size < 0)
return;
// Copy from m_buffer to out.
out->resize(size);
env->GetByteArrayRegion(m_buffer, 0, size, (jbyte*)&out->front());
}
private:
jobject m_inputStream;
jbyteArray m_buffer;
jmethodID m_read;
jmethodID m_close;
};
UrlInterceptResponse::UrlInterceptResponse(JNIEnv* env, jobject response) {
jclass javaResponse = env->FindClass("android/webkit/WebResourceResponse");
LOG_ALWAYS_FATAL_IF(!javaResponse);
jfieldID mimeType = env->GetFieldID(javaResponse, "mMimeType",
"Ljava/lang/String;");
LOG_ALWAYS_FATAL_IF(!mimeType);
jfieldID encoding = env->GetFieldID(javaResponse, "mEncoding",
"Ljava/lang/String;");
LOG_ALWAYS_FATAL_IF(!encoding);
jfieldID inputStream = env->GetFieldID(javaResponse, "mInputStream",
"Ljava/io/InputStream;");
LOG_ALWAYS_FATAL_IF(!inputStream);
jobject stream = env->GetObjectField(response, inputStream);
if (stream)
m_inputStream.set(new JavaInputStreamWrapper(env, stream));
jstring mimeStr = (jstring) env->GetObjectField(response, mimeType);
jstring encodingStr = (jstring) env->GetObjectField(response, encoding);
if (mimeStr) {
const char* s = env->GetStringUTFChars(mimeStr, NULL);
m_mimeType.assign(s, env->GetStringUTFLength(mimeStr));
env->ReleaseStringUTFChars(mimeStr, s);
}
if (encodingStr) {
const char* s = env->GetStringUTFChars(encodingStr, NULL);
m_encoding.assign(s, env->GetStringUTFLength(encodingStr));
env->ReleaseStringUTFChars(encodingStr, s);
}
env->DeleteLocalRef(javaResponse);
env->DeleteLocalRef(stream);
env->DeleteLocalRef(mimeStr);
env->DeleteLocalRef(encodingStr);
}
UrlInterceptResponse::~UrlInterceptResponse() {
// Cannot be inlined because of JavaInputStreamWrapper visibility.
}
bool UrlInterceptResponse::readStream(std::vector<char>* out) const {
if (!m_inputStream)
return false;
m_inputStream->read(out);
return true;
}
} // namespace android