From 30efd5051fe11146b0bbcfcb5766c908615eb37f Mon Sep 17 00:00:00 2001 From: cketti Date: Mon, 17 Apr 2023 18:18:04 +0200 Subject: [PATCH] Convert `K9WebViewClient` to Kotlin --- .../java/com/fsck/k9/view/K9WebViewClient.kt | 209 ++++++++---------- 1 file changed, 95 insertions(+), 114 deletions(-) diff --git a/app/ui/legacy/src/main/java/com/fsck/k9/view/K9WebViewClient.kt b/app/ui/legacy/src/main/java/com/fsck/k9/view/K9WebViewClient.kt index 29ef07e44..7a19f2090 100644 --- a/app/ui/legacy/src/main/java/com/fsck/k9/view/K9WebViewClient.kt +++ b/app/ui/legacy/src/main/java/com/fsck/k9/view/K9WebViewClient.kt @@ -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 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) } } }