From 14c7a63f45b503f3b06aae0b87c6c9a8c9a97f3a Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 16 Oct 2025 16:15:09 +0200 Subject: [PATCH] Extract code that log a ConsoleMessage so that it can be reused. --- .../features/call/impl/ui/CallScreenView.kt | 42 ++++--------- .../call/impl/ui/ElementCallActivity.kt | 5 ++ .../browser/ConsoleMessageLogger.kt | 61 +++++++++++++++++++ 3 files changed, 77 insertions(+), 31 deletions(-) create mode 100644 libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/browser/ConsoleMessageLogger.kt diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt index 88d2e81f8b..2f7a700794 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/CallScreenView.kt @@ -8,7 +8,6 @@ package io.element.android.features.call.impl.ui import android.annotation.SuppressLint -import android.util.Log import android.view.ViewGroup import android.webkit.ConsoleMessage import android.webkit.JavascriptInterface @@ -60,6 +59,7 @@ interface CallScreenNavigator { internal fun CallScreenView( state: CallScreenState, pipState: PictureInPictureState, + onConsoleMessage: (ConsoleMessage) -> Unit, requestPermissions: (Array, RequestPermissionCallback) -> Unit, modifier: Modifier = Modifier, ) { @@ -108,6 +108,7 @@ internal fun CallScreenView( val callback: RequestPermissionCallback = { request.grant(it) } requestPermissions(androidPermissions.toTypedArray(), callback) }, + onConsoleMessage = onConsoleMessage, onCreateWebView = { webView -> webView.addBackHandler(onBackPressed = ::handleBack) val interceptor = WebViewWidgetMessageInterceptor( @@ -174,6 +175,7 @@ private fun CallWebView( url: AsyncData, userAgent: String, onPermissionsRequest: (PermissionRequest) -> Unit, + onConsoleMessage: (ConsoleMessage) -> Unit, onCreateWebView: (WebView) -> Unit, onDestroyWebView: (WebView) -> Unit, modifier: Modifier = Modifier, @@ -188,7 +190,11 @@ private fun CallWebView( factory = { context -> WebView(context).apply { onCreateWebView(this) - setup(userAgent, onPermissionsRequest) + setup( + userAgent = userAgent, + onPermissionsRequested = onPermissionsRequest, + onConsoleMessage = onConsoleMessage, + ) } }, update = { webView -> @@ -208,6 +214,7 @@ private fun CallWebView( private fun WebView.setup( userAgent: String, onPermissionsRequested: (PermissionRequest) -> Unit, + onConsoleMessage: (ConsoleMessage) -> Unit, ) { layoutParams = ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, @@ -232,35 +239,7 @@ private fun WebView.setup( } override fun onConsoleMessage(consoleMessage: ConsoleMessage): Boolean { - val priority = when (consoleMessage.messageLevel()) { - ConsoleMessage.MessageLevel.ERROR -> Log.ERROR - ConsoleMessage.MessageLevel.WARNING -> Log.WARN - else -> Log.DEBUG - } - - val message = buildString { - append(consoleMessage.sourceId()) - append(":") - append(consoleMessage.lineNumber()) - append(" ") - append(consoleMessage.message()) - } - - if (message.contains("password=")) { - // Avoid logging any messages that contain "password" to prevent leaking sensitive information - return true - } - - Timber.tag("WebView").log( - priority = priority, - message = buildString { - append(consoleMessage.sourceId()) - append(":") - append(consoleMessage.lineNumber()) - append(" ") - append(consoleMessage.message()) - }, - ) + onConsoleMessage(consoleMessage) return true } } @@ -286,6 +265,7 @@ internal fun CallScreenViewPreview( state = state, pipState = aPictureInPictureState(), requestPermissions = { _, _ -> }, + onConsoleMessage = {}, ) } diff --git a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt index bf210b0a42..ae04606d29 100644 --- a/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt +++ b/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/ui/ElementCallActivity.kt @@ -42,6 +42,7 @@ import io.element.android.features.call.impl.pip.PipView import io.element.android.features.call.impl.services.CallForegroundService import io.element.android.features.call.impl.utils.CallIntentDataParser import io.element.android.features.enterprise.api.EnterpriseService +import io.element.android.libraries.androidutils.browser.ConsoleMessageLogger import io.element.android.libraries.architecture.Presenter import io.element.android.libraries.architecture.bindings import io.element.android.libraries.audio.api.AudioFocus @@ -65,6 +66,7 @@ class ElementCallActivity : @Inject lateinit var pictureInPicturePresenter: PictureInPicturePresenter @Inject lateinit var buildMeta: BuildMeta @Inject lateinit var audioFocus: AudioFocus + @Inject lateinit var consoleMessageLogger: ConsoleMessageLogger private lateinit var presenter: Presenter @@ -119,6 +121,9 @@ class ElementCallActivity : CallScreenView( state = state, pipState = pipState, + onConsoleMessage = { + consoleMessageLogger.log("ElementCall", it) + }, requestPermissions = { permissions, callback -> requestPermissionCallback = callback requestPermissionsLauncher.launch(permissions) diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/browser/ConsoleMessageLogger.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/browser/ConsoleMessageLogger.kt new file mode 100644 index 0000000000..3c3cf24ebc --- /dev/null +++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/browser/ConsoleMessageLogger.kt @@ -0,0 +1,61 @@ +/* + * Copyright 2025 New Vector Ltd. + * + * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial + * Please see LICENSE files in the repository root for full details. + */ + +package io.element.android.libraries.androidutils.browser + +import android.util.Log +import android.webkit.ConsoleMessage +import dev.zacsweers.metro.AppScope +import dev.zacsweers.metro.ContributesBinding +import dev.zacsweers.metro.Inject +import timber.log.Timber + +interface ConsoleMessageLogger { + fun log( + tag: String, + consoleMessage: ConsoleMessage, + ) +} + +@ContributesBinding(AppScope::class) +@Inject +class DefaultConsoleMessageLogger : ConsoleMessageLogger { + override fun log( + tag: String, + consoleMessage: ConsoleMessage, + ) { + val priority = when (consoleMessage.messageLevel()) { + ConsoleMessage.MessageLevel.ERROR -> Log.ERROR + ConsoleMessage.MessageLevel.WARNING -> Log.WARN + else -> Log.DEBUG + } + + val message = buildString { + append(consoleMessage.sourceId()) + append(":") + append(consoleMessage.lineNumber()) + append(" ") + append(consoleMessage.message()) + } + + // Avoid logging any messages that contain "password" to prevent leaking sensitive information + if (message.contains("password=")) { + return + } + + Timber.tag(tag).log( + priority = priority, + message = buildString { + append(consoleMessage.sourceId()) + append(":") + append(consoleMessage.lineNumber()) + append(" ") + append(consoleMessage.message()) + }, + ) + } +}