Set WebView proxy to 0.0.0.0 when possible (#2539)

* Set WebView proxy to 0.0.0.0 when possible

* add DcHttpResponse to wrapper

* use new DcHttpResponse to show images in email-html-view

* null-encoding is fine for WebResourceResponse()

---------

Co-authored-by: B. Petersen <r10s@b44t.com>
This commit is contained in:
link2xt 2023-04-20 19:30:19 +00:00 committed by GitHub
parent f130336c2f
commit 0e657eed56
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 146 additions and 0 deletions

View file

@ -1021,6 +1021,15 @@ JNIEXPORT jlong Java_com_b44t_messenger_DcContext_getProviderFromEmailWithDnsCPt
}
JNIEXPORT jlong Java_com_b44t_messenger_DcContext_getHttpResponseCPtr(JNIEnv *env, jobject obj, jstring url)
{
CHAR_REF(url);
jlong ret = (jlong)dc_get_http_response(get_dc_context(env, obj), urlPtr);
CHAR_UNREF(url);
return ret;
}
/*******************************************************************************
* DcEventEmitter
******************************************************************************/
@ -2068,3 +2077,63 @@ JNIEXPORT jstring Java_com_b44t_messenger_DcProvider_getOverviewPage(JNIEnv *env
return ret;
}
/*******************************************************************************
* DcHttpResponse
******************************************************************************/
static dc_http_response_t* get_dc_http_response(JNIEnv *env, jobject obj)
{
static jfieldID fid = 0;
if (fid==0) {
jclass cls = (*env)->GetObjectClass(env, obj);
fid = (*env)->GetFieldID(env, cls, "httpResponseCPtr", "J" /*Signature, J=long*/);
}
if (fid) {
return (dc_http_response_t*)(*env)->GetLongField(env, obj, fid);
}
return NULL;
}
JNIEXPORT void Java_com_b44t_messenger_DcHttpResponse_unrefHttpResponseCPtr(JNIEnv *env, jobject obj)
{
dc_http_response_unref(get_dc_http_response(env, obj));
}
JNIEXPORT jstring Java_com_b44t_messenger_DcHttpResponse_getMimetype(JNIEnv *env, jobject obj)
{
char* temp = dc_http_response_get_mimetype(get_dc_http_response(env, obj));
jstring ret = NULL;
if (temp) {
ret = JSTRING_NEW(temp);
}
dc_str_unref(temp);
return ret;
}
JNIEXPORT jstring Java_com_b44t_messenger_DcHttpResponse_getEncoding(JNIEnv *env, jobject obj)
{
char* temp = dc_http_response_get_encoding(get_dc_http_response(env, obj));
jstring ret = NULL;
if (temp) {
ret = JSTRING_NEW(temp);
}
dc_str_unref(temp);
return ret;
}
JNIEXPORT jbyteArray Java_com_b44t_messenger_DcHttpResponse_getBlob(JNIEnv *env, jobject obj)
{
jbyteArray ret = NULL;
dc_http_response_t* http_response = get_dc_http_response(env, obj);
size_t ptr_size = dc_http_response_get_size(http_response);
uint8_t* ptr = dc_http_response_get_blob(http_response);
ret = ptr2jbyteArray(env, ptr, ptr_size);
dc_str_unref((char*)ptr);
return ret;
}

View file

