1ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott/* 2ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott * Copyright 2010, The Android Open Source Project 3ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott * 4ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott * Redistribution and use in source and binary forms, with or without 5ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott * modification, are permitted provided that the following conditions 6ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott * are met: 7ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott * * Redistributions of source code must retain the above copyright 8ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott * notice, this list of conditions and the following disclaimer. 9ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott * * Redistributions in binary form must reproduce the above copyright 10ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott * notice, this list of conditions and the following disclaimer in the 11ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott * documentation and/or other materials provided with the distribution. 12ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott * 13ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 14ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 17ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott */ 25ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott 26ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott#define LOG_TAG "UrlInterceptResponse" 27ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott#include "config.h" 28ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott 29ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott#include "JNIUtility.h" 30ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott#include "UrlInterceptResponse.h" 31ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott#include "WebCoreJni.h" 32ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott 3302e159d45d6ecf733b834c350ef2035cd979a200Steve Block#include <ScopedLocalRef.h> 34ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott#include <utils/Log.h> 35ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott 36ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scottnamespace android { 37ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott 38ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scottclass JavaInputStreamWrapper { 39ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scottpublic: 40ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott JavaInputStreamWrapper(JNIEnv* env, jobject inputStream) 41ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott : m_inputStream(env->NewGlobalRef(inputStream)) 4202e159d45d6ecf733b834c350ef2035cd979a200Steve Block , m_buffer(NULL) { 4302e159d45d6ecf733b834c350ef2035cd979a200Steve Block LOG_ALWAYS_FATAL_IF(!m_inputStream); 4402e159d45d6ecf733b834c350ef2035cd979a200Steve Block ScopedLocalRef<jclass> inputStreamClass(env, env->FindClass("java/io/InputStream")); 4502e159d45d6ecf733b834c350ef2035cd979a200Steve Block LOG_ALWAYS_FATAL_IF(!inputStreamClass.get()); 4602e159d45d6ecf733b834c350ef2035cd979a200Steve Block m_read = env->GetMethodID(inputStreamClass.get(), "read", "([B)I"); 47ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott LOG_ALWAYS_FATAL_IF(!m_read); 4802e159d45d6ecf733b834c350ef2035cd979a200Steve Block m_close = env->GetMethodID(inputStreamClass.get(), "close", "()V"); 49ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott LOG_ALWAYS_FATAL_IF(!m_close); 50ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott } 51ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott 52ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott ~JavaInputStreamWrapper() { 53ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott JNIEnv* env = JSC::Bindings::getJNIEnv(); 54ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott env->CallVoidMethod(m_inputStream, m_close); 55ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott checkException(env); 56ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott env->DeleteGlobalRef(m_inputStream); 57ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott // In case we never call read(). 58ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott if (m_buffer) 59ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott env->DeleteGlobalRef(m_buffer); 60ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott } 61ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott 62ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott void read(std::vector<char>* out) { 63ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott JNIEnv* env = JSC::Bindings::getJNIEnv(); 64ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott // Initialize our read buffer to the capacity of out. 65ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott if (!m_buffer) { 6602e159d45d6ecf733b834c350ef2035cd979a200Steve Block ScopedLocalRef<jbyteArray> buffer_local(env, env->NewByteArray(out->capacity())); 6702e159d45d6ecf733b834c350ef2035cd979a200Steve Block m_buffer = static_cast<jbyteArray>(env->NewGlobalRef(buffer_local.get())); 68ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott } 6902e159d45d6ecf733b834c350ef2035cd979a200Steve Block int size = env->CallIntMethod(m_inputStream, m_read, m_buffer); 70ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott if (checkException(env) || size < 0) 71ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott return; 72ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott // Copy from m_buffer to out. 73ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott out->resize(size); 74ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott env->GetByteArrayRegion(m_buffer, 0, size, (jbyte*)&out->front()); 75ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott } 76ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott 77ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scottprivate: 78ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott jobject m_inputStream; 79ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott jbyteArray m_buffer; 80ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott jmethodID m_read; 81ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott jmethodID m_close; 82ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott}; 83ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott 84ff1576a1bd6302d6c9988912d17e47f325242574Patrick ScottUrlInterceptResponse::UrlInterceptResponse(JNIEnv* env, jobject response) { 8502e159d45d6ecf733b834c350ef2035cd979a200Steve Block ScopedLocalRef<jclass> javaResponse(env, env->FindClass("android/webkit/WebResourceResponse")); 8602e159d45d6ecf733b834c350ef2035cd979a200Steve Block LOG_ALWAYS_FATAL_IF(!javaResponse.get()); 8702e159d45d6ecf733b834c350ef2035cd979a200Steve Block jfieldID mimeType = env->GetFieldID(javaResponse.get(), "mMimeType", "Ljava/lang/String;"); 88ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott LOG_ALWAYS_FATAL_IF(!mimeType); 8902e159d45d6ecf733b834c350ef2035cd979a200Steve Block jfieldID encoding = env->GetFieldID(javaResponse.get(), "mEncoding", "Ljava/lang/String;"); 90ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott LOG_ALWAYS_FATAL_IF(!encoding); 9102e159d45d6ecf733b834c350ef2035cd979a200Steve Block jfieldID inputStream = env->GetFieldID(javaResponse.get(), "mInputStream", "Ljava/io/InputStream;"); 92ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott LOG_ALWAYS_FATAL_IF(!inputStream); 93ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott 9402e159d45d6ecf733b834c350ef2035cd979a200Steve Block ScopedLocalRef<jobject> stream(env, env->GetObjectField(response, inputStream)); 9502e159d45d6ecf733b834c350ef2035cd979a200Steve Block if (stream.get()) 9602e159d45d6ecf733b834c350ef2035cd979a200Steve Block m_inputStream.set(new JavaInputStreamWrapper(env, stream.get())); 97ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott 9802e159d45d6ecf733b834c350ef2035cd979a200Steve Block ScopedLocalRef<jstring> mimeStr(env, static_cast<jstring>(env->GetObjectField(response, mimeType))); 9902e159d45d6ecf733b834c350ef2035cd979a200Steve Block ScopedLocalRef<jstring> encodingStr(env, static_cast<jstring>(env->GetObjectField(response, encoding))); 100ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott 10102e159d45d6ecf733b834c350ef2035cd979a200Steve Block if (mimeStr.get()) { 10202e159d45d6ecf733b834c350ef2035cd979a200Steve Block const char* s = env->GetStringUTFChars(mimeStr.get(), NULL); 10302e159d45d6ecf733b834c350ef2035cd979a200Steve Block m_mimeType.assign(s, env->GetStringUTFLength(mimeStr.get())); 10402e159d45d6ecf733b834c350ef2035cd979a200Steve Block env->ReleaseStringUTFChars(mimeStr.get(), s); 105c171aa015a0cbeab69fa359835f7c82f269d6111Patrick Scott } 10602e159d45d6ecf733b834c350ef2035cd979a200Steve Block if (encodingStr.get()) { 10702e159d45d6ecf733b834c350ef2035cd979a200Steve Block const char* s = env->GetStringUTFChars(encodingStr.get(), NULL); 10802e159d45d6ecf733b834c350ef2035cd979a200Steve Block m_encoding.assign(s, env->GetStringUTFLength(encodingStr.get())); 10902e159d45d6ecf733b834c350ef2035cd979a200Steve Block env->ReleaseStringUTFChars(encodingStr.get(), s); 110c171aa015a0cbeab69fa359835f7c82f269d6111Patrick Scott } 111ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott} 112ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott 113ff1576a1bd6302d6c9988912d17e47f325242574Patrick ScottUrlInterceptResponse::~UrlInterceptResponse() { 114ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott // Cannot be inlined because of JavaInputStreamWrapper visibility. 115ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott} 116ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott 117ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scottbool UrlInterceptResponse::readStream(std::vector<char>* out) const { 118ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott if (!m_inputStream) 119ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott return false; 120ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott m_inputStream->read(out); 121ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott return true; 122ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott} 123ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott 124ff1576a1bd6302d6c9988912d17e47f325242574Patrick Scott} // namespace android 125