Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Expand Down Expand Up @@ -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()
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find and read the WebViewFragment.kt file
find . -name "WebViewFragment.kt" -type f

Repository: bernaferrari/ChangeDetection

Length of output: 152


🏁 Script executed:

#!/bin/bash
# Read the file around line 88 to see the actual context
if [ -f "app/src/main/java/com/bernaferrari/changedetection/addedit/WebViewFragment.kt" ]; then
  wc -l "app/src/main/java/com/bernaferrari/changedetection/addedit/WebViewFragment.kt"
fi

Repository: bernaferrari/ChangeDetection

Length of output: 154


🏁 Script executed:

#!/bin/bash
# Read the file with context around line 88
sed -n '60,110p' "app/src/main/java/com/bernaferrari/changedetection/addedit/WebViewFragment.kt"

Repository: bernaferrari/ChangeDetection

Length of output: 1900


🏁 Script executed:

#!/bin/bash
# Read the entire file to understand the class structure and callback
cat "app/src/main/java/com/bernaferrari/changedetection/addedit/WebViewFragment.kt"

Repository: bernaferrari/ChangeDetection

Length of output: 4814


Guard nullable Fragment context before showing Toast.

Line 88 uses context directly in an async WebViewClient callback; if the Fragment is detached when the callback arrives, this will crash. Prefer view?.context ?: return (or combine with context ?: return) before Toast.makeText.

Suggested patch
-                Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
+                val ctx = view?.context ?: return
+                Toast.makeText(ctx, message, Toast.LENGTH_SHORT).show()
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
val ctx = view?.context ?: return
Toast.makeText(ctx, message, Toast.LENGTH_SHORT).show()
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@app/src/main/java/com/bernaferrari/changedetection/addedit/WebViewFragment.kt`
at line 88, In WebViewFragment, the Toast call inside the async WebViewClient
callback uses the Fragment's nullable context directly (Toast.makeText(context,
...)); guard against the Fragment being detached by resolving a safe context
first (e.g., val safeCtx = view?.context ?: context ?: return) or check context
?: return before calling Toast.makeText, then use safeCtx when creating/showing
the Toast to avoid crashes when the callback runs after detach.

}
Comment on lines +68 to +89
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Android WebViewClient callback behavior: which callbacks are invoked for main-frame DNS/offline failures, HTTP 4xx/5xx responses, and SSL certificate errors? Please include official Android docs for onReceivedError, onReceivedHttpError, and onReceivedSslError.

💡 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 onReceivedError, which handles DNS/offline failures and non-recoverable SSL errors, but does not handle HTTP 4xx/5xx responses (onReceivedHttpError) or recoverable SSL certificate errors (onReceivedSslError). This leaves users without feedback when the server returns HTTP errors or when certificate validation fails. Both cases are explicitly listed in the PR objective and require separate callbacks to be implemented.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@app/src/main/java/com/bernaferrari/changedetection/addedit/WebViewFragment.kt`
around lines 68 - 89, The WebViewFragment currently only handles onReceivedError
(main-frame DNS/offline and non-recoverable SSL), but missing handling for HTTP
errors and recoverable SSL errors; implement overrides for
onReceivedHttpError(WebView, WebResourceRequest, WebResourceResponse) to detect
main-frame HTTP 4xx/5xx and show the same progress hide + toast logic (use
getString(R.string.webview_load_failed_with_reason) when response reason/status
available), and override onReceivedSslError(WebView, SslErrorHandler, SslError)
to show a user-facing message (hide progress, show appropriate toast using
getString(...) and include sslError.primaryError or message) and call
handler.cancel() to avoid proceeding on unrecoverable cert issues; reuse the
existing progress and message construction approach from onReceivedError so all
three callbacks provide consistent UX.

}

close.setOnClickListener { goPreviousFragment() }
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

<string name="yes">Yes</string>
<string name="no">No</string>
<string name="webview_load_failed">Page failed to load</string>
<string name="webview_load_failed_with_reason">Page failed to load: %1$s</string>

<string name="save">Save</string>
<string name="cancel">Cancel</string>
Expand Down