@ -216,6 +216,7 @@ public class DcContext {
public DcArray getLocations (int chat_id, int contact_id, long timestamp_start, long timestamp_end) { return new DcArray(getLocationsCPtr(chat_id, contact_id, timestamp_start, timestamp_end)); }
public native void deleteAllLocations ();
public DcProvider getProviderFromEmailWithDns (String email) { long cptr = getProviderFromEmailWithDnsCPtr(email); return cptr!=0 ? new DcProvider(cptr) : null; }
public DcHttpResponse getHttpResponse (String url) { long cptr = getHttpResponseCPtr(url); return cptr!=0 ? new DcHttpResponse(cptr) : null; }
public String getNameNAddr() {
String displayname = getConfig("displayname");
@ -255,4 +256,5 @@ public class DcContext {
private native long checkQrCPtr (String qr);
private native long getProviderFromEmailWithDnsCPtr (String addr);
private native long newBackupProviderCPtr();
private native long getHttpResponseCPtr(String url);
}

View file

@ -0,0 +1,22 @@
package com.b44t.messenger;
public class DcHttpResponse {
public DcHttpResponse(long httpResponseCPtr) {
this.httpResponseCPtr = httpResponseCPtr;
}
@Override protected void finalize() throws Throwable {
super.finalize();
unrefHttpResponseCPtr();
httpResponseCPtr = 0;
}
public native String getMimetype ();
public native String getEncoding ();
public native byte[] getBlob ();
// working with raw c-data
private long httpResponseCPtr; // CAVE: the name is referenced in the JNI
private native void unrefHttpResponseCPtr();
}

View file

@ -3,17 +3,20 @@ package org.thoughtcrime.securesms;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings;
import androidx.appcompat.app.AlertDialog;
import com.b44t.messenger.DcContext;
import com.b44t.messenger.DcHttpResponse;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.Prefs;
import org.thoughtcrime.securesms.util.Util;
import java.io.ByteArrayInputStream;
import java.lang.ref.WeakReference;
public class FullMsgActivity extends WebViewActivity
@ -164,4 +167,27 @@ public class FullMsgActivity extends WebViewActivity
webView.getSettings().setBlockNetworkLoads(!this.loadRemoteContent);
webView.reload();
}
@Override
protected WebResourceResponse interceptRequest(String url) {
WebResourceResponse res = null;
try {
if (url == null) {
throw new Exception("no url specified");
}
DcHttpResponse httpResponse = dcContext.getHttpResponse(url);
if (httpResponse == null) {
throw new Exception(dcContext.getLastError());
}
String mimeType = httpResponse.getMimetype();
if (mimeType == null) {
mimeType = "application/octet-stream";
}
res = new WebResourceResponse(mimeType, httpResponse.getEncoding(), new ByteArrayInputStream(httpResponse.getBlob()));
} catch (Exception e) {
e.printStackTrace();
res = new WebResourceResponse("text/plain", "UTF-8", new ByteArrayInputStream(("Error: " + e.getMessage()).getBytes()));
}
return res;
}
}

View file

@ -21,10 +21,14 @@ import androidx.annotation.RequiresApi;
import androidx.appcompat.widget.SearchView;
import androidx.webkit.WebSettingsCompat;
import androidx.webkit.WebViewFeature;
import androidx.webkit.ProxyController;
import androidx.webkit.ProxyConfig;
import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.DynamicTheme;
import java.util.concurrent.Executor;
public class WebViewActivity extends PassphraseRequiredActionBarActivity
implements SearchView.OnQueryTextListener,
WebView.FindListener
@ -39,6 +43,29 @@ public class WebViewActivity extends PassphraseRequiredActionBarActivity
protected void onPreCreate() {
dynamicTheme.onCreate(this);
dynamicLanguage.onCreate(this);
if (WebViewFeature.isFeatureSupported(WebViewFeature.PROXY_OVERRIDE)) {
// Set proxy to non-routable address.
ProxyConfig proxyConfig = new ProxyConfig.Builder()
.removeImplicitRules()
.addProxyRule("0.0.0.0")
.build();
Executor executor = new Executor() {
@Override
public void execute(Runnable command) {
command.run();
}
};
Runnable listener = new Runnable() {
@Override
public void run() {
Log.i(TAG, "Successfully set WebView proxy.");
}
};
ProxyController.getInstance().setProxyOverride(proxyConfig, executor, listener);
} else {
Log.w(TAG, "Cannot set WebView proxy.");
}
}
@Override