OLD | NEW |
1 /* | 1 /* |
2 * This file is part of Adblock Plus <http://adblockplus.org/>, | 2 * This file is part of Adblock Plus <http://adblockplus.org/>, |
3 * Copyright (C) 2006-2013 Eyeo GmbH | 3 * Copyright (C) 2006-2013 Eyeo GmbH |
4 * | 4 * |
5 * Adblock Plus is free software: you can redistribute it and/or modify | 5 * Adblock Plus is free software: you can redistribute it and/or modify |
6 * it under the terms of the GNU General Public License version 3 as | 6 * it under the terms of the GNU General Public License version 3 as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
8 * | 8 * |
9 * Adblock Plus is distributed in the hope that it will be useful, | 9 * Adblock Plus is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 * GNU General Public License for more details. | 12 * GNU General Public License for more details. |
13 * | 13 * |
14 * You should have received a copy of the GNU General Public License | 14 * You should have received a copy of the GNU General Public License |
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. | 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
16 */ | 16 */ |
17 | 17 |
18 #include <AdblockPlus.h> | 18 #include <AdblockPlus.h> |
19 #include "AndroidWebRequest.h" | 19 #include "AndroidWebRequest.h" |
20 #include "Utils.h" | 20 #include "Utils.h" |
21 #include "debug.h" | 21 #include "debug.h" |
22 | 22 |
23 struct JavaException : public std::exception | 23 namespace |
24 { | 24 { |
25 jthrowable ex; | 25 std::string ExtractExceptionMessage(JNIEnv* env, jthrowable throwable) |
26 | |
27 JavaException(jthrowable e) : ex(e) | |
28 { | 26 { |
| 27 jclass throwableClass = env->FindClass("java/lang/Throwable"); |
| 28 jmethodID throwableToStringMethodId = env->GetMethodID(throwableClass, "toSt
ring", "()Ljava/lang/String;"); |
| 29 jstring javaMessage = static_cast<jstring>(env->CallObjectMethod(throwable,
throwableToStringMethodId)); |
| 30 return "Java exception: " + GetString(env, javaMessage); |
29 } | 31 } |
30 | 32 |
31 const char* what() const throw() | 33 class JavaException : public std::exception |
32 { | 34 { |
33 return "Java Exception"; | 35 public: |
| 36 JavaException(JNIEnv* env) |
| 37 : env(env), throwable(env->ExceptionOccurred()) |
| 38 { |
| 39 env->ExceptionClear(); |
| 40 message = ExtractExceptionMessage(env, throwable); |
| 41 } |
| 42 |
| 43 virtual ~JavaException() throw() |
| 44 { |
| 45 } |
| 46 |
| 47 const char* what() const throw() |
| 48 { |
| 49 return message.c_str(); |
| 50 } |
| 51 |
| 52 bool IsInstanceOf(const std::string& className) const |
| 53 { |
| 54 jclass clazz = env->FindClass(className.c_str()); |
| 55 if (!clazz) |
| 56 return false; |
| 57 bool isInstance = env->IsInstanceOf(throwable, clazz); |
| 58 env->DeleteLocalRef(clazz); |
| 59 return isInstance; |
| 60 } |
| 61 |
| 62 private: |
| 63 JNIEnv* env; |
| 64 jthrowable throwable; |
| 65 std::string message; |
| 66 }; |
| 67 |
| 68 int64_t ExceptionToStatus(const JavaException& exception) |
| 69 { |
| 70 if (exception.IsInstanceOf("java/net/MalformedURLException")) |
| 71 return AdblockPlus::WebRequest::NS_ERROR_MALFORMED_URI; |
| 72 if (exception.IsInstanceOf("java/net/SocketTimeoutException")) |
| 73 return AdblockPlus::WebRequest::NS_ERROR_NET_TIMEOUT; |
| 74 return AdblockPlus::WebRequest::NS_ERROR_FAILURE; |
34 } | 75 } |
35 }; | 76 } |
36 | 77 |
37 AndroidWebRequest::AndroidWebRequest(JavaVM*& gJvm) : globalJvm(gJvm) | 78 AndroidWebRequest::AndroidWebRequest(JavaVM*& gJvm) : globalJvm(gJvm) |
38 { | 79 { |
39 JNIEnv* jniEnv = NULL; | 80 JNIEnv* jniEnv = NULL; |
40 int stat = globalJvm->GetEnv((void **)&jniEnv, JNI_VERSION_1_6); | 81 int stat = globalJvm->GetEnv((void **)&jniEnv, JNI_VERSION_1_6); |
41 if (stat == JNI_EDETACHED) | 82 if (stat == JNI_EDETACHED) |
42 { | 83 { |
43 if (globalJvm->AttachCurrentThread(&jniEnv, NULL) != 0) | 84 if (globalJvm->AttachCurrentThread(&jniEnv, NULL) != 0) |
44 throw std::runtime_error("Failed to get JNI environment"); | 85 throw std::runtime_error("Failed to get JNI environment"); |
45 } | 86 } |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 { | 138 { |
98 JNIEnv* jniEnv = NULL; | 139 JNIEnv* jniEnv = NULL; |
99 int stat = globalJvm->GetEnv((void **)&jniEnv, JNI_VERSION_1_6); | 140 int stat = globalJvm->GetEnv((void **)&jniEnv, JNI_VERSION_1_6); |
100 if (stat == JNI_EDETACHED) | 141 if (stat == JNI_EDETACHED) |
101 { | 142 { |
102 if (globalJvm->AttachCurrentThread(&jniEnv, NULL) != 0) | 143 if (globalJvm->AttachCurrentThread(&jniEnv, NULL) != 0) |
103 throw std::runtime_error("Failed to get JNI environment"); | 144 throw std::runtime_error("Failed to get JNI environment"); |
104 } | 145 } |
105 | 146 |
106 AdblockPlus::ServerResponse result; | 147 AdblockPlus::ServerResponse result; |
107 result.status = NS_ERROR_FAILURE; | |
108 result.responseStatus = 0; | |
109 | |
110 try | 148 try |
111 { | 149 { |
112 // URL jUrl = new URL(url) | 150 // URL jUrl = new URL(url) |
113 jstring jUrlStr = jniEnv->NewStringUTF(url.c_str()); | 151 jstring jUrlStr = jniEnv->NewStringUTF(url.c_str()); |
114 | 152 |
115 jobject jUrl = jniEnv->NewObject(jUrlClass, jUrlConstructorID, jUrlStr); | 153 jobject jUrl = jniEnv->NewObject(jUrlClass, jUrlConstructorID, jUrlStr); |
116 if (jniEnv->ExceptionCheck()) | 154 if (jniEnv->ExceptionCheck()) |
117 throw JavaException(jniEnv->ExceptionOccurred()); | 155 throw JavaException(jniEnv); |
118 jniEnv->DeleteLocalRef(jUrlStr); | 156 jniEnv->DeleteLocalRef(jUrlStr); |
119 | 157 |
120 // HttpURLConnection connection = (HttpURLConnection) jUrl.openConnection(); | 158 // HttpURLConnection connection = (HttpURLConnection) jUrl.openConnection(); |
121 jobject jConnection = jniEnv->CallObjectMethod(jUrl, jUrlOpenConnectionID); | 159 jobject jConnection = jniEnv->CallObjectMethod(jUrl, jUrlOpenConnectionID); |
122 if (jniEnv->ExceptionCheck()) | 160 if (jniEnv->ExceptionCheck()) |
123 throw JavaException(jniEnv->ExceptionOccurred()); | 161 throw JavaException(jniEnv); |
124 | 162 |
125 // connection.setRequestMethod("GET"); | 163 // connection.setRequestMethod("GET"); |
126 jstring jMethod = jniEnv->NewStringUTF("GET"); | 164 jstring jMethod = jniEnv->NewStringUTF("GET"); |
127 jniEnv->CallVoidMethod(jConnection, jConnectionSetMethodID, jMethod); | 165 jniEnv->CallVoidMethod(jConnection, jConnectionSetMethodID, jMethod); |
128 if (jniEnv->ExceptionCheck()) | 166 if (jniEnv->ExceptionCheck()) |
129 throw JavaException(jniEnv->ExceptionOccurred()); | 167 throw JavaException(jniEnv); |
130 jniEnv->DeleteLocalRef(jMethod); | 168 jniEnv->DeleteLocalRef(jMethod); |
131 | 169 |
132 for (int i = 0; i < requestHeaders.size(); i++) | 170 for (int i = 0; i < requestHeaders.size(); i++) |
133 { | 171 { |
134 // connection.setRequestProperty(requestHeaders[i].first, requestHeaders[i
].second); | 172 // connection.setRequestProperty(requestHeaders[i].first, requestHeaders[i
].second); |
135 jstring jHeader = jniEnv->NewStringUTF(requestHeaders[i].first.c_str()); | 173 jstring jHeader = jniEnv->NewStringUTF(requestHeaders[i].first.c_str()); |
136 jstring jValue = jniEnv->NewStringUTF(requestHeaders[i].second.c_str()); | 174 jstring jValue = jniEnv->NewStringUTF(requestHeaders[i].second.c_str()); |
137 jniEnv->CallVoidMethod(jConnection, jConnectionSetRequestPropertyID, jHead
er, jValue); | 175 jniEnv->CallVoidMethod(jConnection, jConnectionSetRequestPropertyID, jHead
er, jValue); |
138 if (jniEnv->ExceptionCheck()) | 176 if (jniEnv->ExceptionCheck()) |
139 throw JavaException(jniEnv->ExceptionOccurred()); | 177 throw JavaException(jniEnv); |
140 jniEnv->DeleteLocalRef(jHeader); | 178 jniEnv->DeleteLocalRef(jHeader); |
141 jniEnv->DeleteLocalRef(jValue); | 179 jniEnv->DeleteLocalRef(jValue); |
142 } | 180 } |
143 | 181 |
144 // connection.connect(); | 182 // connection.connect(); |
145 jniEnv->CallVoidMethod(jConnection, jConnectionConnectID); | 183 jniEnv->CallVoidMethod(jConnection, jConnectionConnectID); |
146 if (jniEnv->ExceptionCheck()) | 184 if (jniEnv->ExceptionCheck()) |
147 throw JavaException(jniEnv->ExceptionOccurred()); | 185 throw JavaException(jniEnv); |
148 | 186 |
149 // int lenghtOfFile = connection.getContentLength(); | 187 // int lenghtOfFile = connection.getContentLength(); |
150 jint lenghtOfFile = jniEnv->CallIntMethod(jConnection, jConnectionGetContent
LengthID); | 188 jint lenghtOfFile = jniEnv->CallIntMethod(jConnection, jConnectionGetContent
LengthID); |
151 if (jniEnv->ExceptionCheck()) | 189 if (jniEnv->ExceptionCheck()) |
152 throw JavaException(jniEnv->ExceptionOccurred()); | 190 throw JavaException(jniEnv); |
153 | 191 |
154 D(D_WARN, "Size: %d", lenghtOfFile); | 192 D(D_WARN, "Size: %d", lenghtOfFile); |
155 | 193 |
156 // result.responseStatus = connection.getResponseCode(); | 194 // result.responseStatus = connection.getResponseCode(); |
157 result.responseStatus = jniEnv->CallIntMethod(jConnection, jConnectionGetRes
ponseCodeID); | 195 result.responseStatus = jniEnv->CallIntMethod(jConnection, jConnectionGetRes
ponseCodeID); |
158 if (jniEnv->ExceptionCheck()) | 196 if (jniEnv->ExceptionCheck()) |
159 throw JavaException(jniEnv->ExceptionOccurred()); | 197 throw JavaException(jniEnv); |
160 | 198 |
161 /* Read response data */ | 199 /* Read response data */ |
162 | 200 |
163 // String jEncoding = connection.getContentEncoding(); | 201 // String jEncoding = connection.getContentEncoding(); |
164 jstring jEncoding = (jstring) jniEnv->CallObjectMethod(jConnection, jConnect
ionGetContentEncodingID); | 202 jstring jEncoding = (jstring) jniEnv->CallObjectMethod(jConnection, jConnect
ionGetContentEncodingID); |
165 if (jniEnv->ExceptionCheck()) | 203 if (jniEnv->ExceptionCheck()) |
166 throw JavaException(jniEnv->ExceptionOccurred()); | 204 throw JavaException(jniEnv); |
167 | 205 |
168 if (jEncoding == NULL) | 206 if (jEncoding == NULL) |
169 jEncoding = jniEnv->NewStringUTF("utf-8"); | 207 jEncoding = jniEnv->NewStringUTF("utf-8"); |
170 | 208 |
171 // InputStream jis = connection.getInputStream(); | 209 // InputStream jis = connection.getInputStream(); |
172 jobject jis = jniEnv->CallObjectMethod(jConnection, jConnectionGetInputStrea
mID); | 210 jobject jis = jniEnv->CallObjectMethod(jConnection, jConnectionGetInputStrea
mID); |
173 if (jniEnv->ExceptionCheck()) | 211 if (jniEnv->ExceptionCheck()) |
174 throw JavaException(jniEnv->ExceptionOccurred()); | 212 throw JavaException(jniEnv); |
175 | 213 |
176 // InputStreamReader jisr = new InputStreamReader(jis, jEncoding); | 214 // InputStreamReader jisr = new InputStreamReader(jis, jEncoding); |
177 jobject jisr = jniEnv->NewObject(jInputStreamReaderClass, jInputStreamReader
ConstructorID, jis, jEncoding); | 215 jobject jisr = jniEnv->NewObject(jInputStreamReaderClass, jInputStreamReader
ConstructorID, jis, jEncoding); |
178 if (jniEnv->ExceptionCheck()) | 216 if (jniEnv->ExceptionCheck()) |
179 throw JavaException(jniEnv->ExceptionOccurred()); | 217 throw JavaException(jniEnv); |
180 | 218 |
181 jniEnv->DeleteLocalRef(jEncoding); | 219 jniEnv->DeleteLocalRef(jEncoding); |
182 | 220 |
183 // BufferedReader jin = new BufferedReader(jisr); | 221 // BufferedReader jin = new BufferedReader(jisr); |
184 jobject jin = jniEnv->NewObject(jBufferedReaderClass, jBufferedReaderConstru
ctorID, jisr); | 222 jobject jin = jniEnv->NewObject(jBufferedReaderClass, jBufferedReaderConstru
ctorID, jisr); |
185 if (jniEnv->ExceptionCheck()) | 223 if (jniEnv->ExceptionCheck()) |
186 throw JavaException(jniEnv->ExceptionOccurred()); | 224 throw JavaException(jniEnv); |
187 | 225 |
188 // char[] jBuffer = new char[0x10000]; | 226 // char[] jBuffer = new char[0x10000]; |
189 jcharArray jBuffer = jniEnv->NewCharArray(0x10000); | 227 jcharArray jBuffer = jniEnv->NewCharArray(0x10000); |
190 | 228 |
191 // StringBuilder jout = new StringBuilder(); | 229 // StringBuilder jout = new StringBuilder(); |
192 jobject jout = jniEnv->NewObject(jStringBuilderClass, jStringBuilderConstruc
torID); | 230 jobject jout = jniEnv->NewObject(jStringBuilderClass, jStringBuilderConstruc
torID); |
193 if (jniEnv->ExceptionCheck()) | 231 if (jniEnv->ExceptionCheck()) |
194 throw JavaException(jniEnv->ExceptionOccurred()); | 232 throw JavaException(jniEnv); |
195 | 233 |
196 jlong total = 0; | 234 jlong total = 0; |
197 jint read; | 235 jint read; |
198 | 236 |
199 jint jBufferLength = (jint) jniEnv->GetArrayLength(jBuffer); | 237 jint jBufferLength = (jint) jniEnv->GetArrayLength(jBuffer); |
200 | 238 |
201 do | 239 do |
202 { | 240 { |
203 // read = jin.read(buffer, 0, buffer.length); | 241 // read = jin.read(buffer, 0, buffer.length); |
204 read = jniEnv->CallIntMethod(jin, jBufferedReaderReadID, jBuffer, 0, jBuff
erLength); | 242 read = jniEnv->CallIntMethod(jin, jBufferedReaderReadID, jBuffer, 0, jBuff
erLength); |
205 if (jniEnv->ExceptionCheck()) | 243 if (jniEnv->ExceptionCheck()) |
206 throw JavaException(jniEnv->ExceptionOccurred()); | 244 throw JavaException(jniEnv); |
207 | 245 |
208 if (read > 0) | 246 if (read > 0) |
209 { | 247 { |
210 // jout.append(buffer, 0, read); | 248 // jout.append(buffer, 0, read); |
211 jniEnv->CallObjectMethod(jout, jStringBuilderAppendID, jBuffer, 0, jBuff
erLength); | 249 jniEnv->CallObjectMethod(jout, jStringBuilderAppendID, jBuffer, 0, jBuff
erLength); |
212 if (jniEnv->ExceptionCheck()) | 250 if (jniEnv->ExceptionCheck()) |
213 throw JavaException(jniEnv->ExceptionOccurred()); | 251 throw JavaException(jniEnv); |
214 | 252 |
215 total += read; | 253 total += read; |
216 } | 254 } |
217 } | 255 } |
218 while (read >= 0); | 256 while (read >= 0); |
219 | 257 |
220 // String jData = out.toString(); | 258 // String jData = out.toString(); |
221 jstring jData = (jstring) jniEnv->CallObjectMethod(jout, jStringBuilderToStr
ingID); | 259 jstring jData = (jstring) jniEnv->CallObjectMethod(jout, jStringBuilderToStr
ingID); |
222 if (jniEnv->ExceptionCheck()) | 260 if (jniEnv->ExceptionCheck()) |
223 throw JavaException(jniEnv->ExceptionOccurred()); | 261 throw JavaException(jniEnv); |
224 | 262 |
225 result.responseText = GetString(jniEnv, jData); | 263 result.responseText = GetString(jniEnv, jData); |
226 | 264 |
227 // jin.close(); | 265 // jin.close(); |
228 jniEnv->CallVoidMethod(jin, jBufferedReaderCloseID); | 266 jniEnv->CallVoidMethod(jin, jBufferedReaderCloseID); |
229 if (jniEnv->ExceptionCheck()) | 267 if (jniEnv->ExceptionCheck()) |
230 throw JavaException(jniEnv->ExceptionOccurred()); | 268 throw JavaException(jniEnv); |
231 | 269 |
232 jint i = 0; | 270 jint i = 0; |
233 while (true) | 271 while (true) |
234 { | 272 { |
235 // String jHeaderName = connection.getHeaderFieldKey(i) | 273 // String jHeaderName = connection.getHeaderFieldKey(i) |
236 jstring jHeaderName = (jstring) jniEnv->CallObjectMethod(jConnection, jCon
nectionGetHeaderFieldKeyID, i); | 274 jstring jHeaderName = (jstring) jniEnv->CallObjectMethod(jConnection, jCon
nectionGetHeaderFieldKeyID, i); |
237 if (jniEnv->ExceptionCheck()) | 275 if (jniEnv->ExceptionCheck()) |
238 throw JavaException(jniEnv->ExceptionOccurred()); | 276 throw JavaException(jniEnv); |
239 | 277 |
240 // String jHeaderValue = connection.getHeaderField(i) | 278 // String jHeaderValue = connection.getHeaderField(i) |
241 jstring jHeaderValue = (jstring) jniEnv->CallObjectMethod(jConnection, jCo
nnectionGetHeaderFieldID, i); | 279 jstring jHeaderValue = (jstring) jniEnv->CallObjectMethod(jConnection, jCo
nnectionGetHeaderFieldID, i); |
242 if (jniEnv->ExceptionCheck()) | 280 if (jniEnv->ExceptionCheck()) |
243 throw JavaException(jniEnv->ExceptionOccurred()); | 281 throw JavaException(jniEnv); |
244 | 282 |
245 if (!jHeaderValue) | 283 if (!jHeaderValue) |
246 break; | 284 break; |
247 | 285 |
248 std::string headerName = GetString(jniEnv, jHeaderName); | 286 std::string headerName = GetString(jniEnv, jHeaderName); |
249 std::string headerValue = GetString(jniEnv, jHeaderValue); | 287 std::string headerValue = GetString(jniEnv, jHeaderValue); |
250 | 288 |
251 headerName = TrimString(headerName); | 289 headerName = TrimString(headerName); |
252 headerValue = TrimString(headerValue); | 290 headerValue = TrimString(headerValue); |
253 | 291 |
254 std::transform(headerName.begin(), headerName.end(), headerName.begin(), :
:tolower); | 292 std::transform(headerName.begin(), headerName.end(), headerName.begin(), :
:tolower); |
255 | 293 |
256 result.responseHeaders.push_back(std::pair<std::string, std::string>(heade
rName, headerValue)); | 294 result.responseHeaders.push_back(std::pair<std::string, std::string>(heade
rName, headerValue)); |
257 | 295 |
258 i++; | 296 i++; |
259 } | 297 } |
260 D(D_WARN, "Finished downloading"); | 298 D(D_WARN, "Finished downloading"); |
261 | 299 |
262 result.status = AdblockPlus::DefaultWebRequest::NS_OK; | 300 result.status = NS_OK; |
263 } | 301 } |
264 catch(JavaException& e) | 302 catch(JavaException& e) |
265 { | 303 { |
266 jniEnv->ExceptionClear(); | 304 result.responseStatus = 0; |
267 jclass jThrowableClass = jniEnv->FindClass("java/lang/Throwable"); | 305 result.status = ExceptionToStatus(e); |
268 jmethodID jThrowableToStringID = jniEnv->GetMethodID(jThrowableClass, "toStr
ing", "()Ljava/lang/String;"); | 306 D(D_ERROR, "%s", e.what()); |
269 jstring jMsg = (jstring) jniEnv->CallObjectMethod(e.ex, jThrowableToStringID
); | |
270 const char* msg = jniEnv->GetStringUTFChars(jMsg, 0); | |
271 D(D_ERROR, "Java Exception: %s", msg); | |
272 jniEnv->ReleaseStringUTFChars(jMsg, msg); | |
273 jniEnv->DeleteLocalRef(jMsg); | |
274 result.status = AdblockPlus::DefaultWebRequest::NS_ERROR_FAILURE; | |
275 } | 307 } |
276 catch (const std::exception& e) | 308 catch (const std::exception& e) |
277 { | 309 { |
278 D(D_ERROR, "Exception: %s", e.what()); | 310 D(D_ERROR, "Exception: %s", e.what()); |
279 result.status = AdblockPlus::DefaultWebRequest::NS_ERROR_FAILURE; | 311 result.status = AdblockPlus::DefaultWebRequest::NS_ERROR_FAILURE; |
280 } | 312 } |
281 catch (...) | 313 catch (...) |
282 { | 314 { |
283 D(D_ERROR, "Unknown exception"); | 315 D(D_ERROR, "Unknown exception"); |
284 result.status = AdblockPlus::DefaultWebRequest::NS_ERROR_FAILURE; | 316 result.status = AdblockPlus::DefaultWebRequest::NS_ERROR_FAILURE; |
285 } | 317 } |
286 | 318 |
287 if (stat == JNI_EDETACHED) | 319 if (stat == JNI_EDETACHED) |
288 globalJvm->DetachCurrentThread(); | 320 globalJvm->DetachCurrentThread(); |
289 | 321 |
290 return result; | 322 return result; |
291 } | 323 } |
OLD | NEW |