19ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk/*
29ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * Copyright (C) 2013 The Android Open Source Project
39ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk *
49ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * Licensed under the Apache License, Version 2.0 (the "License");
59ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * you may not use this file except in compliance with the License.
69ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * You may obtain a copy of the License at
79ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk *
89ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk *      http://www.apache.org/licenses/LICENSE-2.0
99ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk *
109ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * Unless required by applicable law or agreed to in writing, software
119ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * distributed under the License is distributed on an "AS IS" BASIS,
129ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * See the License for the specific language governing permissions and
149ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk * limitations under the License.
159ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk */
169ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
179ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk#define LOG_TAG "PacProcessor"
189ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
199ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk#include <utils/Log.h>
209ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk#include <utils/Mutex.h>
219ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk#include "android_runtime/AndroidRuntime.h"
229ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
239ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk#include "jni.h"
249ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk#include "JNIHelp.h"
259ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
269ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk#include "proxy_resolver_v8.h"
279ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
289ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monknamespace android {
299ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
309ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkclass ProxyErrorLogger : public net::ProxyErrorListener {
319ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkpublic:
329ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    ~ProxyErrorLogger() {
339ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
349ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    }
359ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    void AlertMessage(String16 message) {
369ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        String8 str(message);
379ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        ALOGD("Alert: %s", str.string());
389ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    }
399ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    void ErrorMessage(String16 message) {
409ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        String8 str(message);
419ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        ALOGE("Error: %s", str.string());
429ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    }
439ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk};
449ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
459ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monknet::ProxyResolverV8* proxyResolver = NULL;
469ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason MonkProxyErrorLogger* logger = NULL;
479ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkbool pacSet = false;
489ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
499ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason MonkString16 jstringToString16(JNIEnv* env, jstring jstr) {
509ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    const jchar* str = env->GetStringCritical(jstr, 0);
519ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    String16 str16(str, env->GetStringLength(jstr));
529ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    env->ReleaseStringCritical(jstr, str);
539ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    return str16;
549ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk}
559ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
569ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkjstring string16ToJstring(JNIEnv* env, String16 string) {
579ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    const char16_t* str = string.string();
589ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    size_t len = string.size();
599ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
609ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    return env->NewString(str, len);
619ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk}
629ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
639ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkstatic jboolean com_android_pacprocessor_PacNative_createV8ParserNativeLocked(JNIEnv* env,
649ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        jobject) {
659ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    if (proxyResolver == NULL) {
669ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        logger = new ProxyErrorLogger();
679ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        proxyResolver = new net::ProxyResolverV8(net::ProxyResolverJSBindings::CreateDefault(),
689ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk                logger);
699ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        pacSet = false;
709ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        return JNI_FALSE;
719ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    }
729ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    return JNI_TRUE;
739ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk}
749ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
759ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkstatic jboolean com_android_pacprocessor_PacNative_destroyV8ParserNativeLocked(JNIEnv* env,
769ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        jobject) {
779ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    if (proxyResolver != NULL) {
789ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        delete logger;
799ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        delete proxyResolver;
809ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        logger = NULL;
819ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        proxyResolver = NULL;
829ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        return JNI_FALSE;
839ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    }
849ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    return JNI_TRUE;
859ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk}
869ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
879ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkstatic jboolean com_android_pacprocessor_PacNative_setProxyScriptNativeLocked(JNIEnv* env, jobject,
889ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        jstring script) {
899ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    String16 script16 = jstringToString16(env, script);
909ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
919ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    if (proxyResolver == NULL) {
929ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        ALOGE("V8 Parser not started when setting PAC script");
939ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        return JNI_TRUE;
949ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    }
959ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
969ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    if (proxyResolver->SetPacScript(script16) != OK) {
979ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        ALOGE("Unable to set PAC script");
989ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        return JNI_TRUE;
999ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    }
1009ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    pacSet = true;
1019ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
1029ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    return JNI_FALSE;
1039ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk}
1049ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
1059ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkstatic jstring com_android_pacprocessor_PacNative_makeProxyRequestNativeLocked(JNIEnv* env, jobject,
1069ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        jstring url, jstring host) {
1079ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    String16 url16 = jstringToString16(env, url);
1089ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    String16 host16 = jstringToString16(env, host);
1099ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    String16 ret;
1109ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
1119ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    if (proxyResolver == NULL) {
1129ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        ALOGE("V8 Parser not initialized when running PAC script");
1139ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        return NULL;
1149ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    }
1159ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
1169ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    if (!pacSet) {
1179ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        ALOGW("Attempting to run PAC with no script set");
1189ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        return NULL;
1199ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    }
1209ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
1219ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    if (proxyResolver->GetProxyForURL(url16, host16, &ret) != OK) {
1229ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        String8 ret8(ret);
1239ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        ALOGE("Error Running PAC: %s", ret8.string());
1249ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        return NULL;
1259ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    }
1269ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
1279ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    jstring jret = string16ToJstring(env, ret);
1289ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
1299ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    return jret;
1309ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk}
1319ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
1329ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkstatic JNINativeMethod gMethods[] = {
1339ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    { "createV8ParserNativeLocked", "()Z",
1349ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        (void*)com_android_pacprocessor_PacNative_createV8ParserNativeLocked},
1359ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    { "destroyV8ParserNativeLocked", "()Z",
1369ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        (void*)com_android_pacprocessor_PacNative_destroyV8ParserNativeLocked},
1379ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    { "setProxyScriptNativeLocked", "(Ljava/lang/String;)Z",
1389ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        (void*)com_android_pacprocessor_PacNative_setProxyScriptNativeLocked},
1399ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    { "makeProxyRequestNativeLocked", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
1409ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk        (void*)com_android_pacprocessor_PacNative_makeProxyRequestNativeLocked},
1419ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk};
1429ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
1439ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monkint register_com_android_pacprocessor_PacNative(JNIEnv* env) {
1449ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk    return jniRegisterNativeMethods(env, "com/android/pacprocessor/PacNative",
1459ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk            gMethods, NELEM(gMethods));
1469ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk}
1479ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk
1489ced3cd9d6ea414523051ec872fffc68f5fdbf08Jason Monk} /* namespace android */
149