Convert K9WebViewClient to Kotlin

This commit is contained in:
cketti 2023-04-17 18:18:04 +02:00
parent 6a202800f3
commit 30efd5051f

View file

@ -1,142 +1,123 @@
package com.fsck.k9.view;
import java.io.InputStream;
import java.util.Collections;
import java.util.Map;
import android.content.ActivityNotFoundException;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.provider.Browser;
import android.text.TextUtils;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import com.fsck.k9.mailstore.AttachmentResolver;
import com.fsck.k9.ui.R;
import com.fsck.k9.view.MessageWebView.OnPageFinishedListener;
import timber.log.Timber;
package com.fsck.k9.view
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.provider.Browser
import android.webkit.WebResourceRequest
import android.webkit.WebResourceResponse
import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.Toast
import androidx.annotation.RequiresApi
import com.fsck.k9.logging.Timber
import com.fsck.k9.mailstore.AttachmentResolver
import com.fsck.k9.ui.R
import com.fsck.k9.view.MessageWebView.OnPageFinishedListener
/**
* {@link WebViewClient} that intercepts requests for {@code cid:} URIs to load the respective body part.
* [WebViewClient] that intercepts requests for `cid:` URIs to load the respective body part.
*/
public class K9WebViewClient extends WebViewClient {
private static final String CID_SCHEME = "cid";
private static final WebResourceResponse RESULT_DO_NOT_INTERCEPT = null;
private static final WebResourceResponse RESULT_DUMMY_RESPONSE = new WebResourceResponse(null, null, null);
private OnPageFinishedListener onPageFinishedListener;
internal class K9WebViewClient(
private val attachmentResolver: AttachmentResolver?,
) : WebViewClient() {
private var onPageFinishedListener: OnPageFinishedListener? = null
@Nullable
private final AttachmentResolver attachmentResolver;
public static K9WebViewClient newInstance(@Nullable AttachmentResolver attachmentResolver) {
return new K9WebViewClient(attachmentResolver);
@Deprecated("Deprecated in parent class")
override fun shouldOverrideUrlLoading(webView: WebView, url: String): Boolean {
return shouldOverrideUrlLoading(webView, Uri.parse(url))
}
private K9WebViewClient(@Nullable AttachmentResolver attachmentResolver) {
this.attachmentResolver = attachmentResolver;
}
@Override
public boolean shouldOverrideUrlLoading(WebView webView, String url) {
return shouldOverrideUrlLoading(webView, Uri.parse(url));
}
@Override
@RequiresApi(Build.VERSION_CODES.N)
public boolean shouldOverrideUrlLoading(WebView webView, WebResourceRequest request) {
return shouldOverrideUrlLoading(webView, request.getUrl());
override fun shouldOverrideUrlLoading(webView: WebView, request: WebResourceRequest): Boolean {
return shouldOverrideUrlLoading(webView, request.url)
}
private boolean shouldOverrideUrlLoading(WebView webView, Uri uri) {
if (CID_SCHEME.equals(uri.getScheme())) {
return false;
}
private fun shouldOverrideUrlLoading(webView: WebView, uri: Uri): Boolean {
if (uri.scheme == CID_SCHEME) return false
Context context = webView.getContext();
Intent intent = createBrowserViewIntent(uri, context);
val context = webView.context
val intent = createBrowserViewIntent(uri, context)
try {
context.startActivity(intent);
} catch (ActivityNotFoundException ex) {
Toast.makeText(context, R.string.error_activity_not_found, Toast.LENGTH_LONG).show();
context.startActivity(intent)
} catch (e: ActivityNotFoundException) {
Timber.d(e, "Couldn't open URL: %s", uri)
Toast.makeText(context, R.string.error_activity_not_found, Toast.LENGTH_LONG).show()
}
return true;
return true
}
private Intent createBrowserViewIntent(Uri uri, Context context) {
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.addCategory(Intent.CATEGORY_BROWSABLE);
intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
intent.putExtra(Browser.EXTRA_CREATE_NEW_TAB, true);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
return intent;
}
private fun createBrowserViewIntent(uri: Uri, context: Context): Intent {
return Intent(Intent.ACTION_VIEW, uri).apply {
putExtra(Browser.EXTRA_APPLICATION_ID, context.packageName)
putExtra(Browser.EXTRA_CREATE_NEW_TAB, true)
public WebResourceResponse shouldInterceptRequest(WebView webView, WebResourceRequest request) {
Uri uri = request.getUrl();
if (!CID_SCHEME.equals(uri.getScheme())) {
return RESULT_DO_NOT_INTERCEPT;
}
if (attachmentResolver == null) {
return RESULT_DUMMY_RESPONSE;
}
String cid = uri.getSchemeSpecificPart();
if (TextUtils.isEmpty(cid)) {
return RESULT_DUMMY_RESPONSE;
}
Uri attachmentUri = attachmentResolver.getAttachmentUriForContentId(cid);
if (attachmentUri == null) {
return RESULT_DUMMY_RESPONSE;
}
Context context = webView.getContext();
ContentResolver contentResolver = context.getContentResolver();
try {
String mimeType = contentResolver.getType(attachmentUri);
InputStream inputStream = contentResolver.openInputStream(attachmentUri);
WebResourceResponse webResourceResponse = new WebResourceResponse(mimeType, null, inputStream);
addCacheControlHeader(webResourceResponse);
return webResourceResponse;
} catch (Exception e) {
Timber.e(e, "Error while intercepting URI: %s", uri);
return RESULT_DUMMY_RESPONSE;
addCategory(Intent.CATEGORY_BROWSABLE)
addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
}
}
private void addCacheControlHeader(WebResourceResponse response) {
Map<String, String> headers = Collections.singletonMap("Cache-Control", "no-store");
response.setResponseHeaders(headers);
override fun shouldInterceptRequest(webView: WebView, request: WebResourceRequest): WebResourceResponse? {
val uri = request.url
return if (uri.scheme == CID_SCHEME) {
handleCidUri(uri, webView)
} else {
RESULT_DO_NOT_INTERCEPT
}
}
public void setOnPageFinishedListener(OnPageFinishedListener onPageFinishedListener) {
this.onPageFinishedListener = onPageFinishedListener;
private fun handleCidUri(uri: Uri, webView: WebView): WebResourceResponse {
val attachmentUri = getAttachmentUriFromCidUri(uri) ?: return RESULT_DUMMY_RESPONSE
val context = webView.context
val contentResolver = context.contentResolver
@Suppress("TooGenericExceptionCaught")
return try {
val mimeType = contentResolver.getType(attachmentUri)
val inputStream = contentResolver.openInputStream(attachmentUri)
WebResourceResponse(mimeType, null, inputStream).apply {
addCacheControlHeader()
}
} catch (e: Exception) {
Timber.e(e, "Error while intercepting URI: %s", uri)
RESULT_DUMMY_RESPONSE
}
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
if (onPageFinishedListener != null) {
onPageFinishedListener.onPageFinished();
private fun getAttachmentUriFromCidUri(uri: Uri): Uri? {
return uri.schemeSpecificPart
?.let { cid -> attachmentResolver?.getAttachmentUriForContentId(cid) }
}
private fun WebResourceResponse.addCacheControlHeader() {
responseHeaders = mapOf("Cache-Control" to "no-store")
}
fun setOnPageFinishedListener(onPageFinishedListener: OnPageFinishedListener?) {
this.onPageFinishedListener = onPageFinishedListener
}
override fun onPageFinished(view: WebView, url: String) {
super.onPageFinished(view, url)
onPageFinishedListener?.onPageFinished()
}
companion object {
private const val CID_SCHEME = "cid"
private val RESULT_DO_NOT_INTERCEPT: WebResourceResponse? = null
private val RESULT_DUMMY_RESPONSE = WebResourceResponse(null, null, null)
fun newInstance(attachmentResolver: AttachmentResolver?): K9WebViewClient {
return K9WebViewClient(attachmentResolver)
}
}
}