Skip to content
Merged
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
Expand Up @@ -55,6 +55,7 @@ import coil3.SingletonImageLoader
import coil3.request.ImageRequest
import io.aatricks.novelscraper.data.model.*
import io.aatricks.novelscraper.ui.components.*
import io.aatricks.novelscraper.util.WebViewUtils
import io.aatricks.novelscraper.ui.viewmodel.LibraryViewModel
import io.aatricks.novelscraper.ui.viewmodel.ReaderViewModel
import kotlinx.coroutines.launch
Expand Down Expand Up @@ -302,17 +303,7 @@ private fun CloudflareDialog(
factory = { ctx ->
WebView(ctx).apply {
internalWebView = this
settings.apply {
javaScriptEnabled = true
domStorageEnabled = true
loadWithOverviewMode = true
useWideViewPort = true
builtInZoomControls = true
displayZoomControls = false
mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW
javaScriptCanOpenWindowsAutomatically = true
userAgentString = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}
WebViewUtils.configureCloudflareWebView(this)
webViewClient = object : WebViewClient() {
override fun onReceivedSslError(
view: WebView?,
Expand Down
22 changes: 22 additions & 0 deletions app/src/main/java/io/aatricks/novelscraper/util/WebViewUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.aatricks.novelscraper.util

import android.webkit.WebSettings
import android.webkit.WebView

object WebViewUtils {
fun configureCloudflareWebView(webView: WebView) {
webView.settings.apply {
javaScriptEnabled = true
domStorageEnabled = true
loadWithOverviewMode = true
useWideViewPort = true
builtInZoomControls = true
displayZoomControls = false
// SECURITY: Explicitly disallow mixed content (loading HTTP resources on HTTPS pages)
// to prevent Man-in-the-Middle (MitM) attacks.
mixedContentMode = WebSettings.MIXED_CONTENT_NEVER_ALLOW
javaScriptCanOpenWindowsAutomatically = true
userAgentString = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.aatricks.novelscraper.util

import android.webkit.WebSettings
import android.webkit.WebView
import org.junit.Test
import org.mockito.Mockito.*

class WebViewUtilsTest {
@Test
fun `configureCloudflareWebView sets secure mixed content mode`() {
val mockWebView = mock(WebView::class.java)
val mockSettings = mock(WebSettings::class.java)

// When asking for settings, return our mock settings
`when`(mockWebView.settings).thenReturn(mockSettings)

// Run the configuration
WebViewUtils.configureCloudflareWebView(mockWebView)

// Verify that mixed content is set to NEVER_ALLOW (Security Fix)
verify(mockSettings).mixedContentMode = WebSettings.MIXED_CONTENT_NEVER_ALLOW

// Verify other important settings
verify(mockSettings).javaScriptEnabled = true
verify(mockSettings).domStorageEnabled = true
}
}