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(str, env->GetStringLength(jstr));
52     env->ReleaseStringCritical(jstr, str);
53     return str16;
54 }
55 
string16ToJstring(JNIEnv * env,String16 string)56 jstring string16ToJstring(JNIEnv* env, String16 string) {
57     const char16_t* str = string.string();
58     size_t len = string.size();
59 
60     return env->NewString(str, len);
61 }
62 
com_android_pacprocessor_PacNative_createV8ParserNativeLocked(JNIEnv * env,jobject)63 static jboolean com_android_pacprocessor_PacNative_createV8ParserNativeLocked(JNIEnv* env,
64         jobject) {
65     if (proxyResolver == NULL) {
66         logger = new ProxyErrorLogger();
67         proxyResolver = new net::ProxyResolverV8(net::ProxyResolverJSBindings::CreateDefault(),
68                 logger);
69         pacSet = false;
70         return JNI_FALSE;
71     }
72     return JNI_TRUE;
73 }
74 
com_android_pacprocessor_PacNative_destroyV8ParserNativeLocked(JNIEnv * env,jobject)75 static jboolean com_android_pacprocessor_PacNative_destroyV8ParserNativeLocked(JNIEnv* env,
76         jobject) {
77     if (proxyResolver != NULL) {
78         delete logger;
79         delete proxyResolver;
80         logger = NULL;
81         proxyResolver = NULL;
82         return JNI_FALSE;
83     }
84     return JNI_TRUE;
85 }
86 
com_android_pacprocessor_PacNative_setProxyScriptNativeLocked(JNIEnv * env,jobject,jstring script)87 static jboolean com_android_pacprocessor_PacNative_setProxyScriptNativeLocked(JNIEnv* env, jobject,
88         jstring script) {
89     String16 script16 = jstringToString16(env, script);
90 
91     if (proxyResolver == NULL) {
92         ALOGE("V8 Parser not started when setting PAC script");
93         return JNI_TRUE;
94     }
95 
96     if (proxyResolver->SetPacScript(script16) != OK) {
97         ALOGE("Unable to set PAC script");
98         return JNI_TRUE;
99     }
100     pacSet = true;
101 
102     return JNI_FALSE;
103 }
104 
com_android_pacprocessor_PacNative_makeProxyRequestNativeLocked(JNIEnv * env,jobject,jstring url,jstring host)105 static jstring com_android_pacprocessor_PacNative_makeProxyRequestNativeLocked(JNIEnv* env, jobject,
106         jstring url, jstring host) {
107     String16 url16 = jstringToString16(env, url);
108     String16 host16 = jstringToString16(env, host);
109     String16 ret;
110 
111     if (proxyResolver == NULL) {
112         ALOGE("V8 Parser not initialized when running PAC script");
113         return NULL;
114     }
115 
116     if (!pacSet) {
117         ALOGW("Attempting to run PAC with no script set");
118         return NULL;
119     }
120 
121     if (proxyResolver->GetProxyForURL(url16, host16, &ret) != OK) {
122         String8 ret8(ret);
123         ALOGE("Error Running PAC: %s", ret8.string());
124         return NULL;
125     }
126 
127     jstring jret = string16ToJstring(env, ret);
128 
129     return jret;
130 }
131 
132 static JNINativeMethod gMethods[] = {
133     { "createV8ParserNativeLocked", "()Z",
134         (void*)com_android_pacprocessor_PacNative_createV8ParserNativeLocked},
135     { "destroyV8ParserNativeLocked", "()Z",
136         (void*)com_android_pacprocessor_PacNative_destroyV8ParserNativeLocked},
137     { "setProxyScriptNativeLocked", "(Ljava/lang/String;)Z",
138         (void*)com_android_pacprocessor_PacNative_setProxyScriptNativeLocked},
139     { "makeProxyRequestNativeLocked", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;",
140         (void*)com_android_pacprocessor_PacNative_makeProxyRequestNativeLocked},
141 };
142 
register_com_android_pacprocessor_PacNative(JNIEnv * env)143 int register_com_android_pacprocessor_PacNative(JNIEnv* env) {
144     return jniRegisterNativeMethods(env, "com/android/pacprocessor/PacNative",
145             gMethods, NELEM(gMethods));
146 }
147 
148 } /* namespace android */
149