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