Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: jni/AndroidWebRequest.cpp

Issue 5697499218051072: Usage of new API, cleanups (reduced) (Closed)
Patch Set: Even more review issues fixed. Created April 28, 2014, 10:18 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « jni/AndroidWebRequest.h ('k') | jni/Application.mk » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * This file is part of Adblock Plus <http://adblockplus.org/>,
3 * Copyright (C) 2006-2014 Eyeo GmbH
4 *
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
7 * published by the Free Software Foundation.
8 *
9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
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/>.
16 */
17
18 #include <AdblockPlus.h>
19 #include "AndroidWebRequest.h"
20 #include "Utils.h"
21 #include "Debug.h"
22
23 namespace
24 {
25 std::string ExtractExceptionMessage(JNIEnv* env, jthrowable throwable)
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);
31 }
32
33 class JavaException : public std::exception
34 {
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;
75 }
76 }
77
78 AndroidWebRequest::AndroidWebRequest(JavaVM*& gJvm) : globalJvm(gJvm)
79 {
80 JNIEnv* jniEnv = NULL;
81 int stat = globalJvm->GetEnv((void **)&jniEnv, JNI_VERSION_1_6);
82 if (stat == JNI_EDETACHED)
83 {
84 if (globalJvm->AttachCurrentThread(&jniEnv, NULL) != 0)
85 throw std::runtime_error("Failed to get JNI environment");
86 }
87
88 jUrlClass = reinterpret_cast<jclass>(jniEnv->NewGlobalRef(jniEnv->FindClass("j ava/net/URL")));
89 jUrlConstructorID = jniEnv->GetMethodID(jUrlClass, "<init>", "(Ljava/lang/Stri ng;)V");
90 jUrlOpenConnectionID = jniEnv->GetMethodID(jUrlClass, "openConnection", "()Lja va/net/URLConnection;");
91 jConnectionClass = reinterpret_cast<jclass>(jniEnv->NewGlobalRef(jniEnv->FindC lass("java/net/HttpURLConnection")));
92 jConnectionSetMethodID = jniEnv->GetMethodID(jConnectionClass, "setRequestMeth od", "(Ljava/lang/String;)V");
93 jConnectionSetRequestPropertyID = jniEnv->GetMethodID(jConnectionClass, "setRe questProperty", "(Ljava/lang/String;Ljava/lang/String;)V");
94 jConnectionConnectID = jniEnv->GetMethodID(jConnectionClass, "connect", "()V") ;
95 jConnectionGetContentLengthID = jniEnv->GetMethodID(jConnectionClass, "getCont entLength", "()I");
96 jConnectionGetResponseCodeID = jniEnv->GetMethodID(jConnectionClass, "getRespo nseCode", "()I");
97 jConnectionGetContentEncodingID = jniEnv->GetMethodID(jConnectionClass, "getCo ntentEncoding", "()Ljava/lang/String;");
98 jConnectionGetInputStreamID = jniEnv->GetMethodID(jConnectionClass, "getInputS tream", "()Ljava/io/InputStream;");
99 jInputStreamReaderClass = reinterpret_cast<jclass>(jniEnv->NewGlobalRef(jniEnv ->FindClass("java/io/InputStreamReader")));
100 jInputStreamReaderConstructorID = jniEnv->GetMethodID(jInputStreamReaderClass, "<init>", "(Ljava/io/InputStream;Ljava/lang/String;)V");
101 jBufferedReaderClass = reinterpret_cast<jclass>(jniEnv->NewGlobalRef(jniEnv->F indClass("java/io/BufferedReader")));
102 jBufferedReaderConstructorID = jniEnv->GetMethodID(jBufferedReaderClass, "<ini t>", "(Ljava/io/Reader;)V");
103 jStringBuilderClass = reinterpret_cast<jclass>(jniEnv->NewGlobalRef(jniEnv->Fi ndClass("java/lang/StringBuilder")));
104 jStringBuilderConstructorID = jniEnv->GetMethodID(jStringBuilderClass, "<init> ", "()V");
105 jBufferedReaderReadID = jniEnv->GetMethodID(jBufferedReaderClass, "read", "([C II)I");
106 jStringBuilderAppendID = jniEnv->GetMethodID(jStringBuilderClass, "append", "( [CII)Ljava/lang/StringBuilder;");
107 jStringBuilderToStringID = jniEnv->GetMethodID(jStringBuilderClass, "toString" , "()Ljava/lang/String;");
108 jBufferedReaderCloseID = jniEnv->GetMethodID(jBufferedReaderClass, "close", "( )V");
109 jConnectionGetHeaderFieldKeyID = jniEnv->GetMethodID(jConnectionClass, "getHea derField", "(I)Ljava/lang/String;");
110 jConnectionGetHeaderFieldID = jniEnv->GetMethodID(jConnectionClass, "getHeader FieldKey", "(I)Ljava/lang/String;");
111
112 if (stat == JNI_EDETACHED)
113 globalJvm->DetachCurrentThread();
114 }
115
116 AndroidWebRequest::~AndroidWebRequest()
117 {
118 JNIEnv* jniEnv = NULL;
119 int stat = globalJvm->GetEnv((void **)&jniEnv, JNI_VERSION_1_6);
120 if (stat == JNI_EDETACHED)
121 {
122 if (globalJvm->AttachCurrentThread(&jniEnv, NULL) != 0)
123 throw std::runtime_error("Failed to get JNI environment");
124 }
125
126 jniEnv->DeleteGlobalRef(jUrlClass);
127 jniEnv->DeleteGlobalRef(jConnectionClass);
128 jniEnv->DeleteGlobalRef(jInputStreamReaderClass);
129 jniEnv->DeleteGlobalRef(jBufferedReaderClass);
130 jniEnv->DeleteGlobalRef(jStringBuilderClass);
131
132 if (stat == JNI_EDETACHED)
133 globalJvm->DetachCurrentThread();
134 }
135
136 AdblockPlus::ServerResponse AndroidWebRequest::GET(
137 const std::string& url, const AdblockPlus::HeaderList& requestHeaders) const
138 {
139 JNIEnv* jniEnv = NULL;
140 int stat = globalJvm->GetEnv((void **)&jniEnv, JNI_VERSION_1_6);
141 if (stat == JNI_EDETACHED)
142 {
143 if (globalJvm->AttachCurrentThread(&jniEnv, NULL) != 0)
144 throw std::runtime_error("Failed to get JNI environment");
145 }
146
147 AdblockPlus::ServerResponse result;
148 try
149 {
150 // URL jUrl = new URL(url)
151 jstring jUrlStr = jniEnv->NewStringUTF(url.c_str());
152
153 jobject jUrl = jniEnv->NewObject(jUrlClass, jUrlConstructorID, jUrlStr);
154 if (jniEnv->ExceptionCheck())
155 throw JavaException(jniEnv);
156 jniEnv->DeleteLocalRef(jUrlStr);
157
158 // HttpURLConnection connection = (HttpURLConnection) jUrl.openConnection();
159 jobject jConnection = jniEnv->CallObjectMethod(jUrl, jUrlOpenConnectionID);
160 if (jniEnv->ExceptionCheck())
161 throw JavaException(jniEnv);
162
163 // connection.setRequestMethod("GET");
164 jstring jMethod = jniEnv->NewStringUTF("GET");
165 jniEnv->CallVoidMethod(jConnection, jConnectionSetMethodID, jMethod);
166 if (jniEnv->ExceptionCheck())
167 throw JavaException(jniEnv);
168 jniEnv->DeleteLocalRef(jMethod);
169
170 for (int i = 0; i < requestHeaders.size(); i++)
171 {
172 // connection.setRequestProperty(requestHeaders[i].first, requestHeaders[i ].second);
173 jstring jHeader = jniEnv->NewStringUTF(requestHeaders[i].first.c_str());
174 jstring jValue = jniEnv->NewStringUTF(requestHeaders[i].second.c_str());
175 jniEnv->CallVoidMethod(jConnection, jConnectionSetRequestPropertyID, jHead er, jValue);
176 if (jniEnv->ExceptionCheck())
177 throw JavaException(jniEnv);
178 jniEnv->DeleteLocalRef(jHeader);
179 jniEnv->DeleteLocalRef(jValue);
180 }
181
182 // connection.connect();
183 jniEnv->CallVoidMethod(jConnection, jConnectionConnectID);
184 if (jniEnv->ExceptionCheck())
185 throw JavaException(jniEnv);
186
187 // int lenghtOfFile = connection.getContentLength();
188 jint lenghtOfFile = jniEnv->CallIntMethod(jConnection, jConnectionGetContent LengthID);
189 if (jniEnv->ExceptionCheck())
190 throw JavaException(jniEnv);
191
192 D(D_WARN, "Size: %d", lenghtOfFile);
193
194 // result.responseStatus = connection.getResponseCode();
195 result.responseStatus = jniEnv->CallIntMethod(jConnection, jConnectionGetRes ponseCodeID);
196 if (jniEnv->ExceptionCheck())
197 throw JavaException(jniEnv);
198
199 /* Read response data */
200
201 // String jEncoding = connection.getContentEncoding();
202 jstring jEncoding = (jstring) jniEnv->CallObjectMethod(jConnection, jConnect ionGetContentEncodingID);
203 if (jniEnv->ExceptionCheck())
204 throw JavaException(jniEnv);
205
206 if (jEncoding == NULL)
207 jEncoding = jniEnv->NewStringUTF("utf-8");
208
209 // InputStream jis = connection.getInputStream();
210 jobject jis = jniEnv->CallObjectMethod(jConnection, jConnectionGetInputStrea mID);
211 if (jniEnv->ExceptionCheck())
212 throw JavaException(jniEnv);
213
214 // InputStreamReader jisr = new InputStreamReader(jis, jEncoding);
215 jobject jisr = jniEnv->NewObject(jInputStreamReaderClass, jInputStreamReader ConstructorID, jis, jEncoding);
216 if (jniEnv->ExceptionCheck())
217 throw JavaException(jniEnv);
218
219 jniEnv->DeleteLocalRef(jEncoding);
220
221 // BufferedReader jin = new BufferedReader(jisr);
222 jobject jin = jniEnv->NewObject(jBufferedReaderClass, jBufferedReaderConstru ctorID, jisr);
223 if (jniEnv->ExceptionCheck())
224 throw JavaException(jniEnv);
225
226 // char[] jBuffer = new char[0x10000];
227 jcharArray jBuffer = jniEnv->NewCharArray(0x10000);
228
229 // StringBuilder jout = new StringBuilder();
230 jobject jout = jniEnv->NewObject(jStringBuilderClass, jStringBuilderConstruc torID);
231 if (jniEnv->ExceptionCheck())
232 throw JavaException(jniEnv);
233
234 jlong total = 0;
235 jint read;
236
237 jint jBufferLength = (jint) jniEnv->GetArrayLength(jBuffer);
238
239 do
240 {
241 // read = jin.read(buffer, 0, buffer.length);
242 read = jniEnv->CallIntMethod(jin, jBufferedReaderReadID, jBuffer, 0, jBuff erLength);
243 if (jniEnv->ExceptionCheck())
244 throw JavaException(jniEnv);
245
246 if (read > 0)
247 {
248 // jout.append(buffer, 0, read);
249 jniEnv->CallObjectMethod(jout, jStringBuilderAppendID, jBuffer, 0, jBuff erLength);
250 if (jniEnv->ExceptionCheck())
251 throw JavaException(jniEnv);
252
253 total += read;
254 }
255 }
256 while (read >= 0);
257
258 // String jData = out.toString();
259 jstring jData = (jstring) jniEnv->CallObjectMethod(jout, jStringBuilderToStr ingID);
260 if (jniEnv->ExceptionCheck())
261 throw JavaException(jniEnv);
262
263 result.responseText = GetString(jniEnv, jData);
264
265 // jin.close();
266 jniEnv->CallVoidMethod(jin, jBufferedReaderCloseID);
267 if (jniEnv->ExceptionCheck())
268 throw JavaException(jniEnv);
269
270 jint i = 0;
271 while (true)
272 {
273 // String jHeaderName = connection.getHeaderFieldKey(i)
274 jstring jHeaderName = (jstring) jniEnv->CallObjectMethod(jConnection, jCon nectionGetHeaderFieldKeyID, i);
275 if (jniEnv->ExceptionCheck())
276 throw JavaException(jniEnv);
277
278 // String jHeaderValue = connection.getHeaderField(i)
279 jstring jHeaderValue = (jstring) jniEnv->CallObjectMethod(jConnection, jCo nnectionGetHeaderFieldID, i);
280 if (jniEnv->ExceptionCheck())
281 throw JavaException(jniEnv);
282
283 if (!jHeaderValue)
284 break;
285
286 std::string headerName = GetString(jniEnv, jHeaderName);
287 std::string headerValue = GetString(jniEnv, jHeaderValue);
288
289 headerName = TrimString(headerName);
290 headerValue = TrimString(headerValue);
291
292 std::transform(headerName.begin(), headerName.end(), headerName.begin(), : :tolower);
293
294 result.responseHeaders.push_back(std::pair<std::string, std::string>(heade rName, headerValue));
295
296 i++;
297 }
298 D(D_WARN, "Finished downloading");
299
300 result.status = NS_OK;
301 }
302 catch(JavaException& e)
303 {
304 result.responseStatus = 0;
305 result.status = ExceptionToStatus(e);
306 D(D_ERROR, "%s", e.what());
307 }
308 catch (const std::exception& e)
309 {
310 D(D_ERROR, "Exception: %s", e.what());
311 result.status = AdblockPlus::DefaultWebRequest::NS_ERROR_FAILURE;
312 }
313 catch (...)
314 {
315 D(D_ERROR, "Unknown exception");
316 result.status = AdblockPlus::DefaultWebRequest::NS_ERROR_FAILURE;
317 }
318
319 if (stat == JNI_EDETACHED)
320 globalJvm->DetachCurrentThread();
321
322 return result;
323 }
OLDNEW
« no previous file with comments | « jni/AndroidWebRequest.h ('k') | jni/Application.mk » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld