setting to enable screenshot protection

This commit is contained in:
Fabian Freund
2026-05-01 05:18:32 +02:00
parent e7ccd1cf89
commit 0f011351ff
14 changed files with 2347 additions and 3193 deletions
@@ -16,6 +16,7 @@ import android.os.Environment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager.LayoutParams.FLAG_SECURE
import android.widget.FrameLayout
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
@@ -34,6 +35,7 @@ import eu.weblibre.flutter_mozilla_components.integration.ReaderViewIntegration
import eu.weblibre.flutter_mozilla_components.activities.ExternalAppBrowserActivity
import eu.weblibre.flutter_mozilla_components.services.DownloadService
import io.flutter.Log
import mozilla.components.browser.state.selector.findCustomTabOrSelectedTab
import mozilla.components.browser.state.state.WebExtensionState
import mozilla.components.browser.thumbnails.BrowserThumbnails
import mozilla.components.concept.engine.EngineView
@@ -150,6 +152,18 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
private lateinit var requestSitePermissionsLauncher: ActivityResultLauncher<Array<String>>
private lateinit var requestPromptsPermissionsLauncher: ActivityResultLauncher<Array<String>>
private fun updateSecureWindowState() {
val tab = components.core.store.state.findCustomTabOrSelectedTab(sessionId)
val shouldSecure =
GlobalComponents.screenshotProtectionEnabled || tab?.content?.private == true
if (shouldSecure) {
requireActivity().window.addFlags(FLAG_SECURE)
} else {
requireActivity().window.clearFlags(FLAG_SECURE)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -268,6 +282,10 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
GlobalComponents.onPullToRefreshEnabledChanged = { enabled ->
_binding?.swipeToRefresh?.isEnabled = enabled
}
GlobalComponents.onScreenshotProtectionEnabledChanged = {
updateSecureWindowState()
}
updateSecureWindowState()
shareResourceFeature.set(
ShareResourceFeature(
@@ -461,6 +479,11 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
window = requireActivity().window,
store = components.core.store,
customTabId = sessionId,
isSecure = { session ->
session.content.private ||
GlobalComponents.screenshotProtectionEnabled
},
clearFlagOnStop = false,
),
owner = this,
view = binding.root,
@@ -663,6 +686,7 @@ abstract class BaseBrowserFragment : Fragment(), UserInteractionHandler, Activit
browserHandlingScrollFeature = null
GlobalComponents.onPullToRefreshEnabledChanged = null
GlobalComponents.onScreenshotProtectionEnabledChanged = null
val engineView = fragmentEngineView
engineView?.setActivityContext(null)
if (components.activeEngineView == engineView) {
@@ -75,6 +75,14 @@ object GlobalComponents {
var onPullToRefreshEnabledChanged: ((Boolean) -> Unit)? = null
var screenshotProtectionEnabled: Boolean = false
set(value) {
field = value
onScreenshotProtectionEnabledChanged?.invoke(value)
}
var onScreenshotProtectionEnabledChanged: ((Boolean) -> Unit)? = null
// Viewport events for keyboard visibility notifications
var viewportEvents: GeckoViewportEvents? = null
@@ -419,6 +419,10 @@ class GeckoEngineSettingsApiImpl : GeckoEngineSettingsApi {
GlobalComponents.pullToRefreshEnabled = enabled
}
override fun setScreenshotProtectionEnabled(enabled: Boolean) {
GlobalComponents.screenshotProtectionEnabled = enabled
}
override fun setAppLinksMode(mode: AppLinksMode) {
val context = components.profileApplicationContext
val prefKey = context.getString(R.string.pref_key_open_links_in_apps)
@@ -6752,6 +6752,7 @@ interface GeckoSyncApi {
interface GeckoEngineSettingsApi {
fun setDefaultSettings(settings: GeckoEngineSettings)
fun updateRuntimeSettings(settings: GeckoEngineSettings)
fun setScreenshotProtectionEnabled(enabled: Boolean)
fun setPullToRefreshEnabled(enabled: Boolean)
/**
* Sets the app links mode preference (stored in SharedPreferences).
@@ -6811,6 +6812,24 @@ interface GeckoEngineSettingsApi {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.flutter_mozilla_components.GeckoEngineSettingsApi.setScreenshotProtectionEnabled$separatedMessageChannelSuffix", codec)
if (api != null) {
channel.setMessageHandler { message, reply ->
val args = message as List<Any?>
val enabledArg = args[0] as Boolean
val wrapped: List<Any?> = try {
api.setScreenshotProtectionEnabled(enabledArg)
listOf(null)
} catch (exception: Throwable) {
GeckoPigeonUtils.wrapError(exception)
}
reply.reply(wrapped)
}
} else {
channel.setMessageHandler(null)
}
}
run {
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.flutter_mozilla_components.GeckoEngineSettingsApi.setPullToRefreshEnabled$separatedMessageChannelSuffix", codec)
if (api != null) {