1 /*
2  * Copyright (C) 2013 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "PacProcessor"
18 
19 #include <utils/Log.h>
20 #include <utils/Mutex.h>
21 #include "android_runtime/AndroidRuntime.h"
22 
23 #include "jni.h"
24 #include "JNIHelp.h"
25 
26 #include "proxy_resolver_v8.h"
27 
28 namespace android {
29 
30 class ProxyErrorLogger : public net::ProxyErrorListener {
31 public:
~ProxyErrorLogger()32     ~ProxyErrorLogger() {
33 
34     }
AlertMessage(String16 message)35     void AlertMessage(String16 message) {
36         String8 str(message);
37         ALOGD("Alert: %s", str.string());
38     }
ErrorMessage(String16 message)39     void ErrorMessage(String16 message) {
40         String8 str(message);
41         ALOGE("Error: %s", str.string());
42     }
43 };
44 
45 net::ProxyResolverV8* proxyResolver = NULL;
46 ProxyErrorLogger* logger = NULL;
47 bool pacSet = false;
48 
jstringToString16(JNIEnv * env,jstring jstr)49 String16 jstringToString16(JNIEnv* env, jstring jstr) {
50     const jchar* str = env->GetStringCritical(jstr, 0);
51     String16 str16(reinterpret_cast<const char16_t*>(str),
52                    env->GetStringLength(jstr));
53     env->ReleaseStringCritical(jstr, str);
54     return str16;
55 }
56 
string16ToJstring(JNIEnv * env,String16 string)57 jstring string16ToJstring(JNIEnv* env, String16 string) {
58     const char16_t* str = string.string();
59     size_t len = string.size();
60 
61     return env->NewString(reinterpret_cast<const jchar*>(str), len);
62 }
63 
com_android_pacprocessor_PacNative_createV8ParserNativeLocked(JNIEnv *,jobject)64 static jboolean com_android_pacprocessor_PacNative_createV8ParserNativeLocked(JNIEnv* /* env */,
65         jobject) {
66     if (proxyResolver == NULL) {
67         logger = new ProxyErrorLogger();
68         proxyResolver = new net::ProxyResolverV8(net::ProxyResolverJSBindings::CreateDefault(),
69                 logger);
70         pacSet = false;
71         return JNI_FALSE;
72     }
73     return JNI_TRUE;
74 }
75 
com_android_pacprocessor_PacNative_destroyV8ParserNativeLocked(JNIEnv *,jobject)76 static jboolean com_android_pacprocessor_PacNative_destroyV8ParserNativeLocked(JNIEnv* /* env */,
77         jobject) {
78     if (proxyResolver != NULL) {
79         delete logger;
80         delete proxyResolver;
81         logger = NULL;
82         proxyResolver = NULL;
83         return JNI_FALSE;
84     }
85     return JNI_TRUE;
86 }
87 
com_android_pacprocessor_PacNative_setProxyScriptNativeLocked(JNIEnv * env,jobject,jstring script)88 static jboolean com_android_pacprocessor_PacNative_setProxyScriptNativeLocked(JNIEnv* env, jobject,
89         jstring script) {
90     String16 script16 = jstringToString16(env, script);
91 
92     if (proxyResolver == NULL) {
93         ALOGE("V8 Parser not started when setting PAC script");
94         return JNI_TRUE;
95     }
96 
97     if (proxyResolver->SetPacScript(script16) != OK) {
98         ALOGE("Unable to set PAC script");
99         return JNI_TRUE;
100     }
101     pacSet = true;
102 
103     return JNI_FALSE;
104 }
105 
com_android_pacprocessor_PacNative_makeProxyRequestNativeLocked(JNIEnv * env,jobject,jstring url,jstring host)106 static jstring com_android_pacprocessor_PacNative_makeProxyRequestNativeLocked(JNIEnv* env, jobject,
107         jstring url, jstring host) {
108     String16 url16 = jstringToString16(env, url);
109     String16 host16 = jstringToString16(env, host);
110     String16 ret;
111 
112     if (proxyResolver == NULL) {
113         ALOGE("V8 Parser not initialized when running PAC script");
114         return NULL;
115     }
116 
117     if (!pacSet) {
118         ALOGW("Attempting to run PAC with no script set");
119         return NULL;
120     }
121 
122     if (proxyResolver->GetProxyForURL(url16, host16, &ret) != OK) {
123         String8 ret8(ret);
124         ALOGE("Error Running PAC: %s", ret8.string());
125         return NULL;
126     }
127 
128     jstring jret = string16ToJstring(env, ret);
129 
130     return jret;
131 }
132 
133 static JNINativeMethod gMethods[] = {
134     { "createV8ParserNativeLocked", "()Z",
135         (void*)com_android_pacprocessor_PacNative_createV8ParserNativeLocked},
136     { "destroyV8ParserNativeLocked", "()Z",
137         (void*)com_android_pacprocessor_PacNative_destroyV8ParserNativeLocked},
138     { "setProxyScriptNativeLocked", "(Ljava/lang/String;)Z",
139         (void*)com_android_pacprocessor_PacNative_setProxyScriptNativeLocked},
140     { "makeProxyRequestNativeLocked", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
141         (void*)com_android_pacprocessor_PacNative_makeProxyRequestNativeLocked},
142 };
143 
register_com_android_pacprocessor_PacNative(JNIEnv * env)144 int register_com_android_pacprocessor_PacNative(JNIEnv* env) {
145     return jniRegisterNativeMethods(env, "com/android/pacprocessor/PacNative",
146             gMethods, NELEM(gMethods));
147 }
148 
149 } /* namespace android */
150