-
Notifications
You must be signed in to change notification settings - Fork 110
fix(webview): surface main-frame load failures in the in-app browser #61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,18 @@ | ||
| package com.bernaferrari.changedetection.addedit | ||
|
|
||
| import android.graphics.Bitmap | ||
| import android.os.Build | ||
| import android.os.Bundle | ||
| import android.text.Editable | ||
| import android.view.KeyEvent | ||
| import android.view.LayoutInflater | ||
| import android.view.View | ||
| import android.view.ViewGroup | ||
| import android.webkit.WebResourceError | ||
| import android.webkit.WebResourceRequest | ||
| import android.webkit.WebView | ||
| import android.webkit.WebViewClient | ||
| import android.widget.Toast | ||
| import androidx.core.view.isVisible | ||
| import androidx.lifecycle.ViewModelProviders | ||
| import androidx.navigation.findNavController | ||
|
|
@@ -60,6 +64,29 @@ class WebViewFragment : ScopedFragment() { | |
| progress?.visibility = View.GONE | ||
| super.onPageFinished(view, url) | ||
| } | ||
|
|
||
| override fun onReceivedError( | ||
| view: WebView?, | ||
| request: WebResourceRequest?, | ||
| error: WebResourceError? | ||
| ) { | ||
| super.onReceivedError(view, request, error) | ||
| // Only surface the main-frame failure, otherwise every blocked | ||
| // sub-resource would pop a toast | ||
| if (request?.isForMainFrame != true) return | ||
| progress?.visibility = View.GONE | ||
| val description = if (Build.VERSION.SDK_INT >= 23) { | ||
| error?.description?.toString().orEmpty() | ||
| } else { | ||
| "" | ||
| } | ||
| val message = if (description.isNotBlank()) { | ||
| getString(R.string.webview_load_failed_with_reason, description) | ||
| } else { | ||
| getString(R.string.webview_load_failed) | ||
| } | ||
| Toast.makeText(context, message, Toast.LENGTH_SHORT).show() | ||
| } | ||
|
Comment on lines
+68
to
+89
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: In Android WebView, error handling is managed through specific WebViewClient callbacks. Below is the behavior for the requested scenarios: Main-Frame DNS/Offline Failures These are considered resource loading errors and are handled by onReceivedError. - Callback: onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) [1][2]. - Behavior: This method is invoked when the WebView encounters an unrecoverable error, such as a DNS lookup failure (ERROR_HOST_LOOKUP), connection failure (ERROR_CONNECT), or when the device is offline [3][2]. It is called for any resource (e.g., iframes, images) [2]. To specifically target main-frame failures, you should check the isForMainFrame property of the WebResourceRequest [4]. HTTP 4xx/5xx Responses HTTP errors are handled by a separate callback introduced in API level 23. - Callback: onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) [1][5]. - Behavior: This is invoked when the server returns an HTTP status code >= 400 [1][4]. Like onReceivedError, this callback triggers for any resource, not just the main page [1][4]. You can use request.isForMainFrame to filter for main-frame errors [4]. Note that the server response body may not be available in the errorResponse parameter [1][4]. SSL Certificate Errors SSL errors are handled by onReceivedSslError. - Callback: onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) [1][3]. - Behavior: This is invoked only for recoverable SSL certificate errors [1][5]. The host application must explicitly call handler.cancel or handler.proceed to continue or stop the load [1][3]. For non-recoverable SSL errors (e.g., server fails the client), the WebView will instead call onReceivedError with the ERROR_FAILED_SSL_HANDSHAKE constant [1][5]. Official Documentation References - onReceivedError: https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedError(android.webkit.WebView,%20android.webkit.WebResourceRequest,%20android.webkit.WebResourceError) - onReceivedHttpError: https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedHttpError(android.webkit.WebView,%20android.webkit.WebResourceRequest,%20android.webkit.WebResourceResponse) - onReceivedSslError: https://developer.android.com/reference/android/webkit/WebViewClient#onReceivedSslError(android.webkit.WebView,%20android.webkit.SslErrorHandler,%20android.net.http.SslError) Citations:
Main-frame failure handling is incomplete for HTTP and SSL error paths. The current implementation only overrides 🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
| close.setOnClickListener { goPreviousFragment() } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: bernaferrari/ChangeDetection
Length of output: 152
🏁 Script executed:
Repository: bernaferrari/ChangeDetection
Length of output: 154
🏁 Script executed:
Repository: bernaferrari/ChangeDetection
Length of output: 1900
🏁 Script executed:
Repository: bernaferrari/ChangeDetection
Length of output: 4814
Guard nullable Fragment context before showing Toast.
Line 88 uses
contextdirectly in an async WebViewClient callback; if the Fragment is detached when the callback arrives, this will crash. Preferview?.context ?: return(or combine withcontext ?: return) beforeToast.makeText.Suggested patch
📝 Committable suggestion
🤖 Prompt for AI Agents