Better SSL error handling in WebViewActivity (#2535)

- Use unique tags to allow identifying which function receives an error
 - Actually use the onReceivedSslError callback error
 - Also show SSL errors in the external auth callback
This commit is contained in:
Joris Pelgröm 2022-05-23 23:39:26 +02:00 committed by GitHub
parent a06f96fd4d
commit def3b3081f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 9 deletions

View file

@ -270,7 +270,7 @@ class WebViewActivity : BaseActivity(), io.homeassistant.companion.android.webvi
description: String?,
failingUrl: String?
) {
Log.e(TAG, "onReceivedHttpError: errorCode: $errorCode url:$failingUrl")
Log.e(TAG, "onReceivedError: errorCode: $errorCode url:$failingUrl")
if (failingUrl == loadedUrl) {
showError()
}
@ -323,8 +323,12 @@ class WebViewActivity : BaseActivity(), io.homeassistant.companion.android.webvi
handler: SslErrorHandler?,
error: SslError?
) {
Log.e(TAG, "onReceivedHttpError: $error")
showError()
Log.e(TAG, "onReceivedSslError: $error")
showError(
io.homeassistant.companion.android.webview.WebView.ErrorType.SSL,
error,
null
)
}
override fun onLoadResource(
@ -517,6 +521,7 @@ class WebViewActivity : BaseActivity(), io.homeassistant.companion.android.webvi
fun getExternalAuth(payload: String) {
JSONObject(payload).let {
presenter.onGetExternalAuth(
this@WebViewActivity,
it.getString("callback"),
it.has("force") && it.getBoolean("force")
)

View file

@ -1,10 +1,12 @@
package io.homeassistant.companion.android.webview
import android.content.Context
interface WebViewPresenter {
fun onViewReady(path: String?)
fun onGetExternalAuth(callback: String, force: Boolean)
fun onGetExternalAuth(context: Context, callback: String, force: Boolean)
fun checkSecurityVersion()

View file

@ -17,10 +17,14 @@ import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import java.net.SocketTimeoutException
import java.net.URL
import java.util.regex.Matcher
import java.util.regex.Pattern
import javax.inject.Inject
import javax.net.ssl.SSLException
import javax.net.ssl.SSLHandshakeException
import io.homeassistant.companion.android.common.R as commonR
class WebViewPresenterImpl @Inject constructor(
@ActivityContext context: Context,
@ -89,18 +93,26 @@ class WebViewPresenterImpl @Inject constructor(
}
}
override fun onGetExternalAuth(callback: String, force: Boolean) {
override fun onGetExternalAuth(context: Context, callback: String, force: Boolean) {
mainScope.launch {
try {
view.setExternalAuth("$callback(true, ${authenticationUseCase.retrieveExternalAuthentication(force)})")
} catch (e: Exception) {
Log.e(TAG, "Unable to retrieve external auth", e)
val anonymousSession = authenticationUseCase.getSessionState() == SessionState.ANONYMOUS
view.setExternalAuth("$callback(false)")
view.showError(
if (authenticationUseCase.getSessionState() == SessionState.ANONYMOUS)
WebView.ErrorType.AUTHENTICATION
else
WebView.ErrorType.TIMEOUT
errorType = when {
anonymousSession -> WebView.ErrorType.AUTHENTICATION
e is SSLException || (e is SocketTimeoutException && e.suppressed.any { it is SSLException }) -> WebView.ErrorType.SSL
else -> WebView.ErrorType.TIMEOUT
},
description = when {
anonymousSession -> null
e is SSLHandshakeException || (e is SocketTimeoutException && e.suppressed.any { it is SSLHandshakeException }) -> context.getString(commonR.string.webview_error_FAILED_SSL_HANDSHAKE)
e is SSLException || (e is SocketTimeoutException && e.suppressed.any { it is SSLException }) -> context.getString(commonR.string.webview_error_SSL_INVALID)
else -> null
}
)
}
}