WebView: implement file:///android_asset/... URIs

This commit is contained in:
Julian Winkler
2024-10-03 22:42:12 +02:00
parent dc4b40bdf4
commit 633f1e6f96
4 changed files with 40 additions and 0 deletions

View File

@@ -161,6 +161,9 @@ void set_up_handle_cache(JNIEnv *env)
handle_cache.intent.class = _REF((*env)->FindClass(env, "android/content/Intent"));
handle_cache.intent.putExtraCharSequence = _METHOD(handle_cache.intent.class, "putExtra", "(Ljava/lang/String;Ljava/lang/CharSequence;)Landroid/content/Intent;");
handle_cache.webview.class = _REF((*env)->FindClass(env, "android/webkit/WebView"));
handle_cache.webview.internalGetAssetManager = _METHOD(handle_cache.webview.class, "internalGetAssetManager", "()Landroid/content/res/AssetManager;");
}
void extract_from_apk(const char *path, const char *target) {

View File

@@ -111,6 +111,10 @@ struct handle_cache {
jclass class;
jmethodID putExtraCharSequence;
} intent;
struct {
jclass class;
jmethodID internalGetAssetManager;
} webview;
};
extern struct handle_cache handle_cache;

View File

@@ -1,5 +1,8 @@
#include <gtk/gtk.h>
#include <webkit/webkit.h>
#include <gio/gunixinputstream.h>
#include <androidfw/androidfw_c_api.h>
#include "../defines.h"
#include "../util.h"
@@ -9,6 +12,27 @@
#include "../generated_headers/android_view_View.h"
#include "../generated_headers/android_webkit_WebView.h"
static void asset_uri_scheme_request_cb(WebKitURISchemeRequest *request, gpointer user_data)
{
const gchar *path = webkit_uri_scheme_request_get_path(request);
if (path == NULL)
return;
path += 1; // remove the leading '/'
JNIEnv *env = get_jni_env();
WrapperWidget *wrapper = WRAPPER_WIDGET(gtk_widget_get_parent(GTK_WIDGET(webkit_uri_scheme_request_get_web_view(request))));
jobject asset_manager_obj = (*env)->CallObjectMethod(env, wrapper->jobj, handle_cache.webview.internalGetAssetManager);
struct AssetManager *asset_manager = _PTR(_GET_LONG_FIELD(asset_manager_obj, "mObject"));
struct Asset *asset = AssetManager_openNonAsset(asset_manager, path, ACCESS_STREAMING);
off_t offset;
off_t size;
int fd = Asset_openFileDescriptor(asset, &offset, &size);
Asset_delete(asset);
GInputStream *stream = g_unix_input_stream_new(fd, TRUE);
g_input_stream_skip(stream, offset, NULL, NULL);
webkit_uri_scheme_request_finish(request, stream, size, NULL);
g_object_unref(stream);
}
JNIEXPORT jlong JNICALL Java_android_webkit_WebView_native_1constructor(JNIEnv *env, jobject this, jobject context, jobject attrs)
{
/*
@@ -23,6 +47,7 @@ JNIEXPORT jlong JNICALL Java_android_webkit_WebView_native_1constructor(JNIEnv *
GtkWidget *webview = webkit_web_view_new();
wrapper_widget_set_child(WRAPPER_WIDGET(wrapper), webview);
wrapper_widget_set_jobject(WRAPPER_WIDGET(wrapper), env, this);
webkit_web_context_register_uri_scheme(webkit_web_view_get_context(WEBKIT_WEB_VIEW(webview)), "android-asset", asset_uri_scheme_request_cb, NULL, NULL);
return _INTPTR(webview);
}

View File

@@ -1,6 +1,7 @@
package android.webkit;
import android.content.Context;
import android.content.res.AssetManager;
import android.util.AttributeSet;
import android.view.View;
@@ -47,6 +48,8 @@ public class WebView extends View {
public void destroy() {}
public void loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl) {
// webkit doesn't allow overwriting the file:// uri scheme. So we replace it with the android-asset:// scheme
data = data.replace("file:///android_asset/", "android-asset:///assets/");
native_loadDataWithBaseURL(widget, baseUrl, data, mimeType, encoding);
}
@@ -60,6 +63,11 @@ public class WebView extends View {
public void stopLoading() {}
// to be used by native code
AssetManager internalGetAssetManager() {
return getContext().getResources().getAssets();
}
@Override
protected native long native_constructor(Context context, AttributeSet attrs);
private native void native_loadDataWithBaseURL(long widget, String baseUrl, String data, String mimeType, String encoding);